cronを使わずにsystemd timer/serviceを作成する手順
Amazon Linuxを触ってみたら、慣れ親しんでいたCronが無いことに愕然としましたが、Cronを追加する方法はあるものの今後は、定期実行の仕組みとして cron の代わりに systemd timer が推奨とのことで。Cronを追加するのも何だか悔しいので、この記事では、毎日決まった時刻に任意のスクリプトを実行するための systemd service と systemd timer を作成する手順をまとめます。
実際のサーバ名、ユーザ名、バックアップ対象、実パスはダミーに置き換えています。ここでは例として、毎日0時に /usr/local/sbin/example-backup.sh を実行する構成にします。
前提
この記事では、次のような構成を想定します。
- OSはsystemdを利用しているLinux
- 定期実行したいスクリプトは作成済み
- root権限またはsudo権限がある
- cronは使わず、systemd timerで定期実行する
実行したいスクリプトの例は次のパスにあるものとします。
/usr/local/sbin/example-backup.sh
実行スクリプトの存在を確認する
まず、timerから呼び出すスクリプトが存在し、実行権限があることを確認します。
sudo ls -l /usr/local/sbin/example-backup.sh
実行権限がない場合は付与します。
sudo chmod 700 /usr/local/sbin/example-backup.sh
手動で実行できるかも確認しておくと安心です。
sudo /usr/local/sbin/example-backup.sh
serviceユニットを作成する
まず、実際に処理を実行する service ユニットを作成します。timerは時刻を管理し、serviceが実処理を担当します。
sudo tee /etc/systemd/system/example-backup.service >/dev/null <<'EOF'
[Unit]
Description=Run example backup
After=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/example-backup.sh
EOF
Type=oneshot は、バックアップや集計処理のように「実行して終了する」処理に向いています。
timerユニットを作成する
次に、毎日0時にserviceを起動する timer ユニットを作成します。
sudo tee /etc/systemd/system/example-backup.timer >/dev/null <<'EOF'
[Unit]
Description=Run example backup daily at midnight
[Timer]
OnCalendar=*-*-* 00:00:00
Persistent=true
Unit=example-backup.service
[Install]
WantedBy=timers.target
EOF
OnCalendar=*-*-* 00:00:00 は、毎日0時に実行する指定です。
Persistent=true を指定すると、サーバ停止中などで実行予定時刻を過ぎていた場合、次回起動時に未実行分を補完して実行できます。
systemdに設定を読み込ませる
ユニットファイルを作成したら、systemdに再読み込みさせます。
sudo systemctl daemon-reload
timerを有効化して開始する
timerを有効化し、すぐに開始します。
sudo systemctl enable --now example-backup.timer
enable により再起動後も有効になり、--now により現在の起動中セッションでもtimerが開始されます。
timerの状態を確認する
次回実行予定を確認します。
systemctl list-timers example-backup.timer --no-pager
設定内容を確認します。
systemctl cat example-backup.service
systemctl cat example-backup.timer
有効化状態を確認します。
systemctl is-enabled example-backup.timer
systemctl status example-backup.timer --no-pager
手動実行で動作確認する
timerの時刻を待たずに、serviceを手動実行して動作確認できます。
sudo systemctl start example-backup.service
実行ログを確認します。
sudo journalctl -u example-backup.service --no-pager
直近のログだけを見る場合は、次のようにします。
sudo journalctl -u example-backup.service -n 50 --no-pager
作成されるファイル
この手順で作成するsystemd関連ファイルは次の2つです。
/etc/systemd/system/example-backup.service/etc/systemd/system/example-backup.timer
実際の処理本体は、serviceの ExecStart に指定したスクリプトです。
ExecStart=/usr/local/sbin/example-backup.sh
よく使う確認コマンド
systemctl list-timers example-backup.timer --no-pager
systemctl cat example-backup.service
systemctl cat example-backup.timer
systemctl status example-backup.timer --no-pager
sudo systemctl start example-backup.service
sudo journalctl -u example-backup.service -n 50 --no-pager
停止・無効化する場合
timerを止める場合は次のコマンドを使います。
sudo systemctl disable --now example-backup.timer
ユニットファイル自体を削除する場合は、timerを止めてから削除し、systemdを再読み込みします。
sudo rm /etc/systemd/system/example-backup.timer
sudo rm /etc/systemd/system/example-backup.service
sudo systemctl daemon-reload
本番環境では、削除前にファイルをバックアップしておくと戻しやすくなります。
まとめ
systemd timerを使うと、cronを使わずに定期実行を管理できます。処理本体はserviceに分離し、実行時刻はtimerに持たせるため、状態確認やログ確認を systemctl と journalctl で一貫して扱えます。
バックアップ処理のように毎日決まった時刻に1回だけ実行したい処理では、Type=oneshot のserviceと OnCalendar のtimerを組み合わせる構成が扱いやすいです。
