Systemdはいまや多くのLinuxで標準的に使われているシステム管理用の仕組みです。
systemdの機能のひとつに、定期的・定時にコマンドを実行するtimerという機能があります。最近では、cronの代わりとしてsystemdのtimerを使う場面も多くなりました。
しかしcronに比べてsystemd.timerの情報は圧倒的に少なく、実装や移行の妨げになっていると感じます。
cronよりも最初の導入が少し厄介ですが、使いこなせると少ない労力で柔軟な設定が可能になります。最強に便利なツールであることは確かなので、ノートとして残しておきます。
Systemd timerとはなにか
timerはsystemdのもとで動く、定期実行の仕組みです。
設定はcronと同様、設定ファイルを配置してコマンドを実行するだけ。
systemdが導入されているLinux(ほぼすべてのディストリビューション)で利用できるため、一度使い勝手を覚えれば学習コストが抑えられます。
とはいえ、cronと比べると未だに情報が少ないため、こうして情報をメモしておきたくなりました。
Systemd timerコマンド一覧
※適宜sudoを付けて実行します
systemctl daemon-reload | 設定ファイルの再読み込み |
systemctl enable ****.timer | タイマーの有効化 |
systemctl disable ****.timer | タイマーの無効化 |
systemctl start ****.timer | タイマーの開始 |
systemctl stop ****.timer | タイマーの停止 |
systemctl status ****.timer | タイマーの状態確認 |
systemctl list-timers | 各タイマーの設定状態一覧 |
journalctl | ログの確認 |
Systemd timerを使って定期実行させる流れ(基本)
serviceファイル、timerファイルを作成する
/etc/systemd/system/ 以下に
****.service
****.timer
の2つのファイルをつくります。
ファイル名の部分は同じで、拡張子だけ異なります。
各ファイルにより設定される実行単位のことを"Unit"と呼びます。
serviceファイルの例 myscript.service
[Unit]
Description=My Script
[Service]
User=ec2-user
Group=ec2-user
Type=oneshot
WorkingDirectory=/home/ec2-user
ExecStart=/home/ec2-user/myscript.sh
補足解説
[Unit]セクション | 各Unitを起動する前後関係などを記述できる。ここでは説明文のみ。 |
[Service]セクション | サービスの設定をする。ここではシンプルに実行コマンドだけ指定している。 |
User | 実行ユーザー |
Type | サービスプロセスの起動完了を判定する方法。simpleは実行を継続するようなコマンドに、oneshotは一度だけ実行するようなコマンドに対応する。 |
WorkingDirectory | 作業ディレクトリ。実行コマンドをフルパスで指定する上記例のような場合、実は不要。 |
ExecStart | 実行したいコマンド。オプションも指定できる。 |
※他にもExecStop(サービス停止コマンド)やExecStopPost(サービス停止後に実行するコマンド)なども指定できる。こちらのサイトがわかりやすい。
User(実行ユーザー)がExecStartに指定したコマンドなどの実行権限を持っていることをよく確認しましょう。
timerファイルの例 myscript.timer
[Unit]
Description=My Script Timer
[Timer]
OnCalendar=Mon-Fri *:0/10:00
Persistent=true
[Install]
WantedBy=timers.target
補足解説
[Unit]セクション | 各Unitを起動する前後関係などを記述できる。ここでは説明文のみ。 |
[Timer]セクション | タイマーの設定をする。内容は下で解説。 |
[Install]セクション | systemctl enableなどで有効化するのに必要。他のUnitとややこしい依存・親子関係のあるシステムのとき、記述を追加すると便利な場合がある。基本的には定型文とみてOK。 |
Timerセクションの記述をざっくり解説
起動タイミングの指定方法はいろいろあり、かなり柔軟な設定ができます。
OnCalendar 日時形式で指定(リアルタイムタイマー)
上の記述例で用いている方法。
曜日 年-月-日 時-分-秒の形式で指定します。
*(ワイルドカード)や'...'(範囲指定)などが使える。
記述 | 意味 | 例 |
---|---|---|
, | 複数指定(IN) | Mon-Fri 10,12,14,16:0:00 (平日10時,12時,14時0分ちょうど) |
* | 任意の数値 | Mon-Fri *:0:00 (平日の毎時0分ちょうど) |
.. | 範囲指定 | Mon-Fri 9..12:0:00 (平日の9時から12時の0分ちょうど) |
/ | インクリメントする数 | Mon-Fri 9:0/10:00 (平日の9時0分~50分に10分おきに) |
厳しいことに、曜日の範囲表現が .. ではなく - にしないと動かない場合があります。
さらに詳細な例はArchLinuxにあります。
OnUnitActiveSec 最後にアクティブになったときからの経過時間で指定(モノトニックタイマー)
1s, 1m, 1h, 1d, 1w,…などで指定する。
OnCalendar=1m とすると1分おきに指定のUnitが実行されます。
設定を反映させる
$ sudo systemctl daemon-reload
設定ファイルを変更するたびに実行するようにしましょう(うまく実行されないときの原因その1)。
タイマーの有効化と実行
有効化
$ sudo systemctl enable myscript.timer
実行
$ sudo systemctl start myscript.timer
通常のサービスUnit(timerではない)と同様、timerもstartコマンドを実行しないと定時実行されません。よくミスやりがちな部分。(うまく実行されないときの原因その2)
timerが始動していることを確認
ステータスを確認
$ sudo systemctl status myscript.timer
myscript.timer - My Script Timer
Loaded: loaded (/etc/systemd/system/myscript.timer; enabled; vendor preset: disabled)
Active: active (waiting) since Mon 2021-04-26 03:24:32 UTC; 16min ago
Apr 26 03:24:32 ip-10-0-0-116.ap-northeast-1.compute.internal systemd[1]: Started My Script Timer.
Apr 26 03:24:32 ip-10-0-0-116.ap-northeast-1.compute.internal systemd[1]: Starting My Script Timer.
タイマーの一覧と設定状況
上で起動した****.timerの次回実行時刻、前回実行からの経過時間などが確認できます。
$ sudo systemctl list-timers
NEXT LEFT LAST PASSED UNIT
Mon 2021-04-26 03:42:00 UTC 14s left Mon 2021-04-26 03:41:45 UTC 10ms ago myscript.timer
Tue 2021-04-27 03:22:00 UTC 23h left Mon 2021-04-26 03:22:00 UTC 19min ago systemd-tmpfiles-clean.ti
2 timers listed.
実行ログの確認
systemdのログ全般は journalctl コマンドを使用します。
$ journalctl -e
Apr 26 03:34:52 ip-10-0-0-116.ap-northeast-1.compute.internal systemd[1]: Started My Script.
Apr 26 03:34:52 ip-10-0-0-116.ap-northeast-1.compute.internal systemd[1]: Starting My Script...
標準出力の内容などもここに出力されるので、実行確認がしやすいですね。
タイマーの無効化
無効化
$ sudo systemctl disable ****.timer
enableの反対でdisable にするだけなので覚えやすいですね。
まとめ
Linuxで標準的に使われているシステム管理ツールsystemdで、定期実行などの機能を提供するtimerの設定方法について解説しました。
cronと同様、使いこなせば幅広いシステムで自由自在にコマンドを自動実行できるので、うまく活用したいですね。