とあることをやりたくて調べていたら見つけたので記録。 APT 1.6からJSON-RPC2.0を使ったフック機能が追加されたらしい。 詳しくは以下のドキュメント。
フックスクリプトの準備
まず、フックスクリプトを用意する。 以下はテストコードから持ってきた。
#!/bin/bash while true; do read request <&$APT_HOOK_SOCKET read empty <&$APT_HOOK_SOCKET if echo "$request" | grep -q ".hello"; then echo "HOOK: HELLO" printf '{"jsonrpc": "2.0", "result": {"version": "0.1"}, "id": 0}\n\n' >&$APT_HOOK_SOCKET fi if echo "$request" | grep -q ".bye"; then echo "HOOK: BYE" exit 0; fi echo HOOK: request $request echo HOOK: empty $empty done
$APT_HOOK_SOCKET
経由でUnixドメインソケットのFDが渡されるので、それを参照して読み込む。
区切り文字が \n\n
なのでここでは2回readしている。
APTコマンドはHookスクリプトの始めて起動するときにはhelloパケット(org.debian.apt.hooks.hello
)を送ってくるので、規定のパケットを返す。
また、byeパケット(org.debian.apt.hooks.bye
)が来た時はそこで処理が終了する。
$request
に含まれるパラメータは前述のドキュメントに書いてあるので参考にしてほしい。
シェルスクリプトではJSONパースが面倒だが、LL言語を使えば簡単にパースできるはず。
フックの有効化
フックスクリプトができたらフックが有効になるように設定を行なう。 例えば以下のように設定する。
$ cat /etc/apt/apt.conf.d/99hook AptCli::Hooks::Install:: "/path/to/hook.sh"; AptCli::Hooks::Search:: "/path/to/hook.sh";
設定すると以下のようにフックが機能するようになる。
$ sudo apt install sl Reading package lists... Done Building dependency tree Reading state information... Done HOOK: HELLO HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1"]}} HOOK: empty HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.install.pre-prompt","params":{"command":"install","search-terms":["sl"],"unknown-packages":[],"packages":[{"id":23690,"name":"sl","architecture":"amd64","mode":"install","automatic":false,"versions":{"candidate":{"id":55553,"version":"3.03-17build2","architecture":"amd64","pin":500},"install":{"id":55553,"version":"3.03-17build2","architecture":"amd64","pin":500}}}]}} HOOK: empty HOOK: BYE The following NEW packages will be installed: sl 0 upgraded, 1 newly installed, 0 to remove and 26 not upgraded. Need to get 26.4 kB of archives. After this operation, 98.3 kB of additional disk space will be used. Get:1 http://archive.ubuntu.com/ubuntu bionic/universe amd64 sl amd64 3.03-17build2 [26.4 kB] Fetched 26.4 kB in 1s (32.9 kB/s) debconf: delaying package configuration, since apt-utils is not installed Selecting previously unselected package sl. (Reading database ... 4377 files and directories currently installed.) Preparing to unpack .../sl_3.03-17build2_amd64.deb ... Unpacking sl (3.03-17build2) ... Setting up sl (3.03-17build2) ... HOOK: HELLO HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.hello","id":0,"params":{"versions":["0.1"]}} HOOK: empty HOOK: request {"jsonrpc":"2.0","method":"org.debian.apt.hooks.install.post","params":{"command":"install","search-terms":["sl"],"unknown-packages":[],"packages":[{"id":23690,"name":"sl","architecture":"amd64","mode":"install","automatic":false,"versions":{"candidate":{"id":55553,"version":"3.03-17build2","architecture":"amd64","pin":500},"install":{"id":55553,"version":"3.03-17build2","architecture":"amd64","pin":500}}}]}} HOOK: empty HOOK: BYE
おわりに
APTコマンドの操作をJSON Hookで受け取れることがわかった。
同じようなことは Dpkg::Pre-Invoke
やDpkg::Post-Invoke
、dpkgコマンドの --pre-invoke
/ --post-invoke
などでできるのだがこれだとパッケージ情報が取れないので、パッケージ情報を取りたい場合はJSON Hookを利用することになる。
またこのフックはAPTコマンドだけで、aptdaemonやunattended-updatesみたいにlibapt-pkg(のPythonバインディング)を使っているようなコマンドではフックできないので注意。
フックできてもいいと思うんだけどなぁ。