systemd timerでcronジョブを置き換える方法|.timerユニットの作り方と実践例

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Linuxtips, システム管理 > systemd timerでcronジョブを置き換える方法|.timerユニットの作り方と実践例
「毎日深夜にバックアップスクリプトを動かしたいのに、cronの書き方が複雑でミスしてしまう」
「crontab -e で設定したのに、なぜかジョブが動いていない。ログの見方もよくわからない」

こういった悩みを持つエンジニアは多いはずです。cronは歴史ある定番ツールですが、環境変数の引き継ぎや実行ログの管理が独特で、トラブルのたびに原因究明に手間がかかります。

この記事では、systemd timer を使ってcronジョブをモダンな方法で置き換える手順を解説します。.serviceファイルと.timerファイルの書き方から、systemctlによる管理・ログ確認まで、実際のサーバー環境で使える実践例を交えて丁寧に説明します。

この記事のポイント

・systemd timerは.serviceと.timerの2ファイルで定義する
・journalctlでジョブの実行ログをcronより簡単に追跡できる
・OnCalendar=で柔軟な時刻指定が可能(週次・月次も簡単)
・AccuracySec=で実行タイミングの精度をコントロールできる


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
図解60P/登録10秒/解除も3秒 / 詳細はこちら

systemd timerとは?cronとの違いを理解する

systemd timerとは、systemdの仕組みを使ってジョブを定期実行するための機能です。Linuxのinitシステムとして広く使われているsystemdには、サービス管理だけでなく、タイマー機能が標準で搭載されています。

cronと比べたとき、systemd timerには次のような特徴があります。

比較項目 cron systemd timer
設定ファイル crontab(1ファイルに全定義) .serviceと.timerの2ファイル
実行ログ /var/log/cron(環境による) journalctlで統一管理
環境変数 cronの最小環境変数のみ Environmentや.envファイルで明示指定
依存関係 設定不可 After=やWants=で制御可能
ミス検出 実行時まで気づきにくい systemctl statusでユニットの構文エラーを事前検出
実行ユーザー crontabのユーザーに依存 User=で明示指定できる

特にjournalctlによるログ追跡は、cronの「なぜ動いていないかわからない」という問題を大幅に解消してくれます。

動作確認環境: RHEL 9.4 / Rocky Linux 9.3 / Ubuntu 24.04 LTS(systemd 252以降)

systemd timerの基本構成(.serviceと.timerの関係)

systemd timerを使う際は、必ず2つのユニットファイルをセットで作成します。

.serviceファイル: 実際に実行するコマンドやスクリプトを定義する
.timerファイル: いつ.serviceを起動するかのスケジュールを定義する

ファイル名は同じベース名にすることがルールです。例えば `backup.service` と `backup.timer` のようにペアにします。

ユニットファイルの配置場所は用途によって2種類あります。

/etc/systemd/system/: システムワイドなユニット(root権限が必要な処理)
~/.config/systemd/user/: ユーザー単位のユニット(一般ユーザーでも作成可能)

本記事ではシステムワイドな設定(/etc/systemd/system/)を前提に解説します。

実践例:バックアップスクリプトをsystemd timerで毎日実行する

ここでは `/usr/local/bin/backup.sh` というバックアップスクリプトを、毎日午前2時に実行するsystemd timerを作成します。

1. バックアップスクリプトの準備

まず、実行するスクリプトを用意します。

# /usr/local/bin/backup.sh を作成 cat <<'EOF' > /usr/local/bin/backup.sh #!/bin/bash BACKUP_DIR=/var/backup DATE=$(date +%Y%m%d) tar -czf "${BACKUP_DIR}/home_${DATE}.tar.gz" /home echo "backup completed: ${DATE}" EOF chmod +x /usr/local/bin/backup.sh

2. .serviceファイルを作成する

次に、スクリプトを実行するためのサービスユニットを作成します。

# /etc/systemd/system/backup.service を作成 cat <<'EOF' > /etc/systemd/system/backup.service [Unit] Description=Daily Backup Service After=network.target [Service] Type=oneshot ExecStart=/usr/local/bin/backup.sh User=root EOF

Type=oneshot はコマンドを1回だけ実行して終了するサービスタイプです。バックアップや定期処理など、タイマーから起動するジョブは基本的にこのタイプを使います。

3. .timerファイルを作成する

スケジュールを定義するtimerユニットを作成します。

# /etc/systemd/system/backup.timer を作成 cat <<'EOF' > /etc/systemd/system/backup.timer [Unit] Description=Run backup.service every day at 02:00 [Timer] OnCalendar=*-*-* 02:00:00 Persistent=true [Install] WantedBy=timers.target EOF

OnCalendar=: 実行スケジュールを指定するキーワード(後述で詳しく解説)
Persistent=true: サーバーが停止していた場合、次回起動時に「実行漏れ」を補完する
WantedBy=timers.target: timerユニット共通の設定。システム起動時に自動有効化される

4. timerを有効化・起動する

作成したtimerを有効化して動かします。

# systemdにユニットファイルを認識させる systemctl daemon-reload # timerを有効化(システム起動時に自動開始) systemctl enable backup.timer # timerを今すぐ起動 systemctl start backup.timer # timerの状態を確認 systemctl status backup.timer

実行結果の例:

# systemctl status backup.timer の出力例 * backup.timer - Run backup.service every day at 02:00 Loaded: loaded (/etc/systemd/system/backup.timer; enabled; preset: disabled) Active: active (waiting) since Wed 2026-05-20 10:15:32 JST; 3min ago Trigger: Thu 2026-05-21 02:00:00 JST; 15h 44min left Triggers: * backup.service

「Trigger:」の行に次の実行予定時刻が表示されます。cronではこのような確認が難しかったですが、systemd timerでは一目でわかります。

OnCalendarの書き方|スケジュール指定パターン集

OnCalendarの書式は `曜日 年-月-日 時:分:秒` の形式です。アスタリスク(*)はワイルドカードとして使えます。

やりたいこと OnCalendarの指定
毎日2時に実行 OnCalendar=*-*-* 02:00:00
毎時0分に実行 OnCalendar=*-*-* *:00:00
毎週月曜日の3時に実行 OnCalendar=Mon *-*-* 03:00:00
毎月1日の6時に実行 OnCalendar=*-*-01 06:00:00
30分ごとに実行 OnCalendar=*-*-* *:00,30:00
平日の9時に実行 OnCalendar=Mon..Fri *-*-* 09:00:00
年に一度(元日の0時) OnCalendar=*-01-01 00:00:00

OnCalendar=の指定が正しいか事前に確認するには `systemd-analyze calendar` コマンドが便利です。

# スケジュール指定を検証する systemd-analyze calendar "Mon *-*-* 03:00:00" # 出力例 Original form: Mon *-*-* 03:00:00 Normalized form: Mon *-*-* 03:00:00 Next elapse: Mon 2026-05-25 03:00:00 JST (in UTC): Mon 2026-05-24 18:00:00 UTC From now: 4 days 16h 44min left

「Next elapse:」に次回実行予定が表示されます。.timerファイルに書く前に必ず検証するのが実務での鉄則です。

AccuracySec=でタイミング精度を制御する

systemd timerにはデフォルトで `AccuracySec=1min`(1分の精度誤差)が設定されています。これはシステムへの負荷分散のために意図的に設けられた「ゆらぎ」です。

AccuracySec=1s: 秒単位の精度が必要な場合(ただしCPUウェイクアップ頻度が増える)
AccuracySec=1min: デフォルト。バックアップや定期レポートなら十分
AccuracySec=1h: 精度をさらに下げてシステム負荷を最小化したい場合

バックアップやログ集計など、数分のズレが許容できるジョブであればデフォルトのまま使って問題ありません。

よく使うsystemctl管理コマンド

systemd timerを運用する際によく使うコマンドをまとめます。

やりたいこと コマンド
ユニット変更を反映 systemctl daemon-reload
timerを有効化 systemctl enable backup.timer
timerを起動 systemctl start backup.timer
timerの状態確認 systemctl status backup.timer
今すぐserviceを手動実行 systemctl start backup.service
全timerの一覧表示 systemctl list-timers
timerを停止・無効化 systemctl disable --now backup.timer

`systemctl list-timers` は特に便利で、有効化されているすべてのtimerの次回実行予定を一覧表示します。

# 全timerの一覧を確認 systemctl list-timers --all # 出力例(抜粋) NEXT LEFT LAST PASSED UNIT ACTIVATES Thu 2026-05-21 02:00:00 JST 15h 44min Wed 2026-05-20 02:00:05 JST 8h ago backup.timer backup.service Thu 2026-05-21 00:00:00 JST 13h 44min Wed 2026-05-20 00:00:03 JST 10h ago logrotate.timer logrotate.service

journalctlでジョブの実行ログを確認する

systemd timerの最大の利点のひとつが、journalctlによるログ管理です。cronでは `/var/log/cron` を読むか、スクリプト内でログを書くかしかありませんでしたが、systemd timerはすべての実行ログがjournalに自動記録されます。

# backup.serviceの実行ログを確認 journalctl -u backup.service # 直近10件のみ表示 journalctl -u backup.service -n 10 # リアルタイムでログを追う journalctl -u backup.service -f # 今日の実行ログだけ確認 journalctl -u backup.service --since today

実際のサーバーでの出力例:

May 20 02:00:05 web01.example.com systemd[1]: Starting Daily Backup Service... May 20 02:00:07 web01.example.com backup.sh[12345]: backup completed: 20260520 May 20 02:00:07 web01.example.com systemd[1]: backup.service: Deactivated successfully. May 20 02:00:07 web01.example.com systemd[1]: Finished Daily Backup Service.

「Starting」と「Finished」が自動で記録されるため、スクリプト内で開始・終了ログを書く必要がありません。

トラブルシュート|よくあるエラーと対処法

1. timerが起動しない(Activeがinactiveのまま)

systemctl start後もActiveが `inactive` の場合は、まずステータスを確認します。

systemctl status backup.timer journalctl -xe -u backup.timer

多くの場合、ユニットファイルの構文エラーが原因です。`systemctl daemon-reload` 時にエラーが出ていないか確認します。

2. serviceは起動するがスクリプトが失敗する

cronとは異なり、systemd serviceの実行環境はPATHが最小限です。スクリプト内でフルパスを使うか、Environmentでパスを明示します。

# .serviceファイルにEnvironmentを追加する例 [Service] Type=oneshot ExecStart=/usr/local/bin/backup.sh Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin User=root

3. Persistent=trueなのに実行漏れが補完されない

Persistent=trueは「前回の実行がトリガー時刻を過ぎていた場合に補完する」機能です。timerが有効化(enabled)されていることが前提です。`systemctl is-enabled backup.timer` でenabledと表示されるか確認します。

4. ユニットファイル変更後に反映されない

.serviceや.timerファイルを編集した後は必ず `systemctl daemon-reload` を実行します。これを忘れると古いファイルのまま動作し続けます。

# ファイル編集後は必ずこのセットを実行する systemctl daemon-reload systemctl restart backup.timer systemctl status backup.timer

cronとsystemd timerの使い分けの考え方

systemd timerが優れているからといって、cronを完全に廃止する必要はありません。現場での使い分けの目安を整理します。

systemd timerが向いているケース
  複数のサービスに依存するジョブ(After=で依存関係を制御したい)
  実行結果をjournalctlで一元管理したいケース
  サーバー停止中の実行漏れをPersistent=trueで補完したいケース

cronが向いているケース
  既存のcrontabエントリを移行するコストが高い環境
  Dockerコンテナ内など、systemdが動作しない環境
  ユーザー単位の設定を`crontab -e`で素早く追加したい場合

新規にジョブを追加するなら、systemd timerを選ぶのが今のLinuxサーバー運用のスタンダードになりつつあります。

本記事のまとめ

やりたいこと コマンド・設定
ユニット変更を反映 systemctl daemon-reload
timerを有効化・起動 systemctl enable --now backup.timer
スケジュール指定の検証 systemd-analyze calendar "OnCalendar指定文字列"
全timerの次回実行確認 systemctl list-timers --all
実行ログの確認 journalctl -u backup.service -n 20
今すぐ手動実行 systemctl start backup.service
timerを停止・無効化 systemctl disable --now backup.timer

systemd timerは、cronに比べてログ追跡・エラー検出・依存関係管理の面で大きなアドバンテージがあります。.serviceと.timerの2ファイルを用意するだけで使い始められますので、新規のジョブ追加時にはぜひ活用してみてください。

Linuxのサービス管理についてさらに詳しく学びたい場合は、以下の関連記事も参考にしてください。

systemd-analyze で起動時間計測
Linux ポート確認の全コマンド
Linux DNS 設定の基本

systemd timerを含めた、安定したサーバー運用の基礎を固めませんか?

systemd timerの活用はサーバー自動化の一歩ですが、サービス管理・ログ監視・セキュリティ設定と合わせて体系的に身につけることで、現場で頼られる存在になれます。
ネットの切れ端の情報をコピペするだけでなく、現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。

「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は1分、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

登録10秒/合わなければ解除3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。