※本記事にはプロモーション(広告)を含みます。

1分単位の定期実行を止めずに安定させたいなら、まずsystemd-timerへの移行を検討し、単純な1行コマンドの定期実行だけをcronに残すのが実務的な落としどころです。Linuxサーバーの運用ではバックアップスクリプトやログローテーション、監視バッチなど「決まった時刻に決まった処理を動かす」場面が頻繁に発生します。cronは長年使われてきた枯れた仕組みですが、依存関係の管理やログ収集、実行状態の可視化という観点ではsystemdのtimerユニットに分があります。一方でtimerユニットはunit定義が必要になるぶん記述量が増え、簡易なジョブには過剰な場合もあります。本記事ではcronとsystemd-timerそれぞれの仕組みを整理したうえで、実運用で使い分けるための判断基準と移行手順、トラブル対応の方法まで具体的に解説します。

  • cronの仕組みと限界
  • systemd timerとは
  • 使い分けの判断基準
  • 移行と併用の手順
  • 運用トラブルの対処
  • よくある質問
  • まとめ

cronの仕組みと限界

cronはUNIX系OSに古くから搭載されているスケジューラで、cronデーモンがcrontabに記述された時刻情報を読み取り、該当時刻になるとコマンドを実行します。設定ファイルはユーザー単位のcrontab -eと、システム全体を管理する/etc/crontabや/etc/cron.d/配下のファイルに分かれており、どこに書いても最終的にcronデーモンが一括して監視する点は共通しています。

crontabの書式

crontabは「分 時 日 月 曜日 コマンド」の5フィールド形式です。たとえば毎日午前3時にバックアップスクリプトを実行する設定は次のようになります。

0 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

書式自体は短く済み、思いついた瞬間に1行追加できる手軽さがcron最大の利点です。ログをファイルにリダイレクトしなければ標準出力が破棄される点や、環境変数がログインシェルと異なる点は、初めて触る技術者がつまずきやすい部分です。

cron特有の弱点

cronには実行完了を待たずに次の周期が来ると多重起動してしまう問題があります。ジョブAの処理が5分を超えて終わらない状態で次の5分間隔の起動時刻が来ると、同じスクリプトが並行して走り出すことがあり、ロック処理を自前で組み込まない限り防げません。また実行結果の成功・失敗はログファイルを人力で確認するしかなく、依存関係のあるジョブ同士を「Aが終わったらBを実行する」という形で表現する仕組みも標準では用意されていません。サーバーがスリープや一時停止から復帰した際に、停止中に実行されるはずだった処理をどう扱うかという制御もcron単体では持っていません。

systemd timerとは

systemdを採用しているディストリビューションでは、timerユニットとserviceユニットを組み合わせて定期実行を構成できます。timerユニットが起動条件を定義し、実際の処理内容は対応するserviceユニットに書くという役割分担になっており、実行結果はsystemdのジャーナルにまとめて記録されます。

unitとtimerの関係

最小構成では、実行内容を書いたbackup.serviceと、起動条件を書いたbackup.timerの2ファイルを用意します。

[Unit]
Description=Backup job

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
[Unit]
Description=Run backup daily

[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true

[Install]
WantedBy=timers.target

timerを有効化するコマンドはsystemctl enable --now backup.timerです。実行状況はsystemctl list-timersで一覧確認でき、個別の実行ログはjournalctl -u backup.serviceで追跡できます。

OnCalendarの書き方

OnCalendarはcronのフィールド形式より表現の幅が広く、「毎週月曜と木曜の6時」のような複合条件をMon,Thu 06:00のように直接記述できます。さらにRandomizedDelaySec=300を指定すると、同時刻に集中しがちなジョブの起動時刻を最大300秒の範囲でランダムに分散でき、複数サーバーが同一スケジュールで走る環境での負荷集中を避けやすくなります。前回の起動が失敗した場合の再試行回数をOnFailure=で別のunitに委ねる構成も可能です。書式の細部はsystemdのバージョンによって挙動が変わることがあるため、実装前に公式ドキュメントで対象ディストリビューションのsystemdバージョンにおける仕様を確認してください。

使い分けの判断基準

どちらを選ぶかは「ジョブの複雑さ」「失敗検知の要否」「対象環境がsystemd前提かどうか」の3点で決めると迷いにくくなります。

cronが向く場面

コンテナイメージの中で1つのスクリプトだけを定期実行したい場合や、複数のUNIX系環境に共通の設定を配布したい場合はcronのほうが扱いやすい傾向があります。crontabはプレーンテキスト1行で完結するため、構成管理ツールのテンプレートに組み込みやすく、systemdを持たない軽量コンテナベースイメージでも動作します。

timerが向く場面

実行前に別のサービスが起動済みであることを保証したい、失敗時に自動でリトライさせたい、実行結果をジャーナルで一元的に検索したいといった要件があるなら、timerユニットのほうが適しています。依存関係はRequires=やAfter=で明示的に書けるため、ネットワークマウントの完了を待ってから実行する、といった条件付き起動も設定ファイルの記述だけで表現できます。

比較表で見る違い

項目cronsystemd timer
設定ファイルcrontab 1行.timer + .service 2ファイル
ログ管理手動でリダイレクト設定が必要journalctlで一元管理
依存関係定義基本的に不可After/Requiresで指定可能
実行の分散標準機能なしRandomizedDelaySecで分散可能
復帰時の実行保証標準機能なしPersistent=trueで対応
状態確認コマンドcrontab -lsystemctl list-timers
非systemd環境での可搬性高いsystemd必須

移行と併用の手順

既存のcronジョブをすべて一度に置き換える必要はありません。重要度と障害時の影響範囲を基準に段階的に移行するほうが安全です。

cronからの移行手順

まず既存のcrontabをエクスポートし、実行コマンドと実行時刻を確認します。次に対応するserviceユニットを作成し、実行コマンド部分をそのままExecStartに移し替えます。timerユニットのOnCalendarにはcronの時刻フィールドを読み替えて記述し、systemctl start backup.serviceで単体動作を確認してからsystemctl enable --now backup.timerで本稼働に切り替えます。移行直後は旧cronエントリをコメントアウトのまま数日残しておき、timer側のジャーナルに正常終了のログが継続して記録されることを確認してから完全に削除する運用が安全です。

併用時の注意点

同一スクリプトをcronとtimerの両方から起動する二重登録は、ロックファイルによる排他制御を入れていない限り事故の原因になります。移行期間中は必ずどちらか一方だけが有効な状態を維持し、切り替えのタイミングをチェンジログやチケットに記録しておくと、後から原因調査する際に混乱しません。

運用トラブルの対処

定期実行の障害は「動いていない」ことに気づくまでに時間がかかりやすい種類の問題です。日常的な確認手順を決めておくことで検知が早まります。

ログの確認方法

cron側では標準出力・標準エラーをリダイレクトしたログファイルをtailやgrepで確認します。systemd timer側はjournalctl -u サービス名 --since "1 hour ago"のように時間範囲を絞って確認でき、実行時刻・終了コード・標準出力が同じログストリームにまとまっているため、複数のログファイルを行き来する手間がありません。

よくある失敗例

cronでよくあるのは、対話シェルで動くコマンドがcron経由では環境変数不足で失敗するケースです。PATHやHOMEをスクリプト冒頭で明示的に設定することで多くは解消します。systemd timer側でよくあるのは、Type指定を省略して長時間実行のスクリプトを動かし、想定外のタイムアウトで強制終了されるケースです。長時間ジョブにはType=oneshotを指定し、必要に応じてTimeoutStartSec=で上限時間を明示してください。

よくある質問

cronは今後廃止されますか

主要ディストリビューションでcronパッケージ自体が削除される動きは確認できません。systemdを採用した環境でも多くの場合cronパッケージは別途インストール可能な状態で提供されており、当面は共存が前提になると見てよいでしょう。

コンテナ内でcronは使えますか

コンテナ内でcronデーモンを常駐させる構成は可能ですが、コンテナオーケストレーション基盤側にスケジューラ機能がある場合は、そちらを利用したほうがログやリトライの管理が一元化しやすくなります。基盤ごとの推奨方法は各公式ドキュメントを確認してください。

timerユニットの記述ミスはどう確認しますか

systemd-analyze verify backup.timerを実行すると、構文エラーや参照先serviceユニットの不整合を事前に検出できます。本番反映前に必ず実行しておくと切り分けが早くなります。

OnCalendarの秒指定は必須ですか

秒フィールドを省略すると00秒として扱われます。分単位の精度で十分な場合は省略しても問題ありませんが、複数ジョブの起動時刻を意図的にずらしたい場合は秒まで明示するか、RandomizedDelaySecを併用してください。

ジャーナルのログ保存期間はどこで決まりますか

journaldのログ保存期間や容量上限は/etc/systemd/journald.confの設定値に依存します。長期保存が必要なジョブでは、journaldの保持設定を確認したうえで、必要であれば外部のログ収集先に転送する構成を検討してください。

関連記事

まとめ

cronは設定が1行で完結する手軽さが強みで、非systemd環境や単純なワンショット処理には現在も有効な選択肢です。一方でsystemd-timerは依存関係の定義、ログの一元管理、実行時刻の分散といった運用面の機能が標準で備わっており、複雑な定期処理やチーム運用が前提の環境では管理コストを下げやすくなります。既存のcronジョブをすべて置き換える必要はなく、重要度が高く障害検知を早めたいジョブから段階的にtimerユニットへ移行し、単純な処理はcronに残すという併用方針が現実的な着地点です。設定変更後は必ずsystemd-analyze verifyやsystemctl list-timersで状態を確認し、セキュリティ設定やアクセス権限の変更を伴う場合は自己責任のもとテスト環境で十分に検証してから本番環境へ反映してください。

【編集・制作ポリシー】
本記事はInfra Academy編集部が各ベンダー公式ドキュメント・エンジニア監修をもとに作成しています。インフラ・クラウド構築は環境により異なります。本番環境への適用前に必ずテストを実施してください。情報の正確性には万全を期していますが、最新情報は各公式ドキュメントをご確認ください。 編集ポリシーはこちら

職場のIT課題、どこから手をつけるか整理してみませんか?

運営者の無料IT診断では、簡単な質問に答えるだけで社内のIT活用状況を整理し、改善の方向性のヒントをお返しします。売り込みはありません。

無料IT診断を受けてみる

Googleフォームが開きます / 無料 / 中小企業のIT担当者・経営者向け

ABOUT ME
たから
フリーランスIT講師/エンジニア。 ◆経験:IT講師/インフラエンジニア/PM/マネジメント/採用/運用・保守・構築・設計 ◆取得資格:CCNA/CCNP/LPIC-1/AZ-900//サーティファイC言語/情報処理技術者 ◆サイドビジネス:アパレル事業/複数のWEBメディアを運営