chkbuild
を動かすのに chkbuild
自体を動かすのと git pull
は別権限で動かしたかったので、 systemd.exec(5)
の User=
では指定できなさそうだったので、 runuser
を使いました。
動作確認環境
- Debian GNU/Linux 10 (buster)
- systemd 241-7~deb10u4
su での失敗
service unit ファイルで ExecStartPre=/bin/su -l uucp -c pwd
と指定すると、以下のような感じでエラーになりました。 (uucp
ユーザーは適当に使っていないシステムユーザーを選んだだけで深い意味はありません。)
su[327]: (to uucp) root on none
su[327]: pam_unix(su-l:session): session opened for user uucp by (uid=0)
su[327]: pam_systemd(su-l:session): Runtime directory '/run/user/10' is not owned by UID 10, as it should.
su[327]: pam_systemd(su-l:session): Not setting $XDG_RUNTIME_DIR, as the directory is not in order.
エラーメッセージから推測すると session optional pam_systemd.so
で失敗しているようでした。 /etc/pam.d/common-session
で設定されていて、 /etc/pam.d/su-l
や /etc/pam.d/su
からは @include
で参照していました。
util-linux: /sbin/runuser
runuser
コマンドは util-linux
パッケージに入っていて、 Linux 依存のようでしたが、 systemd を使っている時点で Linux 依存なので気にせず使うことにしました。
パスワード認証などに対応していなくて、 root
権限から他の権限でコマンドを実行することに特化したコマンドのようです。 さらに細かく制御できる setpriv
というコマンドもあるようですが、今回はそこまで細かい制御は必要なかったので、使いませんでした。
/etc/pam.d/runuser
には pam_systemd.so
はなく、 /etc/pam.d/runuser-l
は -session optional pam_systemd.so
となっていました。
頭の -
は pam.d(5)
によると以下のような意味のようです。
If the type value from the list above is prepended with a - character the PAM library will not log to the system log if it is not possible to load the module because it is missing in the system. This can be useful especially for modules which are not always installed on the system and are not required for correct authentication and authorization of the login session.
ということで -l
は使わずに ExecStartPre=/sbin/runuser -u chkbuild-owner -- git pull origin master
という設定にしました。
chkbuild.service
最終的にテスト実行中の chkbuild.service
全体は以下のようになりました。
WorkingDirectory
は ExecStartPre
にも影響していたので、 sh -c "cd ... && git ...
にしていた cd
は止めて、 git
を直接使うようにしました。
[Unit]
Description=Run chkbuild
[Service]
Type=oneshot
PermissionsStartOnly=true
ExecStartPre=/sbin/runuser -u chkbuild-owner -- git pull origin master
ExecStart=/home/chkbuild/chkbuild/start-build
User=chkbuild
Group=chkbuild
WorkingDirectory=/home/chkbuild/chkbuild
PrivateTmp=true
本番環境用では start-build
の代わりに start-rubyci
にして、 EnvironmentFile=-/etc/systemd/system/chkbuild.env
も指定して別ファイルも組み合わせて、 環境変数 RUBYCI_NICKNAME
, AWS_ACCESS_KEY_ID
, AWS_SECRET_ACCESS_KEY
を指定しています。
chkbuild.timer
参考のため、 timer ユニットの設定ものせておくと、 今のところ実行間隔は、起動直後は 10 分待って、前回の終了後 1 時間あけて次を実行にしています。
[Unit]
Description=Run chkbuild
[Timer]
OnBootSec=10min
OnUnitInactiveSec=1h
Persistent=true
[Install]
WantedBy=timers.target
感想
他の環境では動いていた ExecStartPre=/bin/su - chkbuild-owner -c "cd /home/chkbuild/chkbuild && git pull origin master"
が動かなかったのをきっかけに、 runuser
コマンドや setpriv
コマンドを知ることができました。
今までは runit
パッケージの chpst
を使っていることもあったのですが、 追加でインストールせずに使える可能性が高い runuser
や setpriv
で足りるときは、 そちらを使うようにしたいと思いました。