Linuxサーバーで「毎日深夜2時にバックアップを実行する」「毎週月曜朝9時にレポートを送信する」といった定期処理を設定するとき、欠かせないのが Cron と Cron式 です。
本記事では、Cron式の5フィールドの意味から、よく使うパターン、GitHub ActionsやAWS Lambda・Laravelでの活用方法、デバッグのコツまでを実践的に解説します。
Cronとは?
Cron(クロン)はUnix/Linux系OSに標準搭載された時間ベースのジョブスケジューラーです。バックグラウンドで常駐する cron デーモンが、crontab(cron table)と呼ばれる設定ファイルを定期的に読み込み、指定時刻になるとコマンドを自動実行します。
- バックアップ処理:毎日深夜にDBをダンプしてS3へ転送
- メール送信:毎朝9時に日次レポートをメール配信
- ログローテーション:週次でログを圧縮・アーカイブ
- キャッシュ更新:30分ごとに集計データを再生成
- サイト監視:5分ごとにヘルスチェックエンドポイントをping
Cron式の構文
Cron式は空白区切りの 5つのフィールド で構成されます:
分(0-59) 時(0-23) 日(1-31) 月(1-12) 曜日(0-7) * * * * *
| フィールド | 範囲 | 備考 |
|---|---|---|
| 分 | 0〜59 | 0が毎時0分(正時) |
| 時 | 0〜23 | 0が深夜0時 |
| 日 | 1〜31 | 月によって最大日が異なる |
| 月 | 1〜12(またはJan〜Dec) | |
| 曜日 | 0〜7(0と7が日曜) | 1=月曜, 5=金曜, 6=土曜 |
特殊記号
| 記号 | 意味 | 例 |
|---|---|---|
* | すべての値 | * * * * *(毎分) |
*/n | n間隔ごと | */5 * * * *(5分ごと) |
a-b | a〜bの範囲 | 1-5(月〜金) |
a,b,c | リスト指定 | 0,15,30,45(15分ごと) |
a-b/n | 範囲をn間隔で | 0-12/2(0〜12時を2時間ごと) |
よく使うCron式パターン集
基本パターン
# 毎分実行 * * * * * # 毎5分ごと */5 * * * * # 毎15分ごと 0,15,30,45 * * * * # または */15 * * * * # 毎時0分(1時間に1回) 0 * * * * # 毎日深夜0時 0 0 * * * # 毎日午前2時(バックアップ等) 0 2 * * * # 毎週月曜日の朝9時 0 9 * * 1 # 毎月1日の0時(月次バッチ) 0 0 1 * * # 毎年1月1日の0時 0 0 1 1 *
ビジネスシーン向けパターン
# 平日(月〜金)の朝9時 0 9 * * 1-5 # 平日の業務時間内(9時〜18時)、毎時実行 0 9-18 * * 1-5 # 平日深夜2時のバッチ処理 0 2 * * 1-5 # 金曜日の18時(週次レポート) 0 18 * * 5 # 毎月第1営業日っぽい代替(毎月1〜5日の月曜) # ※Cronのみでは第1月曜は直接指定できない 0 9 1-7 * 1
注意が必要なパターン
# 「日」と「曜日」を両方指定するとOR動作(ANDにはならない) # ↓ 毎月15日 OR 毎週日曜(どちらかに一致すれば実行) 0 0 15 * 0
多くのCronシステムでは、日フィールドと曜日フィールドの両方に * 以外を指定すると、ANDではなくORで動作します。「毎月15日かつ日曜のみ」とはならないので注意してください。
crontabの使い方
基本コマンド
# crontabを編集(エディタが開く) crontab -e # 現在のcrontabを表示 crontab -l # crontabを削除(全削除なので注意) crontab -r # 特定ユーザーのcrontabを編集(root権限が必要) crontab -u username -e
crontabの書き方
# 形式:Cron式 + 実行コマンド(フルパス推奨) 0 2 * * * /usr/bin/python3 /home/user/backup.py # 出力をログファイルに保存 0 2 * * * /usr/bin/backup.sh >> /var/log/backup.log 2>&1 # 環境変数の設定(先頭行で定義) MAILTO=admin@example.com PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin 0 2 * * * /usr/local/bin/myapp --backup
フルパスを使う理由:crontabの実行環境は通常のシェルよりも少ない環境変数しか持ちません。python3 だけでなく /usr/bin/python3 のようにフルパスを指定することで「コマンドが見つからない」エラーを防げます。
システム全体のcron(/etc/cron.d)
Linuxには /etc/cron.daily/、/etc/cron.weekly/、/etc/cron.hourly/ のようなディレクトリがあり、スクリプトを置くだけで自動実行されます。/etc/cron.d/ には実行ユーザーを明示する必要があります:
# /etc/cron.d/myapp の形式(ユーザー名フィールドが必要) 0 2 * * * root /usr/local/bin/myapp-backup
クラウド・各種サービスでのCron設定
GitHub Actions
GitHub Actionsのワークフローで on.schedule にCron式を記述します。タイムゾーンはUTC固定です。
on:
schedule:
- cron: '0 0 * * *' # UTC 0:00 = JST 9:00
jobs:
nightly:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: ./scripts/nightly.sh
日本時間で動かしたい場合は、JSTからUTCに9時間引いた値を設定してください。JST 9:00 → UTC 0:00、JST 18:00 → UTC 9:00 です。
AWS EventBridge(旧CloudWatch Events)
AWS EventBridgeのスケジュールルールでは2種類の記法があります:
# Rate式(シンプルな繰り返し) rate(5 minutes) rate(1 hour) rate(7 days) # Cron式(6フィールド形式 — 年フィールドが追加) # cron(分 時 日 月 曜日 年) cron(0 2 * * ? *) # 毎日UTC 2:00(?は必須、日と曜日のどちらかに指定) cron(0 9 ? * MON-FRI *) # 平日UTC 9:00
AWSのCron式は標準の5フィールドと異なり、6フィールド(年追加)で日と曜日に ?(未指定)が使えます。
Laravel タスクスケジューラー
LaravelではCrondが1分ごとに php artisan schedule:run を呼び出し、その中でスケジュール定義を評価します。
# まずcrontabに1行だけ追加 * * * * * cd /path/to/project && php artisan schedule:run >> /dev/null 2>&1
// app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
$schedule->command('backup:run')->dailyAt('02:00');
$schedule->command('report:weekly')->weeklyOn(5, '18:00'); // 金曜18時
$schedule->job(new ProcessQueue)->everyFiveMinutes();
$schedule->cron('0 9 * * 1-5')->command('send:digest'); // カスタムCron式
}
Kubernetes CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
name: backup-job
spec:
schedule: "0 2 * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: backup
image: my-backup:latest
restartPolicy: OnFailure
タイムゾーンの注意点
Cronが実行される時刻はサーバーのタイムゾーン設定に依存します。クラウドサーバーはUTCで動作していることが多く、意図した時刻に実行されないミスがよく起きます。
# タイムゾーンを確認 date timedatectl # crontabでタイムゾーンを指定(GNU cronの場合) CRON_TZ=Asia/Tokyo 0 9 * * * /usr/bin/send-digest.sh
本番環境では、Cronの実行時刻と想定タイムゾーンをチームで明記しておくことを強くお勧めします。特にGitHub Actions(UTC固定)やAWS Lambda(UTC固定)は日本時間と9時間ずれます。
デバッグのコツ
Cronが実行されない原因チェックリスト
- パスの問題:コマンドのフルパスを使っているか確認。
which python3でパスを調べる - 実行権限:スクリプトに実行権限があるか(
chmod +x script.sh) - 改行コード:Windowsで作成したスクリプトの
\r\n改行が原因で失敗することがある(dos2unixで変換) - ログ確認:
/var/log/syslogまたは/var/log/cronにcronの実行ログが残る - メール確認:MAILTOを設定するとエラー出力がメールで届く
- 環境変数:cronの環境は最小限なのでスクリプト内で
source ~/.bashrcや必要な変数を明示的に読み込む
ログに出力して確認
# 標準出力と標準エラーをログに追記 0 2 * * * /usr/bin/backup.sh >> /var/log/backup.log 2>&1 # システムのcronログを確認 grep CRON /var/log/syslog | tail -20 # journalctlでcronのログを確認(systemd環境) journalctl -u cron --since today
よくある質問(FAQ)
- Cron式で月末最終日を指定できますか?
- 標準の5フィールドCronでは月末最終日を直接指定できません。代替として「28〜31日」で設定し、スクリプト側で最終日判定するか、
last記号に対応したVixie Cron拡張版を使う方法があります。 - */1 と * の違いは何ですか?
- どちらも同じ意味で「すべての値」を指します。
*/1は「1間隔ごとのすべて」なので * と等価です。可読性のために * を使う方が一般的です。 - Cronで30秒ごとの実行は可能ですか?
- 標準のCronは最小単位が1分です。30秒ごとに実行したい場合は、1分ごとのCronで実行し、スクリプト内で
sleep 30 && commandを呼ぶ方法か、Systemd timersやより高頻度のスケジューラーを使う方法があります。 - crontab -r を誤って実行してしまいました。復元できますか?
- 残念ながら、
crontab -rで削除したcrontabはバックアップがない限り復元できません。定期的にcrontab -l > ~/crontab.bakでバックアップしておくことをお勧めします。 - GitHub Actionsのcronは最小どのくらいの頻度で動かせますか?
- GitHub Actionsのスケジュールは最短5分間隔(
*/5 * * * *)が目安です。ただしGitHub側の負荷により、指定した時刻より数分遅れて実行されることがあります。高頻度・精密な実行が必要な場合は自前のサーバーでcronを使う方が確実です。
まとめ
- Cron式は「分 時 日 月 曜日」の5フィールド。
*・*/n・a-b・a,b,cの4種の記号で細かく指定できる。 - crontabではコマンドのフルパスを使い、出力をログファイルにリダイレクトする習慣をつける。
- GitHub Actions・AWS EventBridge・Laravelなど各プラットフォームで微妙に記法が異なる点に注意。
- タイムゾーンは必ず確認——クラウドサーバーはUTCで動作しており、JST(UTC+9)とは9時間ずれる。
- 日フィールドと曜日フィールドを同時に指定するとOR動作になる。
- CronジェネレーターでGUI操作でCron式を作成し、Cronパーサーで既存の式を解読できます。