Cron式のよくある間違いと回避方法
最も一般的なcron式の間違いと修正方法を学びます。Cronでのタスクスケジューリングにおけるこれらの落とし穴を回避しましょう。
Having trouble? Try the tool
Test your with our interactive tool
Top 10 Common Mistakes
相対パスではなく絶対パスを使用する
Symptoms
- • コマンドが "command not found" エラーで失敗する
- • スクリプトは手動では実行できるがcronでは失敗する
- • カレントディレクトリに依存した断続的な失敗
Root Cause
Cronジョブは最小限の環境で実行され、作業ディレクトリは予測不能(通常ユーザーのホームディレクトリまたは/root)です。相対パスはカレントディレクトリに依存するため、cronコンテキストでは保証されません。
Solution
すべてのコマンド、スクリプト、ファイル参照に常に絶対パスを使用してください。必要に応じて、コマンドの前に`cd`で作業ディレクトリを明示的に設定してください。
❌ Wrong
# 間違い - 相対パスを使用
*/5 * * * * python script.py
*/5 * * * * ./scripts/backup.sh
✅ Correct
# 正解 - 絶対パスを使用
*/5 * * * * /usr/bin/python3 /opt/scripts/script.py
*/5 * * * * cd /opt/scripts && ./backup.sh
*/5 * * * * /opt/scripts/backup.sh
環境変数を無視する
Symptoms
- • スクリプトはシェルでは動作するがcronでは失敗する
- • 手動実行時はPATHにあるコマンドが見つからない
- • 環境設定が欠如しているためアプリケーションが失敗する
Root Cause
Cronは厳しく制限された環境で実行されます - 通常HOME、LOGNAME、SHELL、最小限のPATH(/usr/bin:/bin)のみです。シェルプロファイル(.bashrc、.zshrc)の環境変数は読み込まれません。
Solution
crontabまたはスクリプトで必要な環境変数を明示的に定義してください。PATHとアプリケーション固有の変数を設定してください。
❌ Wrong
# 間違い - シェル環境を想定
*/5 * * * * python script.py
*/5 * * * * ./data_process.sh
✅ Correct
# 正解 - 明示的な環境変数
PATH=/usr/local/bin:/usr/bin:/bin
NODE_ENV=production
DB_HOST=localhost
*/5 * * * * /usr/bin/python3 /opt/scripts/script.py
*/5 * * * * /opt/scripts/data_process.sh
出力とエラーのリダイレクトを忘れる
Symptoms
- • 失敗したcronジョブをデバッグする方法がない
- • 出力がシステムメールに送られる(通常は読まれない)
- • ログに記録されていない出力でディスク容量が満杯になる
Root Cause
デフォルトでは、cronはすべての出力をジョブ所有者のメールに送信します。明示的なリダイレクトがない場合、エラーとログはメールまたは虚空に失われます。
Solution
常にstdoutとstderrをログファイルにリダイレクトしてください。追加には`>>`を使用し、両方のストリームをリダイレクトするには`2>&1`を使用してください。
❌ Wrong
# 間違い - 出力はメールへ行くか失われる
*/5 * * * * /opt/scripts/check.sh
✅ Correct
# 正解 - 出力はファイルにログされる
*/5 * * * * /opt/scripts/check.sh >> /var/log/check.log 2>&1
*/5 * * * * /opt/scripts/check.sh 1>> /var/log/check.out.log 2>> /var/log/check.err.log
日付と曜日の両方を使用する
Symptoms
- • ジョブが予想より頻繁に実行される
- • ジョブが予期しない日に実行される
- • ジョブ実行タイミングに関する混乱
Root Cause
標準cronでは、日付(1-31)と曜日(0-6)の両方が制限されている(非*)場合、いずれかのフィールドが一致するとジョブが実行されます。これは混乱の一般的な原因です。
Solution
一方のフィールドを制限する場合、他方には`?`または`*`を使用してください。「15日でかつ月曜日のみ」が必要な場合は、スクリプト自体にロジックを実装してください。
❌ Wrong
# 間違い - どちらか15日またはどちらか金曜日に実行
0 0 15 * 5 /script.sh # 毎月15日と毎金曜日に実行
✅ Correct
# 正解 - 金曜日の15日のみ実行(スクリプト内ロジック)
0 0 * * 5 /scripts/check_friday_15th.sh # スクリプトが今日が15日かチェック
# または、非制限フィールドには?を使用するモダンcron
0 0 15 * ? /scripts/monthly.sh # 15日に実行、曜日は無視
0 0 ? * 5 /scripts/weekly.sh # 毎金曜日に実行、日は無視
スクリプトの実行権限がない
Symptoms
- • Cronジョブが "Permission denied" で失敗する
- • ジョブはスケジュールされているが実行されない
- • ログにエラーや意味不明なエラーがない
Root Cause
スクリプトは直接実行するために実行権限(+x)を持っている必要があります。実行権限がないと、スクリプトはcronから呼び出されません。
Solution
常に`chmod +x`でスクリプトに実行権限を設定してください。または、インタープリタを使ってスクリプトを明示的に呼び出します(例:`bash script.sh`)。
❌ Wrong
# 間違い - スクリプトが実行可能でない可能性
*/5 * * * * /opt/scripts/myscript.sh
✅ Correct
# 正しいオプション:
# 1. スクリプトを実行可能にする
$ chmod +x /opt/scripts/myscript.sh
*/5 * * * * /opt/scripts/myscript.sh
# 2. インタープリタで呼び出す
*/5 * * * * /bin/bash /opt/scripts/myscript.sh
# 3. shebangを追加して実行可能にする
#!/bin/bash
# スクリプト内容
タイムゾーン処理が不適切
Symptoms
- • ジョブが間違った時間に実行される
- • ジョブが1時間早くまたは遅く実行される
- • システム間での動作が不一致
Root Cause
Cronはシステム設定のタイムゾーンを使用します。クラウド環境やコンテナでは、ローカルタイムゾーンではなくUTCの場合があります。タイムゾーン変更(夏時間)もスケジュールに影響します。
Solution
crontabでCRON_TZを使ってタイムゾーンを明示的に設定するか、一貫してUTCを使用してください。cronが想定するタイムゾーンを文書化してください。
❌ Wrong
# 間違い - システムタイムゾーンを想定(変化する可能性)
0 9 * * * /scripts/morning_report.sh # 午前9時に実行、しかしどのタイムゾーン?
✅ Correct
# 正解 - 明示的なタイムゾーン
CRON_TZ=Asia/Tokyo
0 9 * * * /scripts/morning_report.sh # 午前9時日本時間
# またはUTCを使用して文書化
# すべてのcron時刻はUTC
0 0 * * * /scripts/morning_report.sh # 日本時間午前9時 = UTC深夜0時
重複するジョブを処理しない
Symptoms
- • 同じジョブの複数のインスタンスが同時に実行される
- • 重複プロセスによるリソース枯渇
- • 同時書き込みによるデータ破損
- • 出力ファイルでの競合状態
Root Cause
ジョブの実行時間がスケジュール間隔より長い場合、cronは最初のインスタンスがまだ実行中に別のインスタンスを開始します。これにより重複実行が発生します。
Solution
ファイルロック(flock)またはプロセスチェック(pgrep)を使用して、1つのインスタンスのみが実行されるようにしてください。重要なジョブには、適切なミューテックス処理でsystemdまたはsupervisordを使用してください。
❌ Wrong
# 間違い - スクリプトが5分より長く実行される場合、重複が開始
*/5 * * * * /scripts/data_sync.sh
✅ Correct
# 正解 - 重複実行を防止
# 方法1: flock
*/5 * * * * /usr/bin/flock -w 0 /tmp/data_sync.lock -c /scripts/data_sync.sh
# 方法2: スクリプトでのpidチェック
if [ -f /tmp/myscript.pid ]; then
pid=$(cat /tmp/myscript.pid)
if ps -p $pid > /dev/null; then
echo "Already running"
exit 1
fi
fi
echo $$ > /tmp/myscript.pid
trap "rm -f /tmp/myscript.pid" EXIT
ピーク時間にリソース集中タスクをスケジュールする
Symptoms
- • 営業時間中のシステムパフォーマンス低下
- • システムの遅さに関する苦情
- • Cronジョブがユーザーアクティビティと競合する
- • 予測可能な時間の負荷スパイク
Root Cause
リソース集中タスク(バックアップ、バッチ処理、レポート)がピーク使用時間にスケジュールされると、アクティブユーザーとCPU、メモリ、I/Oを競合します。
Solution
リソース集中タスクをオフピーク時間(深夜、早朝)にスケジュールしてください。システム負荷を監視し、スケジュールに応じて調整してください。
❌ Wrong
# 間違い - 営業日に重いバックアップ
0 10 * * * /scripts/heavy_backup.sh # 午前10時 - ピークタイム
0 14 * * * /scripts/data_processing.sh # 午後2時 - 同样に混雑
✅ Correct
# 正解 - オフピークスケジューリング
0 2 * * * /scripts/heavy_backup.sh # 深夜2時 - 最小アクティビティ
0 3 * * 0 /scripts/weekly_report.sh # 日曜日深夜3時 - ウィークエンド
0 6 * * 1 /scripts/monthly_cleanup.sh # 月曜朝6時 - 仕事前
# 実行前にシステム負荷をチェック
*/30 * * * * /usr/bin/bash -c '[[ $(cat /proc/loadavg | awk '{print $1}'`) < 2.0 ]] && /scripts/light_task.sh'
新しいCronジョブをテストしない
Symptoms
- • ジョブが本番で静かに失敗する
- • 展開後に構文エラーが発見される
- • cron環境での予期しない動作
- • 不適切な時に緊急修正が必要
Root Cause
テスト環境で動作するcron式とスクリプトは、異なるパス、環境変数、権限、システム設定のために本番で失敗する可能性があります。
Solution
本番環境に展開する前に、常にcronジョブをテストしてください。スクリプトを手動でテストし、cron式構文を検証し、最初の実行を監視してください。
❌ Wrong
# 間違い - テストなしで本番に
0 0 * * * /scripts/new_feature.sh # 本番に直接追加
✅ Correct
# 正解 - テストワークフロー
# 1. スクリプトを手動でテスト
$ /scripts/new_feature.sh
# 2. cron構文を検証
$ crontab -l | grep new_feature
# またはオンライン検証器を使用
# 3. まず頻繁な時間でテスト
*/5 * * * * /scripts/new_feature.sh # 5分ごとに実行してテスト
# チェック: tail -f /var/log/new_feature.log
# 4. 検証後、ターゲットスケジュールに更新
0 0 * * * /scripts/new_feature.sh
Cronサービスステータスを無視する
Symptoms
- • Cronジョブが謎のように実行停止する
- • ログやエラーメッセージがない
- • 再起動後は動作するが後で失敗する
- • スケジューリングが信頼できない
Root Cause
Cronまたはcrondサービスが停止、無効化、または障害が発生している可能性があります。システム更新または設定変更は、通知なしにサービスを停止する可能性があります。
Solution
Cronサービスステータスを監視し、アラートを設定してください。ブート時に起動するようにサービスを有効にしてください。
❌ Wrong
# 間違い - cronが常に実行されていると想定
# 監視やチェックなし
✅ Correct
# 正解 - cronサービスを監視
# サービスステータスをチェック
$ systemctl status cron
$ systemctl status crond
# ブート時に有効化
$ sudo systemctl enable cron
$ sudo systemctl start cron
# ヘルスチェックで監視
*/15 * * * * /usr/bin/systemctl is-active cron || /usr/bin/systemctl restart cron
# cron失敗時にアラート
*/15 * * * * /usr/bin/systemctl is-active --quiet cron || echo "Cron stopped!" | mail -s "Alert" [email protected]