自作のスクリプトやgithub等で入手したソフトについて、debパッケージで配布したい。
debパッケージ化する方法として、いくつか方法があるようだが、あまり手間をかけたくないので、
一番簡単そうな、dpkg-debを利用した手法にてパッケージを作成する
この備忘録では少々面倒ですが、tm16xx-displayのパッケージ化の記録を残します。
一般ユーザーで.debファイルを作成すると、配置されるファイルは権限が一般ユーザーとなってしまいます。
fakerootコマンドを利用すると、全てのファイルの権限がroot:rootに置き換わります。
しかし/var/log の下など、権限をroot:admにしたい場合があります。
その場合はfakerootを使わず、rootユーザーでdpkg-debをbuildすれば、各ファイルの権限はファイルroot:rootに置き換わらず、各ファイルの権限が維持されます。
一般ユーザーでfakerootを利用して.debファイルを作成したいが、
指定した権限(root:adm等)にしたい場合にはファイル名をpostinstとしたファイル内に、
chown コマンド等で変更するように、スクリプトを書く必要があります。
パーミッションについては、fakerootでbuildしても、そのまま引き継がれます。
手動で組み込む際は下記の流れとなりますが、これらの操作を自動的に実行されるようにスクリプトを書いたり、仕込みを行う必要があります。
1. tm16xx-display をビルド時にカーネルモジュール(.koファイル)をビルドします。 2. ビルドしたファイルをインストールします。 配置するファイルには、カーネルモジュールファイル(.ko)ファイルが含まれます。 3. /boot/armbianEnv.txt に、「user_overlays=tm16xx」を追加します。 再起動後、カーネルモジュールを自動ロードする為です。 4. OSを再起動します 5. 再起動後に以下のコマンドを実行し、サービスとして立ち上げます。 depmod -a modprobe -a ledtrig_timer ledtrig_netdev tm16xx systemctl daemon-reload systemctl enable display.service systemctl restart display.service
今回のパッケージ作成では、.debファイル作成時に
という2点を考慮させる必要があり、
[方法1]
少し乱暴ですが、インストール中のエラー処理を考えずにdebianパッケージのインストールを全て完了させ、 インストール完了後に、「OSを再起動するしてください」のメッセージ出す。 個人で運用していているサーバーやクライアントに対して、インストールするのであれば許容範囲でしょう。
[方法2]
要所要所にエラー処理を組み込み、OS再起動後に1回だけ自動実行されるようにスクリプトを組み込む 1度だけ自動実行されたスクリプトは最後に削除したり、安易に触らない場所やhidden化するなどの考慮をしておきたい。
今回は[方法2]でやってみようと思う
(1) tm16xx-display でインストールされるファイルが何かを調べる
Makefileを読んだり、“make -n install” で出力ログをみたりするのも良い。
-パーミッション-
※ 上記と異なる場合は、補足しています、
/ |-- boot | `-- overlay-user | `-- tm16xx.dtbo |-- lib | |-- modules | | `-- 6.7.12-edge-sunxi64 | | `-- updates | | `-- tm16xx.ko | `-- systemd | `-- system | `-- display.service `-- usr `-- sbin |-- display-service (0755) `-- display-utils (0755)
(2) debパッケージ作成の為のファイル構造
ワークディレクトリを作り、配下に上記と同じディレクトリ構造にします。
また、ワークディレクトリ配下に“DEBIAN” ディレクトリ(大文字)を作ります。
DEBIANディレクトリに、インストールする為の設定ファイルやスクリプトを置きます。
最終形がこちら
/home `-- develop |-- tm16xx-display_kernel6.7.12 |-- DEBIAN | |-- control | |-- md5sums | |-- postinst (0755) | |-- postrm (0755) | |-- preinst (0755) | `-- prerm (0755) |-- boot | `-- overlay-user | `-- tm16xx.dtbo |-- lib | |-- modules | | `-- 6.7.12-edge-sunxi64 | | `-- updates | | `-- tm16xx.ko | `-- systemd | `-- system | `-- display.service `-- usr `-- sbin |-- display-service (0755) `-- display-utils (0755)
(3) DEBIANディレクトリのファイル
control | パッケージに関連する情報を記述する | 必須 |
md5sums | インストールされる(DEBIANディレクトリを除く)各ファイルのmd5sumを列挙 | 必須 |
preinst | インストールされる(ファイルが配置される)前に、preinstファイルが実行される | オプション |
prerm | アンインストールされる(ファイルが削除される)前に、prermファイルが実行される | オプション |
postinst | インストールされた(ファイルが配置された)後に、postinstファイルが実行される | オプション |
postrm | アンインストールされた(ファイルが削除された)後に、postrmファイルが実行される | オプション |
preinst/prerm/postinst/postrm は、スクリプトファイルで実行ファイル(x)として設定する
これらのファイルはオプションであり必須ではない。 実行したいスクリプトを実行したいタイミングのファイル名さえ存在しておけば良い。
(3-1) control ファイル (ある意味一番手間がかかる)
という事で、最初のうちは必須フィールド
Package/Version/Architecture/Maintainer/Description のみ埋めておけば、パッケージ作成はできる。
https://www.debian.or.jp/community/devel/debian-policy-ja/policy.ja.html/ch-controlfields.html
5.3 バイナリパッケージコントロールファイル の項を参照
control ファイル
Package: tm16xx-display Version: 0.0.0-1~6.7.12 Source: tm16xx-display Architecture: arm64 Maintainer: foo-bar <foo-bar@example.jp> Installed-Size: 96 Section: utils Priority: extra Depends: linux-image-edge-sunxi64 (= 24.5.0-trunk) Description: Linux kernel driver for auxiliary displays based on led controllers such as tm16xx family and alike . jefflessard: tm16xx-display (branch: main) https://github.com/jefflessard/tm16xx-display . NickAlilovic: build (branch: main) https://github.com/NickAlilovic/build.git . == armbian-release == BOARD_NAME: Transpeed 8k618-t BOARDFAMILY: sun50iw9 BUILD_REPOSITORY_COMMIT: 74d622f5b LINUXFAMILY: sunxi64 ARCH: arm64 VENDOR: Armbian-unofficial VERSION: 24.5.0-trunk BRANCH: edge KernelVersion: 6.7.12-edge-sunxi64
(3-2) md5sums ファイル
ee5c0b5be58a1999e3f1caa5bceb6df3 ./boot/overlay-user/tm16xx.dtbo da333ff46de6f56b1ae03c477ac610bb ./lib/systemd/system/display.service 948ce985e4913c0d79423c439f033771 ./lib/modules/6.7.12-edge-sunxi64/updates/tm16xx.ko 03d7836a6bb09f6b8fbb85518128de15 ./usr/sbin/display-utils 0316206df3dac79db549da4995369346 ./usr/sbin/display-service
(3-3) preinst/prerm/postinst/postrm ファイル
スクリプトを書く言語だが、配布先の端末がどの言語をインストールされているか不明な状態である。
私としてはperlが一番書きやすいし、debianの最小インストールでもperlはインストールされているだろう。
しかしながら、必要なperlモジュールでも導入されているかまでは不明である為、使用するなら依存関係をcontrolファイルに記述して、インストールさせる必要がある。
必ず入っているのはshell系。特に bashは簡易計算も外部コマンド不要だったりするのでbashで書けるに越した事はない。
preinst ファイル
#!/usr/bin/env bash set -e PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin ARMBIAN_ENV=/boot/armbianEnv.txt # ARMBIAN_ENV.txt 存在確認 if [[ ! -f $ARMBIAN_ENV ]]; then echo "$ARMBIAN_ENV が存在しません。OSがarmbianではない可能性がある為、処理を中止します。" exit 1; fi exit 0
postinst ファイル
#!/usr/bin/env bash set -e FLG=0 PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin ARMBIAN_ENV=/boot/armbianEnv.txt SYSTEMD_FILE=/etc/systemd/system/tm16xx-firstboot.service ONETIME_FILE=/var/tmp/tm16xx-firstboot.sh # dtbo 追加処理 if [[ -f $ARMBIAN_ENV ]]; then LINE=$(grep "user_overlays" $ARMBIAN_ENV) if [[ $? -eq 0 ]];then KEY=$(echo $LINE | awk -F '=' '{print $2}') for i in $KEY do if [[ $i == 'tm16xx' ]]; then FLG=1 fi done if [[ $FLG -eq 0 ]]; then cp -bp $ARMBIAN_ENV ${ARMBIAN_ENV}.bak sed -i "s/$LINE/$LINE tm16xx/" $ARMBIAN_ENV fi else cp -bp $ARMBIAN_ENV ${ARMBIAN_ENV}.bak echo "user_overlays=tm16xx" >> $ARMBIAN_ENV fi else echo "$ARMBIAN_ENV が存在しません。インストール前チェックとの齟齬が発生しました。" echo "処理を中断します。" exit 1; fi # dtboをLoadさせる為に再起動する必要がある。その後の後続処理は、ワンタイムスクリプト処理を施す cat << EOS > $ONETIME_FILE #!/usr/bin/env bash set -e PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin depmod -a modprobe -a ledtrig_timer ledtrig_netdev tm16xx systemctl daemon-reload systemctl enable display.service systemctl restart display.service rm -f $SYSTEMD_FILE rm -f $ONETIME_FILE EOS chmod 0755 $ONETIME_FILE cat <<EOS > $SYSTEMD_FILE [Unit] Description=tm16xx dtbo call (reboot) DefaultDependencies=no After=local-fs.targe [Service] Type=oneshot ExecStart=$ONETIME_FILE Restart=no RemainAfterExit=no EOS # 再起動通知処理 echo "インストールを続行させる為には、再起動が必要です。" read -p "再起動を実行しても良いですか? (y/N) " res if [[ $res == 'y' ]] || [[ $res == 'Y' ]] ; then shutdown -r now exit 0 fi echo "再起動は中止されました。" echo "準備が整いましたら、再起動を実施してください。" echo "再起動後に後続処理が実行されます"
prerm ファイル
#!/usr/bin/env bash set -e PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin lsmod | grep -q tm16xx if [[ $? -eq 0 ]]; then systemctl stop display.service systemctl disable display.service rmmod tm16xx fi
postrm ファイル
#!/usr/bin/env bash set -e PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin COUNT=0 FLG=0 ARMBIAN_ENV=/boot/armbianEnv.txt systemctl daemon-reload if [[ -f $ARMBIAN_ENV ]]; then LINE=$(grep "user_overlays" $ARMBIAN_ENV) if [[ $? -eq 0 ]];then KEY=$(echo $LINE | awk -F '=' '{print $2}') for i in $KEY do ((COUNT = COUNT + 1)) if [[ $i == 'tm16xx' ]]; then FLG=1 fi done if [[ $FLG -eq 1 ]]; then cp -bp $ARMBIAN_ENV ${ARMBIAN_ENV}.bak if [[ $COUNT -eq 1 ]]; then grep -v $LINE ${ARMBIAN_ENV}.bak > $ARMBIAN_ENV else CHG=$(echo $LINE | sed -e "s/tm16xx//" | sed -e "s/= /=/" | sed -e "s/ $//") sed -i "s/$LINE/$CHG/" $ARMBIAN_ENV fi fi fi fi
ファイルが揃ったら、パッケージング化(deb)ファイルを作成する。
develop@repo11:~$ cd develop@repo11:~$ fakeroot dpkg-deb --build tm16xx-display_kernel6.7.12 . dpkg-deb: building package 'tm16xx-display' in './tm16xx-display_0.0.0-1~6.7.12_arm64.deb'. develop@repo11:~$ ls -l -rw-r--r-- 1 dev dev 12676 5月 30 04:10 tm16xx-display_0.0.0-1~6.7.12_arm64.deb drwxr-xr-x 6 dev dev 4096 5月 18 08:17 tm16xx-display_kernel6.7.12
以上で、tm16xx-display_0.0.0-1~6.7.12_arm64.deb パッケージの作成が完了
詰まるところ、ファイルさえ規定通りに準備出来れば、dpkg-deb –build の1コマンドで作成出来る