systemd timerを使った経緯
Gitにコミットしたテストコードを定刻で実行したい日のこと。
Github ActionsのWorkflowにscheduleトリガーイベントを定義して待つ
↓
設定した時刻になっても起動しない...?
↓
数十分後やっと起動
どうやらGitHub Docsを見ると、ワークフロー実行の負荷が高い期間中はスケジュールイベントが遅延する可能性があるとのこと。
テストの都合上、Amazon EC2(Amazon Linux 2023)をセルフホストランナーとして使用していたため、サーバ側から決まった時間にGithub ActionsのAPIを実行しワークフローを実行することにしました。
簡単なシェルスクリプトを作成し実行テスト後、cronで時刻起動の設定を...
-bash: crontab: command not found
cronがない!?
Amazon Linux 2023ではcronはデフォルトでインストールされておらず、代わりにsystemd timerが推奨されていました。(Amazon Linux 2023ユーザガイド)
ということでsystemd timerを使って定期実行の設定をしてみたので設定方法をまとめておきます。
systemd timerとは
cronと同じように定期実行できるsystemdの仕組みで、起動したいコマンドやスクリプトはserviceファイル、スケジュール設定をtimerファイルに記述し、systemctlコマンドで有効化などの操作を行います。
設定方法
1.serviceファイル作成
/etc/systemd/systemに/<機能名>.serviceという名前でファイルを作成します。
[Unit]
Description=sample
After=network.target
[Service]
ExecStart=/home/ec2-user/sample.sh
User=ec2-user
名前 | 説明 |
---|---|
Description | 説明(任意の文字列) |
After | 起動順序制御(network.target:インターネット接続後に実行) |
ExecStart | 実行したいコマンドやスクリプト |
User | 起動するユーザ名(ExecStartに記述した内容の実行権限が必要) |
2.timerファイル作成
serviceファイルと同じ/etc/systemd/system/に同じ機能名で<機能名>.timerという名前のファイルを作成します。
[Unit]
Description=test
After=network.target
[Timer]
OnCalendar=Mon..Fri *-*-* 00:00:00
[Install]
WantedBy=timers.target
名前 | 説明 |
---|---|
Description | 説明 |
After | 起動順序制御(network.target:インターネット接続後に実行) |
OnCalendar | スケジュール設定(例では月~金の0時に起動する設定) ※cron式とは異なるので注意 |
WantedBy | タイマー設定ではtimers.targetの指定が必要(これによりすべてのタイマーをグループ化するためのターゲットユニットに関連付けされる) |
OnCalendarに設定する書式はcron式とは異なり馴染みがないかもしれませんが、マニュアルをチェックして書式を作成し、テストツールで書式の確認が可能です。
マニュアル表示
$ man systemd.time
書式チェック(誤っている場合エラー、正しい場合は次の実行タイミング等が出力されます)
$ systemd-analyze calendar '確認したい書式'
3.サービス自動起動有効化
以下コマンドでサービスの自動起動を有効化します。
$ sudo systemctl enable <機能名>.timer
4.サービス起動
以下コマンドでサービスを起動します。
$ sudo systemctl start <機能名>.timer
5.起動確認
以下コマンドでtimer設定の一覧を表示します。
$ sudo systemctl list-timers
一覧表示される項目を見て想定通りに設定されていることを確認します。
項目 | 内容 |
---|---|
NEXT | 次回起動予定時刻 |
LEFT | 次回起動予定時刻までの残り時間 |
LAST | 前回起動時刻 |
PASSED | 前回実行時刻からの経過時間 |
UNIT | timerファイル名 |
ACTIVATES | serviceファイル名 |
6.設定変更時
serviceやtimerファイルを修正した場合は以下コマンドを実行し設定の反映が必要です。
$ sudo systemctl daemon-reload
まとめ
今回はただ決まった時刻に1つのシェルを実行するというシンプルな設定でのsystemd timer利用でした。
例として記載したserviceやtimerファイル記載のオプション以外に、実行ディレクトリの指定、何らかの原因で指定したタイミングに実行されなかった場合システム再起動後すぐに実行する、サーバ起動から一定時間経過後に一度実行するなど様々な設定ができるため、要件に応じて柔軟なカスタマイズができそうです。
サーバレスの流れやジョブ管理のマネージドサービスがたくさん登場していますが、Linux上で何かを定期実行したい場合もまだまだあるかと思いますので、また機会があれば違った使い方で活用してみようと思います。