サーバで定期的に実行するタスクを登録したいんだけど、別にずっと実行させたいわけではなく、数日間だけ定期実行されていれば良くて、再起動とかで消えてしまっても構わない。
というとき、いちいち crontab で設定したり、あるいは systemd.timer のユニットファイルを書いたりするのはとても面倒です。
systemd-run
を使えばコマンドだけでそういう設定がさっと作れます。
systemd-run --unit=oreore --on-active=1s --on-unit-active=30s echo "this is 30s timer."
これで 30 秒ごとに echo "this is 30s timer."
が実行されるようになります。
下記のコマンドで timer のユニットを一覧表示してみると、登録されていることがわかります。
systemctl list-timers
ユニットのステータスも見れます。
systemctl status oreore.timer
systemctl status oreore.service
実行ログも journalctl
で見れます(CentOS なら /var/log/messages
にも書かれているだろうけど)。
journalctl -f -u oreore.service
いらなくなったら timer ユニットを stop すれば止まります。
systemctl stop oreore.timer
systemd-run
の --unit=oreore
は省略可能で、省略すると run-99999
みたいな名前が自動的に付けられます。
余談その1(--on-XXX の指定)
最初 --on-unit-active=30s
だけで良いと思っていて「なぜか実行されない」とか思っていました。
--on-unit-active
つまり OnUnitActiveSec は、ユニットが最後に実行された時間からの相対、なので、1回も実行されていないと「最後に実行された時間」がないため、いつまでも実行されませんでした。
なので --on-active
つまり OnActiveSec も指定して、タイマーそのものが有効にされた後に1回実行してやる必要がありました。
そういえば普通に timer のユニットを書くときも OnBootSec は指定してましたけど、てっきり「起動直後はいろいろ忙しいからちょっと遅らせたい」ぐらいに考えていましたが、これも OnBootSec を書かなければ OnUnitActiveSec だけではいつまでも実行されません。
余談その2(sudo の代替)
root から別のユーザーとしてコマンドを実行したいときに sudo
だといろいろとつらみがあってその代替として gosu とかが使われたりしているようなんですけど systemd-run
でもアドホックに uid/gid 指定してコマンド実行できます。
systemd-run --scope -q --uid=apache pstree -aug $$
# bash,6243
# └─pstree,6333,apache -aug 6243
--scope
をつけると scope タイプのユニットとなり、デーモンにはならずに systemd-run
から直接実行されるようです。