cron が動かない原因チェックリスト|手動では動くのに失敗する理由とログの確認方法
crontab に書いたはずのバッチが動いていない。ターミナルで手で実行すると成功するのに、cron からだと何も起きない。cron のトラブルは、エラーがどこにも表示されないまま静かに失敗することが多く、原因を探すのに時間がかかりがちです。この記事では、cron が動かないときに確かめる順番を「式」「cron 本体」「ログ」「実行環境」「ファイルと権限」「タイムゾーン」に分けて整理し、手動では動くのに cron だと失敗する典型的な理由と、その直し方をまとめます。
まず切り分け:「cron が動いていない」のか「コマンドが失敗している」のか
「cron が動かない」と一口に言っても、原因は大きく 2 つに分かれます。1 つは、そもそも cron がその時刻にコマンドを起動していないケース。もう 1 つは、cron は予定どおり起動しているのに、コマンドの中で失敗しているケースです。どちらなのかで調べる場所がまったく違うので、最初に切り分けます。
- 1
ログに起動の記録があるかを見る
後で説明する cron のログに、その時刻に「CMD (コマンド)」の行が出ていれば、cron は起動しています。原因はコマンド側です。行がなければ、式・cron 本体・ファイルの書き方を疑います。
- 2
1 分ごとのテスト行を足してみる
crontab -e で「* * * * * date >> /tmp/cron-test.log 2>&1」を一時的に追加し、1〜2 分待って /tmp/cron-test.log に時刻が増えていくかを見ます。増えていれば cron 自体は正常に動いています。確認が終わったら必ず削除します。
- 3
本番の行の時刻を近い時刻に変えて試す
日次や週次の予定は、次に動くまで待つと何日もかかります。テスト中だけ時刻を数分後に変え、結果を見てから元に戻すと、すぐに確かめられます。
式の書き間違いで「動いていない」ように見えるパターン
cron は式として正しければ、意図と違っていても文句を言わずにその時刻に動きます。「動かない」と思っていたら、実は想定外の日時に動いていた、ということも少なくありません。まず式そのものを疑いましょう。
| 書いた式 | 意図 | 実際の動き |
|---|---|---|
| 0 9 31 * * | 毎月末日 | 31 日がない 2・4・6・9・11 月は動かない |
| 0 9 30 2 * | 2 月の末日 | 2 月 30 日は存在しないので一度も動かない |
| 0 9 1-7 * 1 | 第 1 月曜 | 毎週月曜と毎月 1〜7 日に動く(OR) |
| 30 9 * * *(UTC のサーバー) | 日本時間 9:30 | 日本時間 18:30 に動く |
| 9 30 * * * | 9:30 | 時の欄に 30 は書けず、エラーで読み込まれない |
| * 3 * * * | 毎日 3 時に 1 回 | 3:00〜3:59 の毎分、60 回動く |
日と曜日の組み合わせや月末の書き方は特に間違えやすいので、cron の日と曜日の OR と第 n 曜日・月末の書き方で詳しく解説しています。cron 式チェッカーに crontab の行を貼れば、意味を日本語に訳して次の実行日時を 10 件並べるので、「いつ動く予定になっているか」をすぐに確認できます。
cron 本体の状態とログの確認方法
式が正しいのに起動の記録がない場合は、cron のサービスが止まっていないか、ログにエラーが出ていないかを確認します。ディストリビューションによってサービス名とログの場所が違います。
| 確認すること | Ubuntu・Debian | RHEL・CentOS・Rocky・Amazon Linux |
|---|---|---|
| サービスの状態 | systemctl status cron | systemctl status crond |
| サービスの起動 | sudo systemctl enable --now cron | sudo systemctl enable --now crond |
| ログ(ファイル) | grep CRON /var/log/syslog | sudo cat /var/log/cron |
| ログ(journal) | journalctl -u cron --since today | journalctl -u crond --since today |
- 「(ユーザー名) CMD (コマンド)」の行:その時刻にコマンドを起動した記録。これがあれば cron は正常
- 「(CRON) info (No MTA installed, discarding output)」:コマンドが何か出力したが、メールで送る仕組みがないので捨てた、という意味。エラーメッセージがここで消えている可能性が高い
- 「(*system*) … WRONG FILE OWNER」「INSECURE MODE」:/etc/cron.d などのファイルの持ち主や権限がおかしく、読み込まれていない
- 「bad minute」「bad hour」「errors in crontab file」:式の書式エラー。その行は読み込まれていない
手動では動くのに cron だと失敗する 5 つの理由
ログに起動の記録があるのに結果が出ていないなら、コマンドが cron の環境で失敗しています。cron は、ログインしたときのシェルとは違う、ごく最小限の環境でコマンドを実行します。手で試すと成功するのに cron だと失敗するのは、ほとんどがこの差です。
| 原因 | 症状 | 直し方 |
|---|---|---|
| PATH が短い | command not found(/usr/local/bin や ~/.local/bin のコマンド) | コマンドを絶対パスで書く。または crontab の先頭に PATH= を書く |
| シェルが /bin/sh | bash の書き方(source、[[ ]]、配列)でエラー | スクリプトの先頭に #!/bin/bash を書き、スクリプトとして呼ぶ |
| .bashrc などを読まない | 環境変数(API キーや言語のバージョン管理)が空 | 必要な変数をスクリプト内で設定するか、crontab の先頭に書く |
| 作業ディレクトリがホーム | 相対パスのファイルが見つからない | スクリプトの最初で cd /path/to/dir するか、絶対パスにする |
| % が改行になる | date +%Y%m%d の途中でコマンドが切れる | crontab の中では \% とエスケープする |
cron と同じ環境で試すには、「env -i HOME=$HOME PATH=/usr/bin:/bin SHELL=/bin/sh /bin/sh -c 'コマンド'」のように、環境変数をほぼ空にしてコマンドを実行してみるのが近道です。ここで失敗すれば、原因は環境の差だと分かります。
% の問題は気づきにくいので特に注意が必要です。crontab のコマンド部分では、% が「ここで改行、残りは標準入力に渡す」という意味になります。「tar czf /backup/$(date +%Y%m%d).tar.gz /data」のような行は、% の手前でコマンドが切れて失敗します。「date +\%Y\%m\%d」とエスケープするか、処理をシェルスクリプトにまとめて crontab からはスクリプトを呼ぶだけにすると確実です。
ファイル・権限・改行コードの落とし穴
crontab の書き方そのものは正しくても、ファイルの置き方や権限が原因で読み込まれていない、実行できない、ということもあります。次の項目を順に確認します。
- スクリプトに実行権限があるか:ls -l で x が付いているか確認し、なければ chmod +x script.sh。または sh script.sh のようにシェル経由で呼ぶ
- 1 行目の #! が正しいか:#!/bin/bash のパスが実在するか。Windows で編集したファイルは行末が CRLF になり「/bin/bash^M: bad interpreter」で失敗するので、dos2unix などで LF に直す
- crontab の最後の行に改行があるか:最終行に改行がないと、その行が無視される実装がある
- /etc/cron.d のファイルにユーザー名の欄があるか:/etc/crontab と /etc/cron.d/ のファイルは「分 時 日 月 曜日 ユーザー名 コマンド」の 7 つ以上の欄が必要
- /etc/cron.d のファイル名と権限:Debian・Ubuntu ではファイル名に . を含むファイル(backup.cron など)は読まれない。持ち主は root、ほかのユーザーが書き込めない権限(644)にする
- cron.allow・cron.deny:/etc/cron.allow があると、そこに書かれたユーザーしか crontab を使えない
タイムゾーンのずれ:9 時間ずれて動いていないか
「動かない」の正体が「9 時間ずれて動いている」だったということはよくあります。cron は、cron が動いているサーバー(コンテナ)のタイムゾーンで時刻を読みます。クラウドのサーバーやコンテナのイメージは初期設定が UTC のことが多く、日本時間のつもりで書いた時刻より 9 時間遅れて動きます。
- 1
サーバーのタイムゾーンを確かめる
date や timedatectl を実行し、表示が JST か UTC かを見ます。UTC なら、日本時間から 9 時間引いた時刻で書くか、タイムゾーンを変更します。
- 2
タイムゾーンを変えたら cron を再起動する
sudo timedatectl set-timezone Asia/Tokyo で変更できますが、すでに動いている cron は古いタイムゾーンのままのことがあります。sudo systemctl restart cron(RHEL 系は crond)で再起動します。
- 3
1 行だけ別のタイムゾーンにしたいとき
RHEL 系で使われる cronie は、crontab に CRON_TZ=Asia/Tokyo と書くと、その後の行を指定したタイムゾーンで読みます。ただし Debian・Ubuntu の標準の cron では効かないので、時刻を UTC に直して書くほうが確実です。
GitHub Actions・AWS EventBridge・Kubernetes など、サーバーの外で cron 式を読む仕組みでも同じずれが起きます。GitHub Actions は常に UTC なのでGitHub Actions の cron を日本時間で動かす方法を、EventBridge はEventBridge の cron 式の書き方を参照してください。
次に失敗したときすぐ分かるようにする
原因が分かって直ったら、次に同じことが起きたときにすぐ気づけるようにしておくと、トラブルの調査時間が大きく減ります。
- 出力を必ずログに残す:行の末尾に >> /var/log/myjob.log 2>&1 を付け、エラーも含めて追記する。ログが大きくなりすぎないよう logrotate も設定する
- MAILTO を設定する:crontab の先頭に MAILTO=you@example.com と書くと、出力があったときにメールで届く(メールを送る仕組みがサーバーに必要)
- 二重起動を防ぐ:前回の処理が終わる前に次が始まると不具合の元になる。flock -n /tmp/myjob.lock コマンド のようにロックをかける
- 成功を外から監視する:処理の最後に監視サービスの URL を叩く「死活監視(ハートビート)」を入れると、動かなかったことにも気づける
- crontab のバックアップ:crontab -l > ~/crontab.bak を定期的に取り、設定の変更履歴を残す
crontab の書き方や記号の意味をもう一度整理したいときはcrontab の書き方と早見表が役立ちます。設定を変えるたびに cron 式チェッカーで次の実行日時を確かめておけば、「書いたつもりと違う時刻に動く」タイプのトラブルは事前に防げます。
よくある質問
- crontab に書いたのに実行されないときは、まず何を確認すればいいですか?
- 最初に cron のログ(Ubuntu なら grep CRON /var/log/syslog、RHEL 系なら /var/log/cron)を見て、その時刻に CMD の行があるかを確認します。行があればコマンド側の失敗、なければ式の書き間違いや cron のサービスの停止を疑います。「* * * * * date >> /tmp/cron-test.log」を一時的に足すと、cron 自体が動いているかをすぐに確かめられます。
- 手動では動くのに cron だと動かないのはなぜですか?
- cron は PATH が /usr/bin:/bin 程度しかない最小限の環境で、/bin/sh を使い、.bashrc なども読まずにコマンドを実行するためです。コマンドを絶対パスで書く、必要な環境変数をスクリプト内で設定する、作業ディレクトリに cd する、% を \% とエスケープする、といった対応で解決することがほとんどです。
- cron のログはどこで確認できますか?
- Ubuntu・Debian では /var/log/syslog に記録されるので grep CRON /var/log/syslog で絞り込みます。RHEL・CentOS・Rocky Linux などでは /var/log/cron です。systemd の環境なら journalctl -u cron(RHEL 系は -u crond)でも確認できます。
- cron の実行時刻が 9 時間ずれるのはなぜですか?
- cron がサーバーのタイムゾーンで時刻を読んでいて、そのサーバーが UTC に設定されているためです。日本時間は UTC より 9 時間進んでいるので、日本時間のつもりで書いた時刻より 9 時間遅れて動きます。タイムゾーンを Asia/Tokyo に変えて cron を再起動するか、UTC の時刻に直して書きます。
- /etc/cron.d に置いたファイルが動きません。
- /etc/cron.d のファイルは、5 つの時刻の欄とコマンドの間に実行するユーザー名の欄が必要です。また Debian・Ubuntu ではファイル名に . を含むと読み込まれず、持ち主が root でない、ほかのユーザーが書き込める権限になっている場合も無視されます。ログの WRONG FILE OWNER や INSECURE MODE の表示も確認してください。
この記事で紹介したツール
あわせて読みたい
cron の日と曜日は OR になる|第 2 月曜・月末・最終金曜・隔週の正しい書き方
「毎月第 1 月曜の 9 時」のつもりで「0 9 1-7 * 1」と書いたら、毎週月曜に加えて毎月 1〜7 日の毎日にも動いてしまった。cron でとても多いこの失敗は、日と曜日の両方を指定すると「どちらか」に当てはまる日に動くという、cron 独特のルールが原因です。この記事では、日と曜日が OR になる仕組みと例外、crontab で第 n 曜日・月末・最終金曜・隔週を正しく動かす書き方、AWS EventBridge や Spring で使える L・#・W の書き方までを、実際の実行日付の例つきで解説します。
記事を読む →GitHub Actions の cron を日本時間で動かす|UTC 変換の早見表と曜日ずれ・遅延の対策
GitHub Actions の schedule に「0 9 * * 1-5」と書いたのに、ワークフローが動いたのは日本時間の夕方 6 時だった。これは書き間違いではなく、GitHub Actions の cron が必ず UTC(協定世界時)で読まれるためです。この記事では、日本時間(JST)の時刻を UTC の cron 式に直す計算と早見表、朝 0〜8 時を指定したときに起きる「曜日・日付が前の日にずれる」問題、1 行で書けないときの 2 行への分け方、そして schedule が遅れる・動かないときの原因と対策までをまとめます。
記事を読む →EventBridge の cron 式の書き方|? の意味・曜日の数字・日本時間の指定と crontab からの書き換え
AWS で Lambda や ECS のタスクを定期実行するときに使う EventBridge の cron 式は、Linux の crontab と似ているようで、欄の数・? の使い方・曜日の数字・タイムゾーンが少しずつ違います。crontab の感覚で「0 9 * * 1-5」と書くとエラーになり、曜日の数字をそのまま移すと 1 日ずれ、時刻は UTC で読まれて 9 時間ずれる、とつまずきどころが重なります。この記事では、EventBridge の cron 式の 6 つの欄と ? のルール、曜日の数字、L・W・# の使い方、rate 式との違い、ルールと Scheduler での日本時間の扱い、crontab・Kubernetes・Spring・systemd との書き換え表までをまとめます。
記事を読む →