これは、cronとcrontabの使用に関する 標準的な質問 です。
コミュニティはあなたの質問に対する答えが以下にあると確信しているので、あなたはここに導かれました。以下で質問に対する回答がない場合、回答は、コミュニティがあなたを助けるのに役立つ情報を収集するのに役立ちます。この情報は、元の質問に編集する必要があります。
「なぜ私のcrontabが機能しないのですか、そしてどのようにトラブルシューティングできますか?」の答えは以下にあります。これは、crontabが強調表示されたcron
システムに対処します。
これは community wiki です。この回答に誤りがあることに気付いた場合、または追加情報がある場合は、編集してください。
システム上のすべてのユーザーは、独自のcrontabファイルを持っている場合があります。ルートとユーザーのcrontabファイルの場所はシステムによって異なりますが、通常は/var/spool/cron
の下にあります。
システム全体の/etc/crontab
ファイルがあり、/etc/cron.d
ディレクトリにはcrontabフラグメントが含まれている場合があります。一部のLinuxディストリビューション(Red Hatなど)にも/etc/cron.{hourly,daily,weekly,monthly}
があり、これはディレクトリであり、スクリプトは1時間/日/週/月ごとにroot権限で実行されます。
rootは常にcrontabコマンドを使用できます。通常のユーザーはアクセスを許可される場合とされない場合があります。コマンドcrontab -e
を使用してcrontabファイルを編集し、保存すると、crondは基本的な有効性をチェックしますが、crontabファイルが正しく形成されることを保証しません。 cron.deny
というファイルがあり、cronを使用できないユーザーを指定します。 cron.deny
ファイルの場所はシステムに依存しており、すべてのユーザーがcronを使用できるように削除できます。
コンピューターの電源が入っていないか、crondデーモンが実行されておらず、コマンドを実行する日付/時刻が過ぎている場合、crondはキャッチアップせず、過去のクエリを実行しません。
Crontabコマンドは1行で表されます。 \
を使用して、コマンドを複数行に拡張することはできません。ハッシュ(#
)記号はコメントを表し、その行のすべてがcronによって無視されることを意味します。先頭の空白と空白行は無視されます。
コマンドでパーセント(%
)記号を使用する場合は、十分に注意してください。エスケープされない限り\%
は改行に変換され、エスケープされていない最初の%
以降のすべてがstdinのコマンドに渡されます。
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から始まり、5ごとに開始することを意味します(2、7、12、17、22 ...)。彼らは終わりを越えて折り返さない。*
)は、そのフィールドの範囲全体を示します(たとえば、分フィールドの場合は0-59
)。*/2
は、関連するフィールドの最小値から開始し、その後2ごとに開始することを意味します。 0は分(0,2 ... 58)、1は月(1,3 ... 11)など.デフォルトでは、cronはコマンドからの出力を、コマンドを実行しているユーザーにメールで送信します。出力がない場合、メールは送信されません。 cronから別のアカウントにメールを送信する場合は、crontabファイルでMAILTO環境変数を設定できます。
[email protected]
1 2 * * * /path/to/your/command
Stdoutとstderrをファイルにリダイレクトできます。出力をキャプチャするための正確な構文は、シェルcronが使用しているものによって異なる場合があります。次に、すべての出力を/tmp/mycommand.log
のファイルに保存する2つの例を示します。
1 2 * * * /path/to/your/command &>/tmp/mycommand.log
1 2 * * * /path/to/your/command >/tmp/mycommand.log 2>&1
Cronはsyslogを介してアクションをログに記録します。これは(設定によって異なりますが)/var/log/cron
または/var/log/syslog
に頻繁に送られます。
必要に応じて、cronステートメントを次のようにフィルタリングできます。
grep CRON /var/log/syslog
ファイルの場所とそれらの使用方法について、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
他の方法があるかもしれません。ディストリビューションが提供するものを使用してください。
使用できる環境変数は非常に限られている可能性があります。通常、$LOGNAME
、$HOME
、$PATH
など、定義されているいくつかの変数のみを取得します。
特に注目すべきは、PATH
が/bin:/usr/bin
に制限されていることです。 「私のcronスクリプトが機能しない」問題の大部分は、この限定的なパスが原因です。コマンドが別の場所にある場合、いくつかの方法でこれを解決できます。
コマンドの絶対パスを入力します。
1 2 * * * /path/to/your/command
Crontabファイルに適切なPATHを提供します
PATH=/bin:/usr/bin:/path/to/something/else
1 2 * * * command
コマンドで他の環境変数が必要な場合は、crontabファイルでも定義できます。
実行するプログラムがファイルシステムのどこにあるかに関係なく、cronを実行したときのプログラムの現在の作業ディレクトリはユーザーのホームディレクトリになります。プログラム内のファイルにアクセスする場合、相対パスを使用する場合はこれを考慮する必要があります。または、(できれば)どこでも完全修飾パスを使用するだけで、誰もが混乱するのを防ぐことができます。
Cronでは通常、コマンドを改行で終了する必要があります。 crontabを編集します。最後のコマンドを含む行の終わりに移動し、新しい行を挿入します(Enterキーを押します)。
/ etc/crontabまたは/etc/cron.dのフラグメントにユーザーcrontabでフォーマットされたcrontabを使用することはできません。逆も同様です。ユーザーでフォーマットされたcrontabは行の6番目の位置にユーザー名を含みませんが、システムでフォーマットされたcrontabはユーザー名を含み、そのユーザーとしてコマンドを実行します。
#!/bin/sh
を先頭に置く)日付がユーザーまたはシステムの更新、タイムゾーンなどによって最近変更された場合、crontabは不規則に動作し始め、奇妙なバグを示します。これは、下から時刻が変わったときに「やりたいことをしよう」とするcrontabの試みです。 「分」フィールドは、時間を変更すると無効になります。このシナリオでは、アスタリスクのみが受け入れられます。 cronを再起動し、インターネットに接続せずに再試行します(日付がタイムサーバーの1つにリセットする機会がありません)。
パーセント記号に関するアドバイスを強調するために、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")"
Debian Linuxとその派生物(Ubuntu、Mintなど)には、cronジョブの実行を妨げる特性があります。特に、/etc/cron.d
、/etc/cron.{hourly,daily,weekly,monthly}
のファイルは次のようにする必要があります。
最後のものは、疑いを持たないユーザーを定期的に傷つけます。特に、whatever.sh
、mycron.py
、testfile.pl
などの名前が付けられたこれらのフォルダーの1つにあるスクリプトは、常にnotが実行されます。
私の経験では、この特定のポイントは、Debianおよび派生物で実行されないcronjobの最も頻繁な理由でした。
必要に応じて、詳細についてはman cron
をご覧ください。
Cronジョブが機能しなくなった場合は、パスワードが期限切れになっていないことを確認してください。期限が切れると、すべてのcronジョブが停止します。
メッセージは/var/log/messages
以下のように、ユーザーの認証に関する問題を示します。
(username) FAILED to authorize user with PAM (Authentication token is no longer valid; new one required)
Cronはすべて非常に基本的なスケジューラと見なされており、この構文では、管理者が少し一般的でないスケジュールを簡単に作成することはできません。
一般的に "run command
every 5 minutes"と説明される次のジョブを考えてみましょう。
*/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から7分ごとに一致しますが、-1時間と次の時間のみバッチ間の4分、00:56
の後、01:00
、01:07
などから新しいシリーズが始まります(01:03
、01:10
、01: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/frequency_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月曜日(または第2水曜日)などにバッチを実行するようにスケジュールすることになります。バッチが毎週月曜日に実行されるようにスケジュールし、日付が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を使用しない
ニーズが複雑な場合は、複雑なスケジュール(複数のサーバーに分散)を実行するように設計され、トリガー、ジョブの依存関係、エラー処理、再試行、再試行の監視などをサポートする、より高度な製品の使用を検討してください。業界の専門用語は「エンタープライズ」です。 " ジョブスケジューリング および/または"ワークロードオートメーション "。
次のようなcronジョブがある場合:
php /bla/bla/something.php >> /var/logs/somelog-for-stdout.log
そして、エラーが予想される場合、それらはあなたに送られますが、そうではありません-これをチェックしてください。
PHPはデフォルトでエラーをSTDOUTに送信しません。 @see https://bugs.php.net/bug.php?id=22839
これを修正するには、cli`s php.iniまたは行(またはPHPのbashラッパー)に以下を追加します。
1番目の設定では、「メモリoops」や2番目の設定を使用して、すべてをSTDERRにリダイレクトできます。すべてがログに記録されるのではなく、ルートのメールに送信されるため、十分にスリープ状態になった後にのみ。
完全を期すために、 ここから と私の回答を追加し、別の潜在的に役立つリソースを追加します。
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
仕様を知っておく必要がある場合があります(または、興味があるだけかもしれません)。environment
ユーザーのcron
とは何ですか?それは私たちのユーザーとどう違うのですか? さらに、別のenvironment
ユーザーのcron
を知る必要がある場合があります-root
たとえば... root
ユーザーのenvironment
とはcron
?これを学ぶ1つの方法は、cron
に次のことを伝えるよう依頼することです。
~/
)にシェルスクリプトを作成します。$ nano ~/envtst.sh
#!/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
$ chmod a+rx ~/envtst.sh
/home/you/envtst.sh.out
の出力を確認します。この出力は、現在の環境を、ログインしている$USER
として表示します。$ ./envtst.sh $$ cat /home/you/envtst.sh.out
crontab
を開いて編集します。$ crontab -e -u root
crontab
の下部に次の行を入力します。* * * * * /home/you/envtst.sh >> /home/you/envtst.sh.err 2>&1
回答:出力ファイル/home/you/envtst.sh.out
には、「ルートcronユーザー」のenvironment
のリストが含まれます。それがわかったら、それに応じてcrontab
エントリを調整します。
crontab
エントリで必要なスケジュールを指定できません。crontab
のスケジュールエントリはman crontab
で定義されているので、これを読んでください。ただし、man crontab
を読み、スケジュールを理解することは2つの異なることです。そして、スケジュール仕様の試行錯誤は、非常に退屈になる可能性があります。さいわい、 crontabの第一人者を助けることができるリソースがあります。 。スケジュールの仕様を入力すると、わかりやすい英語でスケジュールが説明されます。
最後に、ここで他の回答のいずれかと重複するリスクがある場合は、スケジュールするジョブが1つあるため、単一のcrontab
エントリに制限されているとは思わないでください。必要なスケジュールを取得するために必要な数のcrontab
エントリを自由に使用できます。