私は、毎月、毎日、毎時 7 時 37 分に Bash スクリプトを root として実行する root cron ジョブを設定しようとしました。このスクリプトは にあり、 という/usr/bin
名前が付けられていますtunlrupdate.sh
。これは、Tunlr の DNS を更新します。
$ ls -l /usr/bin/tunlrupdate.sh
-rwxr-xr-x 1 root root 2133 Sep 24 15:42 /usr/bin/tunlrupdate.sh
このBashスクリプトは利用可能ですここ。
スクリプトが呼び出されると、何が起こっているかをログに書き込む。/var/log/tunlr.log
このルートcronジョブを追加するには、ルートのcrontabの標準を使用しました。
sudo crontab -e
そして、最後にこれらの 2 行を挿入しました。cron がスクリプトを root として実行することを期待しています。
# check for updated Tunlr DNS every 30 minutes at the hour + 7 mn and hour + 37 mn
07,37 * * * * root /usr/bin/tunlrupdate.sh
後のコマンドでsudo crontab -l
、cron ジョブが挿入されたことが確認されました。
Ubuntu を再起動し、cron ジョブが適切に起動されたかどうかをログ ファイルで確認しました。ただし、ログ ファイルには何も記録されていないため/var/log/tunlr.log
、ジョブは正常に起動されませんでした。
コマンドラインからスクリプトを実行すると、
sudo /usr/bin/tunlrupdate.sh
ログファイルはそれに応じて更新されます。
この cron ジョブがシステム内で計画どおりに実行されないのはなぜですか?
更新1: これまでに提案された解決策はすべて機能しません。システムログを一覧表示するCLIを提供してくれたOlliに感謝しますsudo grep CRON /var/log/syslog
。ただし、CRONエラーが発生しました。
CRON[13092]: (root) CMD ( [ -x /usr/lib/php5/maxlifetime ] && [ -d /var/lib/php5 ]
&& find /var/lib/php5/ -depth -mindepth 1 -maxdepth 1 -type f -cmin +$(/usr/lib/php
/maxlifetime) ! -execdir fuser -s {} 2>/dev/null \; -delete)
推奨されている PATH= の挿入と、スクリプト内の関数のルートからの絶対パスの使用、またはここで推奨されている解決策がない場合でも、このエラーが引き続き発生します。
/usr/lib/php5/maxlifetime
少し検索した後、説明されているようにファイル内のエラーを特定しましたここ:Change #!/bin/sh -e --> #!/bin/sh -x
次に、システムのCRONエラーログを一覧表示します
sudo grep CRON /var/log/syslog
Feb 11 18:07:01 Marius-PC CRON[14067]: (root) CMD (root /usr/bin/tunlrupdate.sh)
Feb 11 18:07:01 Marius-PC CRON[14066]: (root) MAIL (mailed 1 byte of output; but got
status 0x00ff, #012)
まだ bash スクリプトが実行されません。今回はログにエラーは表示されません。これがスクリプトの内容ではないことを確認するために、スクリプトを次の 3 行に削減しました。
#!/bin/bash
LOGFILE=/var/log/tunlr.log
echo $LOGFILE >> $LOGFILE
まだ cron ジョブが実行できません。ログ ファイルには何も書き込まれません。空のスクリプトでも cron では実行されないのでしょうか? わかりません。現在、次の 2 行に短縮されたスクリプトを試しています。
#!/bin/bash
exit 0
それでも、同じエラー ログが残ります。cron スクリプトは実行されません...
答え1
スクリプトを通常ユーザー:
crontab -e
次の行を追加します:
07,37 * * * * /usr/bin/tunlrupdate.sh
スクリプトを次のように実行したい場合根:
sudo crontab -e
同じ行を追加します:
07,37 * * * * /usr/bin/tunlrupdate.sh
答え2
さて、ようやく実用的な解決策が見つかりました。syslog で、次のような興味深い繰り返しを確認しました。
CRON[18770]: (root) CMD (root /usr/bin/tunlrupdate.sh)
ルートがコマンドとして認識されなかったようです。私はすでに を使用してルートの cron を使用しています$ sudo /usr/bin/tunlrupdate.sh
。次に、元のスクリプト (日付 UNIX コマンドの間違いを修正: 月を表す %m が分を表す %M の代わりに使用されていました) で次のスクリプトを試しました (これにより、ルートが cron 行から削除されます)。
$ sudo crontab -e
# check for updated Tunlr DNS every 30 minutes at the hour + 7 mn and hour + 37 mn
07,37 * * * * /usr/bin/tunlrupdate.sh
これが最終的な解決策であることが判明しました。[ただし、cron 行に root という誤った行が含まれていると記載されている文献が多数見つかりました。これは間違いでした。]
答え3
cronの「問題」の1つは、環境変数が不足していることです(たとえば明らかセキュリティ上の理由によります。PATH と HOME が欠落している可能性があります。これらはスクリプト内で直接定義するか、crontab ファイルで定義できます。
# check for updated Tunlr DNS every 30 minutes at the hour + 7 mn and hour + 37 mn
PATH=/usr/bin
07,37 * * * * root /usr/bin/tunlrupdate.sh
必要な変数がすべてスクリプトの要件どおりに定義されるまでテストする必要があります。
答え4
この行をスクリプトに追加できます。cron ログをチェックしてジョブが実行されたことを確認した後、crontab と同じ $PATH を取得できます。
/bin/echo $PATH > /root/path.txt
そして、おそらくcronスクリプトの問題を診断するためにできる最も良いことは、スクリプト内でenvコマンドを使用してSOのすべての環境変数を取得することです。スクリプトに次の行を追加するだけです。その後、出力を分析できます。allEvnVars.txt
/usr/bin/env > /root/allEvnVars.txt
もう一つのトリックは、スクリプトの出力をどこかに送ることです。 を追加します/root/log.log
。こうすることで、スクリプトの出力はすべて/root/log.log
07,37 * * * * root /usr/bin/tunlrupdate.sh > /root/log.log
また、テストとチェックを容易にするために、スクリプトを毎分実行するようにスケジュールすることもできます。
*/1 * * * * root /usr/bin/tunlrupdate.sh > /root/log.log