crontabが機能しないのはなぜですか?どうすればトラブルシューティングできますか?


225

これは、cronとcrontabの使用に関する標準的な質問です。

コミュニティはあなたの質問に対する答えが下にあることをかなり確信しているので、あなたはここに導かれました。あなたの質問が以下に回答されていない場合、回答はコミュニティがあなたを助けるのに役立つ情報を集めるのに役立ちます。この情報は、元の質問に編集する必要があります。

crontabが機能しないのはなぜですか?どうすればトラブルシューティングできますか?'以下に見ることができます。これcronにより、crontabが強調表示されたシステムがアドレス指定されます。


2
これは、crontabが AskUbuntuで動作しない理由の大きなduです。
ダンダスカレスク

1
@DanDascalescuエリックがより多くの担当者を取得する必要があるよう
です

1
Server Fault SEに参加しました(101担当者のみ)が、この質問に-1を付けたいと思います!この質問は担当者を得るためだけに作られましたか?@IamtheMostStupidPerson完全にあなたに同意します...
Holyprogrammer

これらの13歳のパダワンの西洋のイデオロギーは、超新星のように教科書でもあり、盲目でもあります。あなたの両方の質問に答えるために:はい、私は担当者のためにそれをしました、そして、はい、エリックはより多くの評判を得る必要があります。さらに多くの担当者が必要ですか?? もっと。 youtu.be/IaDt9T7BF38?t=262
Eric Leschinski

回答:


317

crontabに関連するすべての問題/問題を修正する方法(Linux)


これはコミュニティWikiです。この回答に誤りがある場合、または追加情報がある場合は編集してください。


まず、基本的な用語:

  • cron(8)は、スケジュールされたコマンドを実行するデーモンです。
  • crontab(1)は、ユーザーのcrontab(5)ファイルを変更するために使用されるプログラムです。
  • crontab(5)は、cron(8)の指示を含むユーザーごとのファイルです。

次に、cronに関する教育:

システム上のすべてのユーザーは、独自のcrontabファイルを持つことができます。ルートおよびユーザーcrontabファイルの場所はシステムに依存しますが、通常は以下にあります/var/spool/cron

システム全体の/etc/crontabファイルがあり、/etc/cron.dディレクトリにはcrontabフラグメントが含まれている場合があり、crontabフラグメントもcronによって読み取られ、アクションが実行されます。一部のLinuxディストリビューション(Red Hatなど)/etc/cron.{hourly,daily,weekly,monthly}には、ディレクトリ、スクリプト、およびその中のスクリプトが1時間/日/週/月ごとにルート権限で実行されるものもあります。

rootは常にcrontabコマンドを使用できます。通常のユーザーにはアクセスが許可される場合と許可されない場合があります。コマンドでcrontabファイルを編集してcrontab -e保存すると、crondは基本的な有効性を確認しますが、crontabファイルが正しく形成されていることを保証しません。cron.denyどのユーザーがcronを使用できないかを指定するというファイルがあります。cron.denyファイルの場所はシステムに依存し、すべてのユーザーがcronを使用できるようになりますどの削除することができます。

コンピューターの電源が入っていないか、crondデーモンが実行されておらず、コマンドの実行日時が過ぎている場合、crondは過去のクエリをキャッチアップして実行しません。

crontabの詳細、コマンドの定式化方法:

crontabコマンドは1行で表されます。\コマンドを複数行にわたって拡張することはできません。ハッシュ(#)記号はコメントを表し、その行のすべてがcronによって無視されます。先頭の空白と空白行は無視されます。

%コマンドでパーセント記号()を使用するときは、十分に注意してください。エスケープ\%されない限り、それらは改行に変換され、最初のエスケープされていないものが%標準入力のコマンドに渡されます。

crontabファイルには2つの形式があります。

  • ユーザーcrontab

    # Example of job definition:
    # .---------------- minute (0 - 59)
    # |  .------------- hour (0 - 23)
    # |  |  .---------- day of month (1 - 31)
    # |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
    # |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7)
    # |  |  |  |  |
    # *  *  *  *  *   command to be executed
    
  • システム全体/etc/crontab/etc/cron.dフラグメント

    # Example of job definition:
    # .---------------- minute (0 - 59)
    # |  .------------- hour (0 - 23)
    # |  |  .---------- day of month (1 - 31)
    # |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
    # |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7)
    # |  |  |  |  |
    # *  *  *  *  * user-name  command to be executed
    

後者にはユーザー名が必要であることに注意してください。コマンドは、指定されたユーザーとして実行されます。

行の最初の5つのフィールドは、コマンドを実行する時間を表します。時間指定では、数字または該当する日/月名を使用できます。

  • フィールドはスペースまたはタブで区切られます。
  • コンマ(,)を使用してリストを指定します(例:1,4,6,8)。これは、1,4,6,8で実行することを意味します。
  • 範囲はダッシュ(-)で指定され、1〜3、9〜12、1〜3、9〜12などのリストと組み合わせることができます。
  • /文字を2でおき5(2,7,12,17,22 ...)を開始することを意味ステップ例えば2/5を導入するために使用することができます。彼らは終わりを超えてラップしません。
  • *フィールド内のアスタリスク()は、そのフィールドの範囲全体を示します(たとえば0-59、分フィールド)。
  • 範囲と手順を組み合わせることができます。たとえば*/2、関連するフィールドの最小値から始まり、2分ごとに0を意味します。たとえば、0分(0,2 ... 58)、1月(1,3 ... 11)などです。

cronコマンドのデバッグ

メールをチェックしてください!

デフォルトでは、cronはコマンドの出力をコマンドを実行しているユーザーにメールで送信します。出力がない場合、メールは送信されません。cronから別のアカウントにメールを送信する場合は、crontabファイルでMAILTO環境変数を設定できます。たとえば、

MAILTO=user@somehost.tld
1 2 * * * /path/to/your/command

自分で出力をキャプチャする

stdoutとstderrをファイルにリダイレクトできます。出力をキャプチャするための正確な構文は、cronが使用しているシェルによって異なる場合があります。以下に、すべての出力をファイルに保存する2つの例を示します/tmp/mycommand.log

1 2 * * * /path/to/your/command &>/tmp/mycommand.log
1 2 * * * /path/to/your/command >/tmp/mycommand.log 2>&1

ログを見てください

Cronは、syslogを介してアクションをログに記録します。syslogは(セットアップに応じて)/var/log/cronまたはに移動し/var/log/syslogます。

必要に応じて、たとえば次のようにcronステートメントをフィルタリングできます

grep CRON /var/log/syslog 

cronの基本について説明したので、ファイルの場所と使用方法について、一般的な問題を見てみましょう。

cronが実行されていることを確認します

cronが実行されていない場合、コマンドはスケジュールされません...

ps -ef | grep cron | grep -v grep

あなたのようなものを取得する必要があります

root    1224   1  0 Nov16 ?    00:00:03 cron

または

root    2018   1  0 Nov14 ?    00:00:06 crond

再起動しない場合

/sbin/service cron start

または

/sbin/service crond start

他の方法があるかもしれません。ディストリビューションが提供するものを使用してください。

cronは、制限された環境でコマンドを実行します。

利用できる環境変数は非常に限られています。一般的に、あなただけのような定義されたいくつかの変数を、得るでしょう$LOGNAME$HOME$PATH

特に注意すべきは、PATHに制限されていること/bin:/usr/binです。「私のcronスクリプトが機能しない」問題の大部分は、この制限されたパスが原因です。コマンドが別の場所にある場合、いくつかの方法でこれを解決できます。

  1. コマンドへのフルパスを指定します。

    1 2 * * * /path/to/your/command
    
  2. crontabファイルに適切なPATHを提供します

    PATH=/usr:/usr/bin:/path/to/something/else
    1 2 * * * command 
    

コマンドに他の環境変数が必要な場合は、crontabファイルでも定義できます。

cronは、cwd == $ HOMEでコマンドを実行します

実行するプログラムがファイルシステムのどこに存在するかに関係なく、cronが実行されるときのプログラムの現在の作業ディレクトリは、ユーザーのホームディレクトリになります。プログラム内のファイルにアクセスする場合、相対パスを使用する場合、または(できれば)あらゆる場所で完全修飾パスを使用する場合、これを考慮する必要があります。

crontabの最後のコマンドが実行されない

Cronでは、通常、コマンドを改行で終了する必要があります。crontabを編集します。最後のコマンドを含む行の最後に移動して、新しい行を挿入します(Enterキーを押します)。

crontab形式を確認してください

/ etc / crontabのユーザーcrontab形式のcrontabまたは/etc/cron.dのフラグメントを使用することはできません。ユーザー形式のcrontabでは、行の6番目の位置にユーザー名が含まれませんが、システム形式のcrontabではユーザー名が含まれ、そのユーザーとしてコマンドが実行されます。

/ etc / cronにファイルを置きます。{hourly、daily、weekly、monthly}実行しません

  • ファイル名に拡張子がないことを確認してくださいrun-parts
  • ファイルに実行権限があることを確認してください。
  • スクリプトを実行するときに何を使用するかをシステムに指示します(例:#!/bin/sh先頭に配置)

Cron日付関連のバグ

ユーザーまたはシステムの更新、タイムゾーンなどによって日付が最近変更された場合、crontabは不規則に動作し始め、奇妙なバグを示します。これは、その下から時間が変わったときに「望むことをする」ことを試みるcrontabの試みです。「分」フィールドは、時間が変更されると無効になります。このシナリオでは、アスタリスクのみが受け入れられます。cronを再起動し、インターネットに接続せずに再試行します(したがって、タイムサーバーのいずれかに日付をリセットする機会はありません)。

パーセント記号、再び

パーセント記号に関するアドバイスを強調するために、cronがパーセント記号を使用する例を次に示します。

# cron entry
* * * * * cat >$HOME/cron.out%foo%bar%baz

3行を含む〜/ cron.outファイルを作成します

foo
bar
baz

これは、dateコマンドの使用時に特に邪魔になります。パーセント記号を必ずエスケープしてください

* * * * * /path/to/command --day "$(date "+\%Y\%m\%d")"

また、 'restricted env'セクションで、共有ライブラリが見つからないためにcronタスクが失敗した場合にLD_LIBRARY_PATHに追加のディレクトリを設定する必要がある場合があることを記載することもできます。
DavidJ

35 1,5-23 / 2 * * * 35,1,5,7,9、..の代わりにdo_something .. * * *さらに、このcrontab.guruは作成したエントリを翻訳します。人間の言語。
デニス・ノルティ

1
出力キャプチャは、shシェルのせいかもしれません。これはより移植性があると思います ... /path/to/your/command >/tmp/mycommand.log 2>&1
。– chus

これは私のために働いた:sudo apt-get install postfix
jmunsch

cronジョブはファイルの重さにも依存しますか?cronを使用してPythonで単純なhello worldを実行したため、動作しました。しかし、私の2番目のコードは少し重く、通常は実行されますが、cronを使用すると、ファイルに何も出力されません。
デベンドラバート

22

Debian Linuxとその派生物(Ubuntu、Mintなど)には、cronジョブの実行を妨げる可能性のあるいくつかの特性があります。特に、のファイルは次の条件/etc/cron.d/etc/cron.{hourly,daily,weekly,monthly}満たしている必要があります。

  • ルートが所有する
  • rootのみが書き込み可能
  • グループまたは他のユーザーによる書き込み不可
  • ドット「。」のない名前があります または「-」と「_」以外の特殊文字

最後の1つは、疑いを持たないユーザーを定期的に傷つけます。名前のこれらのフォルダのいずれかで、任意のスクリプトの特定にはwhatever.shmycron.pytestfile.pl、などでしょうではないこれまで、実行すること。

私の経験では、この特定の点が、Debianおよび派生物でcronジョブを実行しない最も頻繁な理由でした。

man cron必要に応じて、詳細を参照してください。


19

cronジョブが機能しなくなった場合は、パスワードの有効期限が切れていないことを確認してください。一度切れると、すべてのcronジョブが停止するためです。以下のような
メッセージが表示され/var/log/messages、ユーザーの認証に関する問題が示されます。

(username) FAILED to authorize user with PAM (Authentication token is no longer valid; new one required)


2
これも取得しました(エラーメッセージファイル/ var / log / syslog)。私の場合、作成時にルートパスワードを(オプションで)別のパスワードにリセットするDigitalOceanボックスです。残念。修正は次のようなものですsudo -u root passwd
-rogerdpack

12

珍しい不規則なスケジュール

Cronはすべて非常に基本的なスケジューラーと見なされており、この構文では、管理者が一般的ではないスケジュールをわずかに作成することは容易ではありません。

command5分ごとに実行すると一般的に説明される次のジョブを検討してください。

*/5 * * * * /path/to/your/command

対:

*/7 * * * * /path/to/your/command

これ常にcommand 7分ごとに実行されるわけではあり ません

ことを忘れないでください/文字はステップを導入するために使用することができますが、手順は、シリーズなどの終わりを超えてラップしていないことを*/7数分からすべての7分に一致し0-59 、0,7,14,21,28,35,42,49すなわち56しかし、一時間と次の間があるでしょうバッチ間のわずか4分後に、 00:56新シリーズが始まりで 01:0001:07など(バッチが動作しません01:0301:1001:17など)。


代わりに何をしますか?

複数のバッチを作成する

単一のcronジョブではなく、組み合わせて複数のバッチを作成し、目的のスケジュールを作成します。

たとえば、40分(00:00、00:40、01:20、02:00など)ごとにバッチを実行するには、2つのバッチを作成します。1つは偶数時間に2回実行し、2つ目は奇数時間にのみ実行します。

# The following lines create a batch that runs every 40 minutes i.e.

# runs on   0:00, 0:40,        02:00, 02:40         04:00 etc to 22:40
0,40 */2 * * * /path/to/your/command

# runs on               01:20,               03:20,       etc to 23:20
20 1/2 * * * /path/to/your/command

# Combined: 0:00, 0:40, 01:20, 02:00, 02:40, 03:20, 04:00 etc.

バッチの実行頻度を減らす

バッチを7分ごとに実行するのではなく、複数のバッチに分割するのが難しいスケジュールではなく、10分ごとに実行するだけです。

バッチをより頻繁に開始します(ただし、複数のバッチが同時に実行されるのを防ぎます)

バッチランタイムが増加/変動し、その後、同じバッチの後続の実行が重複して同時に実行されるのを防ぐために、少しの追加の安全マージンでバッチがスケジュールされるため、多くの奇妙なスケジュールが進化します。

代わりに、異なる考え方をして、以前の実行がまだ終了していない場合は正常に失敗するが、それ以外の場合は実行されるcronjobを作成します。このQ&Aを参照してください。

* * * * * /usr/bin/flock -n /tmp/fcj.lockfile /usr/local/bin/frequent_cron_job 

/ usr / local / bin / frequent_cron_jobの前回の実行が完了すると、すぐに新しい実行が開始されます。

バッチをより頻繁に開始します(ただし、条件が正しくない場合は正常に終了します)

cron構文は限られているため、バッチジョブ自体(または既存のバッチジョブのラッパースクリプト)に、より複雑な条件とロジック配置することを決定できます。これにより、お気に入りのスクリプト言語の高度な機能を利用して、コードにコメントを付けたり、crontabエントリ自体の読みにくい構成要素を防ぐことができます。

bashでは、seven-minute-job次のようになります。

#!/bin/bash
# seven-minute-job
# This batch will only run when 420 seconds (7 min) have passed
# since the file /tmp/lastrun was either created or updated

if [ ! -f /tmp/lastrun ] ; then
    touch /tmp/lastrun
fi

if [ $(( $(date +%s) - $(date -r /tmp/lastrun +%s) )) -lt 420 ] ; then
     # The minimum interval of 7 minutes between successive batches hasn't passed yet.
    exit 0
fi

####  Start running your actual batch job below

/path/to/your/command

#### actual batch job is done, now update the time stamp
date > /tmp/lastrun
#EOF

これを毎分安全に実行(試行)できます:

* * * * * /path/to/your/seven-minute-job

日付が1の間でもされていないときに、異なるが、同様の問題は、単に毎週月曜日と終了を実行するバッチをスケジュールなど毎月第一月曜日(又は第二水曜日)上で実行するバッチをスケジュールするでしょうSTまたは7 番目と曜日は月曜日ではありません。

#!/bin/bash
# first-monday-of-the-month-housekeeping-job

# exit if today is not a Monday (and prevent locale issues by using the day number) 
if [ $(date +%u) != 1 ] ; then
  exit 0
fi

# exit if today is not the first Monday
if [ $(date +%d) -gt 7 ] ; then
  exit 0
fi

####  Start running your actual batch job below

/path/to/your/command

#EOF

毎週月曜日に安全に(試行)実行できます:

0 0 * * 1 /path/to/your/first-monday-of-the-month-housekeeping-job

cronを使用しないでください

ニーズが複雑な場合は、複雑なスケジュール(複数のサーバーに分散)を実行するように設計され、トリガー、ジョブ依存関係、エラー処理、再試行、再試行の監視などをサポートするより高度な製品の使用を検討できます。業界用語は「エンタープライズ」 「ジョブスケジューリングおよび/または「ワークロードの自動化」。


8

PHP固有

次のようなcronジョブがある場合:

php /bla/bla/something.php >> /var/logs/somelog-for-stdout.log

そして、エラーが予想される場合、それらはあなたに送信されますが、そうではありません-これを確認してください。

デフォルトでは、PHPはエラーをSTDOUTに送信しません。@see https://bugs.php.net/bug.php?id=22839

これを修正するには、cliのphp.iniまたは行(またはPHPのbashラッパー)に以下を追加します。

  • --define display_startup_errors = 1
  • --define display_errors = 'stderr'

1番目の設定では、「Memory oops」や2番目の致命的エラーが発生し、すべてをSTDERRにリダイレクトします。すべてがログに記録されるのではなく、ルートのメールに送信されるため、よく眠れるようになった後にのみ。


2
このエラーレポートは2007年に閉じられ、PHP 5.2+ブランチにパッチのステータスが追加されました。これが必要ですか?PHP 5.4を試してみましたが、うまくいくようです。(ただし、PHP 4にはまだ必要です)。
Xeoncross 14年

@Xeoncross回答日を参照:)
gaRex 14年

1
はい、2013年に回答し、チケットは2007年に戻っていたので、それが私を混乱させました。
Xeoncross 14年

0

完全性のためにここから私の答え追加し、別の潜在的に役立つリソースを追加します:

cronユーザーが異なる持っている$PATHあなたが行うよりも:

ユーザーがcrontabエントリで頻繁に発生する問題は、ログインしているユーザーとしてcron実行するのとは異なる実行を忘れているenvironmentことです。たとえば、ユーザーは自分の$HOMEディレクトリにプログラムまたはスクリプトを作成し、次のコマンドを入力して実行します。

$ ./certbot ... 

コマンドは、彼のコマンドラインから完全に実行されます。次に、ユーザーはそのコマンドを自分のに追加しますcrontabが、これが機能しないことがわかります。

*/10 * * * * ./certbot ....

この場合の失敗の理由は、ログインして./いるcronユーザーとは異なるユーザーの場所であるためです。つまり、environment違います!PATHはの一部でありenvironment、通常はcronユーザーによって異なります。この問題を複雑にしていることであるenvironmentためにはcron、すべてのために同じではありません* nixのディストリビューション、およびそこにあるの複数のバージョンは、cron

この特定の問題に対する簡単な解決策cronは、crontabエントリの完全なパス指定をユーザーに提供することです。

0 22 * * * /path/to/certbot .....

何がcronユーザーのではenvironment

場合によっては、システムの完全environmentな仕様を知る必要cronがあるかもしれません(または単に興味があるかもしれません)。ユーザーにとっては何であり、私たちのものとはどう違うのですか?environmentcronさらに、environment別のcronユーザーの情報を知る必要があるかもしれません- root例えば... rootユーザーは何environmentを使用していcronますか?これを学ぶ1つの方法は、次のことcronを教えてもらうことです。

  1. ~/次のように(または選択したエディターを使用して)ホームディレクトリ()にシェルスクリプトを作成します。
$ nano ~/envtst.sh
  1. システム/ユーザーを調整した後、エディターに次のように入力します。
#!/bin/sh 
/bin/echo "env report follows for user "$USER >> /home/you/envtst.sh.out 
/usr/bin/env >> /home/you/envtst.sh.out 
/bin/echo "env report for user "$USER" concluded" >> /home/you/envtst.sh.out
/bin/echo " " >> /home/you/envtst.sh.out
  1. ファイルを保存し、エディターを終了して、ファイルのアクセス許可を実行可能ファイルとして設定します。
$ chmod a+rx ~/envtst.sh
  1. 作成したスクリプトを実行し、出力を確認します/home/you/envtst.sh.out。この出力には、$USER次のようにログインしている現在の環境が表示されます。
$ ./envtst.sh $$ cat /home/you/envtst.sh.out
  1. crontab編集用に開きます:
$ crontab -e -u root
  1. の下部に次の行を入力しますcrontab
* * * * *  /home/you/envtst.sh >> /home/you/envtst.sh.err 2>&1

回答:出力ファイル/home/you/envtst.sh.outにはenvironment、「root cronユーザー」のリストが含まれます。それがわかったら、crontabそれに応じてエントリを調整します。

crontabエントリに必要なスケジュールを指定できません。

のスケジュールエントリcrontabはもちろんで定義されてman crontabおり、これを読む必要があります。ただし、man crontabスケジュールを読んで理解することは、2つの異なることです。そして、スケジュール仕様の試行錯誤は非常に退屈になる可能性があります。幸いなことに、役立つリソースがあります:crontabの達人。。スケジュール仕様を入力すると、スケジュールがわかりやすい英語で説明されます。

最後に、ここにある他の回答の1つと重複する危険があるcrontabため、スケジュールするジョブが1つしかないため、1つのエントリに制限されていると思わないでください。crontab必要なスケジュールを取得するために必要な数のエントリを自由に使用できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.