ルートcronジョブを適切にセットアップする方法


36

ルートcronジョブをセットアップして、ルートとしてBashスクリプトを実行し、毎時、毎月、毎月、7分37分に実行しようとしました。このスクリプトはにあり/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がスクリプトをルートとして実行することを期待しています。

# 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スクリプトが通過しません...


「ルート」cronジョブにしたい場合は、rootでなければならない場合は、crontab -eと入力します。また、root(コンソールタイプ「su root」)としてログインし、次にcrontab -e(この場合はsudoは必要ありません)としてログインする必要があります。
ヴォルフガング14

まあ。あなたの答えの要点がわかりませんか?$ sudo crontab -eと入力すると、$ sudo crontab -lで報告されたジョブが実行されました。つまり、新しいジョブを説明する行がルートのcronに追加されました。それ自体、ジョブはユーザーcronに存在しません。たとえば、$ crontab -lは、ここで追加されたcronジョブを表示しません。
アントニオ14

@WolfgangVoglは、期待どおりに機能する「sudo」を使用しました。
アレクシスウィルケ14

回答:


68

通常のユーザーとしてスクリプトを実行する場合

crontab -e

そして次の行を追加します。

07,37 * * * * /usr/bin/tunlrupdate.sh

スクリプトをルートとして実行する場合:

sudo crontab -e

そして同じ行を追加します:

07,37 * * * * /usr/bin/tunlrupdate.sh

@NineCattoRules出力を削除しない場合、何が表示されますか?
アンジェロフックス

@AngeloFuchsの古いコメント...確かに私はそのコマンドをルートとして(sudo crontab -eではなくcrontab -e)試しました。とにかくそれが機能する
-NineCattoRules

10

さて、ついに実用的なソリューション。syslogで、反復的で興味深いものを見ました:

CRON[18770]: (root) CMD (root /usr/bin/tunlrupdate.sh)

rootはcmdとして認識されなかったようです。既にを使用してルートのcronを使用しているため$ sudo /usr/bin/tunlrupdate.sh。次に、元のスクリプト(UNIX cmdの日付の誤りを修正:月が%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を含む誤った行を示す多くの文献を見つけました。それは間違いだった]。


良い点オリー。その点については同意します。参照用に、ユーザーcrontabは/ var / spool / cron / crontabs / user-nameに保存されるか、ルート/ var / spool / cron / crontabs / rootに保存されます。このページを参照してくださいaskubuntu.com/questions/216692/where-is-the-user-crontab-stored含まれているフォルダーはすでにユーザー名であり、ユーザーの名前を示しています。
アントニオ14

さて、crontabコマンドでcrontabファイルを編集するだけでよいので、その情報は必要ありません(の下のcrontabファイルを除く/etc)。
オリ

1
@Antonioユーザー名フィールドのスコアは/etc/crontab(システム全体のcrontab)でのみ使用されます。sudo crontab -eあなたが使用しているルートのcrontabで作業しています。これは通常、/var/spool/cron/crontabs
Matijs

2

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

スクリプトで必要なすべての必要な変数が定義されるまでテストする必要があります。


1
これは、実際に私のために働いた唯一の答えです。SHELLおよびPATHステートメントを/etc/crontabファイルからコピーし、それらに貼り付けsudo crontab -e、コマンドは問題なくルートとして実行されました。ありがとうございました!
テランス

0

cronエラーメッセージは、通常-デフォルトで-メールで送信されます。あなたは電子メールがでルートのためにありますかどうかを確認することができsudo mail、または単にの内容をチェックすることにより/var/mail/root例えば、sudo less /var/mail/root


メールメッセージが役に立たない場合は、次も確認してください/var/log/syslog

sudo grep CRON /var/log/syslog

Alexis Wilkeがすでに言ったように、cronには環境変数を設定するための異なるメカニズムがあります。

スクリプトに必要なもの

PATH=/sbin:/bin:/usr/bin

crontabへ。HOME必要ないはずです。スクリプトでは、たとえばの/bin/date代わりに絶対パスを使用する必要がありますdate。を使用してwhich command_name、各コマンドの適切なパスを見つけることができます。

$ which date
/bin/date

/ var / log / syslogで推奨されるgrep CRONを実行すると、2月11日14:37:01 Marius-PC CRON [7826]:(root)CMD(root /usr/bin/tunlrupdate.sh)2月11日14: 37:01 Marius-PC CRON [7825]:(root)MAIL(1バイトの出力をメールで送信しましたが、ステータスは0x00ff、#012になりました)2月11日14:39:01 Marius-PC CRON [7849]:(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 / php5 / maxlifetime)!-execdir fuser -s {} 2> / dev / null \; -delete)cronでPATHの定義を追加しても、システムの$ PATHには影響しませんか?
アントニオ14

その出力は、メールを送信しようとしたが失敗したことを示しています。つまり、そのエラーメッセージはに届きません/var/mail/root。あなたはそれを修正するか、または試すことができますPATH=...
Olli

@Antonio、またはこれを使用する パッチ済みバージョン
オリ

ありがとう。システムの電子メールを構成しなかったこと、およびそれが通過しなかったことを認識していました。呼び出された関数に絶対パスを使用するようにスクリプトを既に修正しました。最後の質問は、crontab内のPATH定義がシステムの$ PATH変数を混乱させないという以前の質問でした。
アントニオ14

1
その間、私は元のスクリプトから日付形式のバグを修正するのに忙しかった。%Mではなく%m(分ではなく月)を使用していました...
アントニオ

0

この行をスクリプトに追加できます。したがって、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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.