DevToolBox

crontabが実行されない時のチェックリスト

「手元で実行すると動くのに、cron に登録すると動かない」——原因の大半はPATH が最小限% のエスケープ漏れ最終行の改行欠落実行権限のどれかです。 この記事では crond の稼働確認 → ログ → 書式 → 環境変数 → 権限 の順に、 上から潰せば必ず原因に当たるチェックリストとして整理します。

This guide is a systematic checklist for cron jobs that never fire: verify the cron daemon, read the logs (/var/log/cron, journalctl -u cron), then check the minimal PATH, % escaping, the trailing newline, execute permissions, and the extra user field in system crontabs.

TL;DR

Cron Parser

cron式(5フィールド)を日本語で解読し、次回実行予定の日時を一覧表示。「そもそもスケジュール指定が意図通りか」を10秒で検証できます。ブラウザ完結・外部送信なし。

今すぐ試す →

1. crond は動いているか・ログに痕跡はあるか / Daemon & logs first

書式を疑う前に、cron デーモンの稼働と「cron がコマンドを起動した記録」を確認します。 ここで切り分けの軸が決まります。

# Debian / Ubuntu
systemctl status cron
grep CRON /var/log/syslog
journalctl -u cron --since today

# RHEL / CentOS / Amazon Linux
systemctl status crond
sudo tail -n 50 /var/log/cron
journalctl -u crond --since today

正常にジョブが起動していれば、ログに次のような CMD 行が残ります。

Jun 11 03:00:01 web01 CRON[21437]: (deploy) CMD (/home/deploy/backup.sh)
Jun 11 03:00:01 web01 CRON[21436]: (CRON) info (No MTA installed, discarding output)

CMD 行があるのに結果が出ない場合、cron は正常でコマンド側の失敗(PATH・権限・% → 2〜4章)です。2行目のNo MTA installed, discarding output は「エラー出力がメール送信できず捨てられた」 という印で、失敗の手がかりが消えている状態。まず出力をファイルに残しましょう。

0 3 * * * /home/deploy/backup.sh >> /tmp/backup.log 2>&1

If the log shows a CMD line, cron itself works and the command is failing. Redirect stdout/stderr to a file to capture the real error instead of letting cron discard it.

2. PATH は最小限 — フルパスで書く / cron's minimal PATH

cron はログインシェルを経由せず、.bashrc.profile も読みません。 PATH は通常 /usr/bin:/bin だけ。nvm で入れた node/usr/local/binaws は見つからず、リダイレクトしたログには こんなエラーが残ります。

/bin/sh: 1: node: not found
/bin/sh: 1: aws: not found

対処は2つ。which node で調べたフルパスを書くか、crontab 冒頭で PATH を明示します。

# NG: 対話シェルでは動くが cron では not found
* * * * * node /home/deploy/job.js

# OK その1: フルパス指定
* * * * * /usr/local/bin/node /home/deploy/job.js

# OK その2: crontab の先頭で環境変数を宣言
PATH=/usr/local/bin:/usr/bin:/bin
SHELL=/bin/bash

cron が実際に見ている環境は、1分間だけ次の行を仕込めば丸ごと確認できます。

* * * * * /usr/bin/env > /tmp/cron-env.txt 2>&1

cron does not source your shell rc files; PATH is typically just /usr/bin:/bin. Use absolute paths or declare PATH= at the top of the crontab, and dumpenv from a temporary job to see the exact environment.

3. 書式の罠 — %・最終行の改行・6フィールド目 / Syntax traps

% は改行扱い。crontab(5) の仕様で、エスケープされていない最初の% 以降はコマンドの標準入力に渡され、% 自体は改行に 置換されます。date +%Y%m%d は「date +」として実行され、 バックアップが app-.tar.gz のような名前で作られる事故が典型です。

# NG: 実行されるのは「date +」まで。%Y... は標準入力へ
0 3 * * * tar czf /backup/app-$(date +%Y%m%d).tar.gz /var/www

# OK: % をバックスラッシュでエスケープ
0 3 * * * tar czf /backup/app-$(date +\%Y\%m\%d).tar.gz /var/www

最終行は改行で終わらせる。Vixie cron 系は各エントリが改行で終わることを 要求します。crontab -e 経由なら通常問題になりませんが、echo '...' | crontab - や構成管理ツールでファイルを流し込むと 末尾改行が欠け、最終行のジョブだけ動かない・crontab が不完全と扱われることがあります。

システム crontab はフィールドが1つ多い。/etc/crontab/etc/cron.d/ 配下は6番目に実行ユーザー名が必要です。

# /etc/crontab・/etc/cron.d/*: 6番目にユーザー名(root)が必要
0 3 * * * root /usr/local/bin/backup.sh

# crontab -e のユーザーcrontab: ユーザー欄は書かない
0 3 * * * /usr/local/bin/backup.sh

逆にユーザー crontab に root を書くと「root」がコマンドとして解釈され、/bin/sh: 1: root: not found で失敗します。スケジュール部分(5フィールド)が 意図通りかは Cron Parser で次回実行日時を見るのが確実です。

Escape % as \% (everything after an unescaped % becomes stdin), end the crontab with a trailing newline, and remember that /etc/crontab and/etc/cron.d/ entries take an extra user field that per-user crontabs must not have.

4. 実行権限・シバン・相対パス / Permissions & paths

Check the execute bit, add a #!/bin/bash shebang (cron uses /bin/shby default), and avoid relative paths — cron starts jobs in the user's home directory.

5. デバッグ手順を1つの表に / The checklist

順 / Step確認 / Checkコマンド / CommandNGなら / If it fails
1crond 稼働 / Daemon upsystemctl status cron(RHEL系: crond)systemctl enable --now cron
2登録先のユーザー / Right crontabcrontab -l / sudo crontab -l -u deploy別ユーザーに登録していないか確認
3ログに CMD 行 / CMD in logsjournalctl -u cron --since today無ければ書式・改行・6フィールド目(3章)
4スケジュール指定 / ScheduleCron Parser で次回実行を確認フィールドの読み違いを修正
5出力の捕捉 / Capture output>> /tmp/job.log 2>&1 を付けるエラー文言から PATH・権限・% を特定
6cron の環境 / cron env* * * * * /usr/bin/env > /tmp/cron-env.txt 2>&1PATH / SHELL / HOME を crontab で明示

Work top-down: daemon → right user's crontab → CMD lines in the log → schedule → captured output → environment dump. Each step eliminates one whole class of failure.

まとめ / Summary

cron トラブルは「cron がコマンドを起動したか」をログで見極めるのが分岐点です。 起動していればコマンド側(フルパス・\%・権限・シバン)、起動していなければ crontab 側(デーモン・書式・最終行の改行・ユーザーフィールド)。本記事の表を上から なぞれば、「なんとなく再起動して様子を見る」よりはるかに速く原因に到達できます。

When a cron job never runs, split the problem in two with the logs. Ifjournalctl -u cron (or /var/log/cron on RHEL) shows aCMD (...) line, cron started your job and the command itself failed: the usual suspects are the minimal PATH (just /usr/bin:/bin, so every binary needs an absolute path), a missing execute bit, a /bin/sh-incompatible script without a shebang, or an unescaped % — crontab treats % as a newline and feeds the rest to stdin, so date +%Y%m%d silently becomes date +. If there is no CMDline, the crontab itself is the problem: the daemon may be stopped, the entry may be in another user's crontab, the file may lack its trailing newline, or you mixed up the formats — system crontabs (/etc/crontab,/etc/cron.d/) need a sixth user field that per-user crontabs reject. Always append >> /tmp/job.log 2>&1 while debugging so cron stops discarding the evidence, and dump env from a one-minute job to see the real environment.

Cron Parser

「0 3 * * 1-5」は何時に走る? 修正した cron 式を貼り付けるだけで、意味の解説と次回実行予定がその場で確認できます。デプロイ前の最終チェックに。

今すぐ試す →

関連ツール / Related tools

関連ガイド / Related guides