🐧 Linux 総合学習プラットフォーム
自動化/定期実行 ・ 中級

systemd timer による定期実行

近年のディストリビューションでは cron の代わりに systemd の timer ユニットで定期実行を組む方法が広く使われます。timer は実行する処理を書いた service ユニットと、起動タイミングを書いた timer ユニットの2つで構成します。cron に比べてログが journal に統合され、依存関係の指定や、電源オフで逃した実行を後から補う Persistent 設定ができる点が利点です。systemctl list-timers で次回起動の予定を一覧できます。

定期実行は cron だけではない。近年の主要なディストリビューションでは、起動処理やサービス管理を一手に担う systemd が標準になっている。この systemd にも定期実行のしくみが備わっている。

cron の代わりに timer ユニットで定期処理を組む方法が、広く使われるようになった。考え方は cron と同じ「決めたタイミングで処理を動かす」だ。

💡
ポイントsystemd timer は cron に代わる定期実行のしくみ。ログの一元管理・依存関係・逃した実行の補完など、素の cron に無い利点を持つ。

違いは、systemd の世界に統合される点にある。これにより、ログの一元管理・依存関係の指定・逃した実行の補完といった、素の cron には無い利点が得られる。

新しくサーバを組むなら、定期実行は cron にするか systemd timer にするか、という選択肢を意識して持っておくと、設計の幅が広がる。

とくに、すでに他のサービスを systemd で管理している環境なら、定期処理も timer に寄せると運用の見え方がそろって扱いやすくなる。

🧩 なぜファイルを2つに分けるのか

systemd timer の最大の特徴は、「何を実行するか」と「いつ実行するか」を別々のユニットファイルに分けて書く点だ。

前者を service ユニット(拡張子 .service)、後者を timer ユニット(拡張子 .timer)と呼ぶ。この2つをペアで用意する。

backup.timerいつ実行するかOnCalendar=...backup.service何を実行するかExecStart=...時間が来たら同名を起動名前をそろえる(backup.timer ↔ backup.service)と timer が自動で service を起動

原則として同じ名前にそろえる。たとえば backup.service と backup.timer のように対応させると、timer 側が時間になったとき自動的に同名の service を起動してくれる。

これらのファイルは、システム全体用なら /etc/systemd/system/ に、ユーザ個人用なら ~/.config/systemd/user/ に置く。

service には実際の処理を ExecStart=/usr/local/bin/backup.sh のように書く。一度だけ走って終わる処理なので Type=oneshot を指定するのが定番だ。

なぜ2つに分けるのか。役割が2つのファイルに分かれることで、「実行内容の修正」と「スケジュールの変更」を独立して扱えるのが利点なのだ。

つまずきファイルを新規に置いたり書き換えたりした後は、systemctl daemon-reload を忘れると変更が反映されない。

ファイルを新規に置いたり書き換えたりした後は、systemctl daemon-reload で systemd に読み直させる必要がある点も覚えておこう。

🗓 スケジュールは、どう書けば読み返しやすいのか

timer ユニットでスケジュールを書く中心が OnCalendar= だ。書式は 曜日 年-月-日 時:分:秒 の並びで、省略した部分や * の部分は「毎」として扱われる。

たとえば OnCalendar=*-*-* 03:00:00 は毎日午前3時。OnCalendar=Mon..Fri 09:00 は平日の午前9時。OnCalendar=*-*-01 00:00:00 は毎月1日の午前0時を表す。

OnCalendar=Mon..Fri 09:00 ……平日の午前9時。曜日や日付を言葉に近い形で書けるのが OnCalendar の持ち味。

daily・weekly・monthly・hourly といった分かりやすい短縮名も使える。OnCalendar=daily は毎日午前0時、OnCalendar=hourly は毎時0分の意味になる。

複数の時刻を指定したいときは行を複数並べることもできる。

コツsystemd-analyze calendar \"Mon..Fri 09:00\" で式を検証できる。次に該当する日時まで表示されるので、登録前の確認に重宝する。

書いた式が狙いどおりに解釈されるかは、systemd-analyze calendar \"Mon..Fri 09:00\" のように検証できる。その式が次に該当する日時まで表示してくれるので、登録前の確認に重宝する。

cron 式が暗号的に見えるのに比べ、OnCalendar は曜日や日付が言葉に近く書ける。後から読み返したときに意図が分かりやすいのも利点だ。

🔁 一定間隔の繰り返しはどう書くか

cron の */15 のような「一定間隔の繰り返し」は、OnCalendar では書きにくい。これにはどうするか。

OnCalendar 以外に、基準時刻からの相対指定もある。OnBootSec= はシステム起動からの経過時間で、OnUnitActiveSec= はそのユニットが最後に動いてからの経過時間でトリガーする。

OnUnitActiveSec=15min ……前回実行から15分後に繰り返し動く。cron の */15 にあたる一定間隔の繰り返しを表現できる。

OnUnitActiveSec=15min なら「前回実行から15分後」に繰り返し動く。これで cron の */15 のような一定間隔の繰り返しを表現できる。

起動直後に1回動かしたうえで以後一定間隔で回す、といった組み合わせも、これらを併用すれば書ける。

🚀 ファイルを置いただけでは動かない

ユニットファイルを置くだけでは動かない。timer を有効にして起動する必要がある。

つまずき有効化するのは service ではなく timer 側。systemctl enable --now backup.timer のように timer を指定する。

systemctl enable --now backup.timer のように --now を付けると、「次回のシステム起動時からの自動有効化」と「いますぐの起動」を同時に行える。ここで有効化するのは service ではなく timer 側である点に注意してほしい。

では、ちゃんと次が予約されたかをどう確かめるか。登録された timer の状況は systemctl list-timers で一覧できる。NEXT 列に次回起動の予定時刻、LAST 列に前回起動時刻、UNIT 列に対応する timer 名が並ぶので、「ちゃんと次が予約されているか」を目で確認できる。

systemctl list-timers ……NEXT(次回)・LAST(前回)・UNIT が並ぶ。次の予約がちゃんと入っているか目で確認できる。

実行結果のログは、cron のようにメールやファイルへ自分で逃がす必要はない。journal に自動で記録される。

コツjournalctl -u backup.service なら、その処理の過去の実行ログだけを時系列で追える。失敗した回も残るので原因の切り分けが楽。

journalctl -u backup.service のように unit を指定すれば、その処理の過去の実行ログだけをまとめて時系列で追える。これが cron に対する大きな使い勝手の差だ。失敗した回も含めて履歴がそろって残るので、原因の切り分けが格段にやりやすくなる。

🔋 電源が落ちていた間の実行は取り戻せるのか

systemd timer がとりわけ強いのが、電源が落ちていた間に逃した実行を後から補える点だ。素の cron は逃した実行を黙って諦める。timer はどうか。

💡
ポイントtimer に Persistent=true を設定すると、電源が落ちて逃した実行を、次に起動したときに補って実行してくれる。

timer ユニットに Persistent=true を設定しておくと、systemd は前回の実行時刻を記録する。もし予定時刻にマシンが停止していて実行を逃した場合、次に起動したときにその分をすぐ実行してくれる。

常時起動でないノートPCや、間欠的に電源を入れるエッジ機器で「電源を入れていなかった日のバックアップが丸ごと飛ぶ」といった事態を防げるわけだ。

これは、逃した実行は黙って諦める素の cron には無い挙動だ。同様の補完を cron 系で得たいときは anacron という別のしくみを併用する必要がある。

🔗
たとえPersistent=true は「留守の間に届かなかった配達を、帰ってきたらまとめて届けてくれる」しくみ。素の cron は不在なら配達をあきらめる。

まとめると、ログが journal に統合される・依存関係や条件を細かく書ける・Persistent で逃した実行を補える、という3点が systemd timer を選ぶ主な理由だ。

一方で、ちょっとした処理を1行でさっと仕込むだけなら crontab -e のほうが手軽、という住み分けになる。要件が素直なら cron、運用の作り込みや堅牢さを求めるなら systemd timer、と覚えておくと選択に迷わない。

この項目に出てくる用語

systemd timerシステムディー タイマー
systemd でコマンドを定期実行するためのユニット。cron の代替として使われる。
ユニットユニット
systemd が管理する処理の単位。service や timer などの種類がある。

関連コマンド

systemctl list-timerssystemctl

▶ 学習アプリでこの続きを学ぶ・演習する