はじめに
以前から話題になっているcron
の代替になるものとして有名な systemd-timer
について調べたので覚書をする。
環境
AWS EC2 (t4g.nano) - AmazonLinux2023
前提
今回、systemd-timer
の検証用にAWS EC2にインスタンスを作成したが、UTC
のままタイムゾーンを変更していないことに注意。
systemd-timer有効なもの
loaded
されており、active
なものを出力する際は、systemctl -t timer
で確認をする。
systemctl -t timer
[ec2-user@ip-172-31-26-155 ~]$ systemctl -t timer
UNIT LOAD ACTIVE SUB DESCRIPTION
fstrim.timer loaded active waiting Discard unused blocks once a week
logrotate.timer loaded active waiting Daily rotation of log files
refresh-policy-routes@ens5.timer loaded active waiting refresh-policy-routes@ens5.timer
sysstat-collect.timer loaded active waiting Run system activity accounting tool every 10 minutes
sysstat-summary.timer loaded active waiting Generate summary of yesterday's process accounting
systemd-tmpfiles-clean.timer loaded active waiting Daily Cleanup of Temporary Directories
update-motd.timer loaded active waiting Timer for Dynamically Generate Message Of The Day
LOAD = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB = The low-level unit activation state, values depend on unit type.
7 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.
--all
オプションをつけると inactive
なものも確認できる。
[ec2-user@ip-172-31-26-155 ~]$ systemctl -t timer --all
UNIT LOAD ACTIVE SUB DESCRIPTION
fstrim.timer loaded active waiting Discard unused blocks once a week
logrotate.timer loaded active waiting Daily rotation of log files
refresh-policy-routes@ens5.timer loaded active waiting refresh-policy-routes@ens5.timer
sysstat-collect.timer loaded active waiting Run system activity accounting tool every 10 minutes
sysstat-summary.timer loaded active waiting Generate summary of yesterday's process accounting
systemd-tmpfiles-clean.timer loaded active waiting Daily Cleanup of Temporary Directories
update-motd.timer loaded active waiting Timer for Dynamically Generate Message Of The Day
LOAD = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB = The low-level unit activation state, values depend on unit type.
7 loaded units listed.
To show all installed unit files use 'systemctl list-unit-files'.
スケジュールの確認
systemctl list-timers
で次の実行時刻を知ることができる。
※NEXT
の列が次回実行時刻
[ec2-user@ip-172-31-26-155 ~]$ systemctl list-timers
NEXT LEFT LAST PASSED UNIT ACTIVATES
Sun 2024-06-09 06:30:00 UTC 4min 17s left - - sysstat-collect.timer sysstat-collect.service
Sun 2024-06-09 06:38:42 UTC 12min left - - systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service
Sun 2024-06-09 21:25:02 UTC 14h left - - update-motd.timer update-motd.service
Mon 2024-06-10 00:00:00 UTC 17h left - - logrotate.timer logrotate.service
Mon 2024-06-10 00:07:00 UTC 17h left - - sysstat-summary.timer sysstat-summary.service
Mon 2024-06-10 00:57:15 UTC 18h left - - fstrim.timer fstrim.service
- - Sun 2024-06-09 06:25:42 UTC 57ms ago refresh-policy-routes@ens5.timer refresh-policy-routes@ens5.service
7 timers listed.
Pass --all to see loaded but inactive timers, too.
systemd-timerで定期的にジョブを実行させる
systemd-timer
は主に2つのユニットファイルで構成されており、
サービスユニットファイル (.service)
実際に実行されるコマンドやスクリプトを定義タイマーユニットファイル (.timer)
サービスユニットの実行タイミングを定義
上記の2つを作成することで、スケジュールに沿ったジョブ実行が可能となる。
サービスユニットファイルを作成する
/etc/systemd/system/
以下に、例としてmy-task.service
を作成する。
sudo vim /etc/systemd/system/my-task.service
[Unit]
Description=My Task
[Service]
Type=oneshot
ExecStart=/usr/local/sh/hello.sh
sudo mkdir -p /usr/local/sh/
sudo touch /usr/local/sh/hello.sh
sudo chmod +x /usr/local/sh/hello.sh
sudo vim /usr/local/sh/hello.sh
#!/bin/sh
echo [$(date '+%Y/%m/%d %H:%M:%S')] "Hello,World" >> /tmp/hello
タイマーユニットファイルの作成
/etc/systemd/system/
以下に、例としてmy-task.timer
を作成する。
sudo vim /etc/systemd/system/my-task.timer
[Unit]
Description=Run My Task every 5 minutes
[Timer]
OnCalendar=*-*-* *:0/5:00
[Install]
WantedBy=timers.target
Persistent=true
をつけると、起動時間を過ぎて、何らかの理由でジョブを起動できなかった場合に、即実行されるようになる。
※cron
の anacron
と同じですね。
タイマーの設定確認
OnCalendar の日時の指定方法は systemd-analyze ユーティリティの calendar オプションを使用することでテストすることができます。タイマーユニットで使用したときに次に実行される日時も確認できます。例えば、systemd-analyze calendar weekly や systemd-analyze calendar “Mon,Tue --01..04 12:00:00” のようにコマンドを実行することでテストできます。
と ArchWikiに書いてあるので、設定内容はこれで良いかをテストする。
systemd-analyze calendar "*-*-* 00:00:00"
↓
[ec2-user@ip-172-31-26-155 ~]$ systemd-analyze calendar "*-*-* 00:00:00"
Normalized form: *-*-* 00:00:00
Next elapse: Mon 2024-06-10 00:00:00 UTC
From now: 17h left
次回実行日まで丁寧に教えてくれる。
OnCalendarの書式について
DayOfWeek Year-Month-Day Hour:Minute:Second
とのことなので、 5分毎に実行であれば、下記のように書く。
OnCalendar=*-*-* *:0/5:00
※秒単位で設定できるので、cron
より細かい時間単位で設定できる
↓
[ec2-user@ip-172-31-26-155 ~]$ date
Sun Jun 9 06:27:59 UTC 2024
[ec2-user@ip-172-31-26-155 ~]$ systemd-analyze calendar "*-*-* *:0/5:00"
Original form: *-*-* *:0/5:00
Normalized form: *-*-* *:00/5:00
Next elapse: Sun 2024-06-09 06:30:00 UTC
From now: 1min 48s left
タイマーの有効化と起動
下記で実行および、起動時に実行されるように設定する。
sudo systemctl enable my-task.timer
sudo systemctl start my-task.timer
[ec2-user@ip-172-31-26-155 ~]$ sudo systemctl enable my-task.timer
Created symlink /etc/systemd/system/timers.target.wants/my-task.timer → /etc/systemd/system/my-task.timer.
[ec2-user@ip-172-31-26-155 ~]$ sudo systemctl start my-task.timer
実行後のステータス確認
sudo systemctl status my-task.timer
↓
[ec2-user@ip-172-31-26-155 ~]$ sudo systemctl status my-task.timer
● my-task.timer - Run My Task every 5 minutes
Loaded: loaded (/etc/systemd/system/my-task.timer; enabled; preset: disabled)
Active: active (waiting) since Sun 2024-06-09 06:28:42 UTC; 10s ago
Trigger: Sun 2024-06-09 06:30:00 UTC; 1min 7s left
Triggers: ● my-task.service
Jun 09 06:28:42 ip-172-31-26-155.ap-northeast-1.compute.internal systemd[1]: Started my-task.timer - Run My Task every 5 minutes.
今回のスクリプトでは、 /tmp/hello
ファイルに追記されていくので、timer
の時刻を過ぎた後にファイルを確認して動作できているかを検証する。
初回実行前は、/tmp/hello
ができていないので一旦待つ。
tail -f /tmp/hello
[ec2-user@ip-172-31-26-155 ~]$ tail -f /tmp/hello
[2024/06/09 06:30:00] Hello,World
参考
- systemd/タイマー | ArchWiki
https://wiki.archlinux.jp/index.php/Systemd/%E3%82%BF%E3%82%A4%E3%83%9E%E3%83%BC
おわりに
systemd-timer
についてcron
の代替となると聞いていたので気になって試してみた。
今後、cron
より増えていくのかなと思うが、cron
の設定のシンプルさや浸透具合から考えるとまだまだかかりそう。
ただ、AmazonLinux2023ではcron
(chrony
)がデフォルトで入っていないので、systemd-timer
が使われる機会が多くなりそうかな…?