Cronは時々出力とエラーに関する電子メールを送信します。

Cronは時々出力とエラーに関する電子メールを送信します。

Debian 8.1 で私は使用しています吹くstackoverflow.comウェブサイトにアクセスできるかどうかを検出する機能:

(エコ>/dev/tcp/stackoverflow.com/80) &>/dev/null || echo "スタックオーバーフローにアクセスできません。"

shこれはBashにのみ適用され、.defaultシェルには影響しませんcron

意図的にスクリプトを試してみると、次のような結果がsh得られます。

$ /bin/sh: 1: cannot create /dev/tcp/stackoverflow.com/80: Directory nonexistent

SHELLしたがって、以下をプライベートcrontab(viaに設定しない/bin/bash)に入れると、crontab -eスクリプトは1分ごとに実行されるので、上記のエラーを電子メールごとに1分に1回送信したいと思います。

* * * * * (echo >/dev/tcp/stackoverflow.com/80) &>/dev/null || echo "Stackoverflowにアクセスできません。"

実際には、期待どおりに/var/log/syslogこのアイテムが毎分実行されていることがわかります。

#sudo grep スタックオーバーフロー /var/log/syslog
8月24日18:58:01ローカルホスト CRON[13719]: (mat) CMD ((echo >/dev/tcp/stackoverflow.com/80) &>/dev/null || echo "stackoverflow にアクセスできません。")
8月24日18:59:01ローカルホスト CRON[13723]: (mat) CMD ((echo >/dev/tcp/stackoverflow.com/80) &>/dev/null || echo "stackoverflow にアクセスできません。")
8月24日19:00:01ローカルホスト CRON[13727]: (mat) CMD ((echo >/dev/tcp/stackoverflow.com/80) &>/dev/null || echo "stackoverflow にアクセスできません。")
...

このコマンドは過去2時間で120回以上実行され、出力をwc -l

しかし、、これらの120以上のシェルコマンド(繰り返し:シェルコマンドのペアが無効です/bin/sh)が実行されたため、次の結果のみが得られます。サムEメール:

最初は19:10:01、2番目は20:15:01、3番目は20:57:01です.

3つのメッセージの内容はすべて期待どおりに正しく読み取られ、(意図的に)互換性のないシェルでスクリプトを実行したときに予想されるエラーメッセージも正しく含まれていました。たとえば、私が受け取った2番目のEメールは次のようになりました(残りの2つのEメールはほぼ同じです)。

~から[Eメール保護]  2015年8月24日月曜日20:15:01
から:[Eメール保護](クレーンデーモン)
到着する:[Eメール保護]
トピック: Cron (echo >/dev/tcp/stackoverflow.com/80)&>/dev/null || echo "Stackoverflowにアクセスできません。"
...

/bin/sh: 1: /dev/tcp/stackoverflow.com/80 を生成できません: ディレクトリが存在しません`

/var/log/mail.logから送信された3つの電子メールは次のとおりです。ただここ数時間で送受信されたメッセージです。

もしそうなら、間違ったスクリプトによって生成された上記の出力のためにcronが受信すると予想される100以上の追加の電子メールはどこにありますか?

結論として:

  1. このシステムでは、メールが正しく設定されており、問題なくメールを送受信できます/usr/bin/sendmail
  2. Cronは正しく設定され、期待どおりにタスクを認識し、設定された時間に正確に実行します。私は他の多くのタスクと予約オプションを試してみましたが、cronは期待どおりに正確に実行しました。
  3. スクリプトいつも出力を作成するので(下記参照)、cronが呼び出すたびに出力を電子メールで送信することを期待しています。
  4. 結果は時々私に郵送され、ほとんどの場合無視されます。

上記の観察結果につながる明らかなエラーを解決する方法はいくつかあります。

  1. SHELL=/bin/bash私はそうすることができますcrontab
  2. heartbeat.shwithを作成して#!/bin/bash呼び出すことができます。
  3. /bin/bash -c ...insideを使用してスクリプトを呼び出すことができますcrontab
  4. ちょっと待ってください。これらすべてがsh

ただし、どちらもこの問題の重要な問題を解決しません。つまり、この場合、cronスクリプトでさえも安定してメールを送信できないということです。いつも出力を生成します。

私はスクリプトが常にwrong.sh次のものを生成して出力を生成することを確認しました。故意に不適切なシェルを使用すると、表示されるのと同じエラーが/bin/sh発生します。)cron

#!/bin/sh
(echo >/dev/tcp/stackoverflow.com/80) &>/dev/null || echo "Stackoverflowにアクセスできません。"

これでスクリプト呼び出しを繰り返して、完了する項目があるかどうかを確認できます。いいえ出力を生成します。使用吹く:

$ trueの場合; do [[ -n $(./wrong.sh 2>&1 ) ]] echo $?;

何千もの呼び出しにもかかわらず、出力を生成せずにスクリプトが完了する状況を再現することはできません。

このように予測できない行動が現れるのはなぜでしょうか。誰でもこれを再現できますか?私には、cronがスクリプトの出力を見逃す可能性がある競合条件がある可能性があるようです。おそらく、ほとんどの場合、エラーがシェル自体で発生する状況に関連している可能性があります。ありがとうございます!

ベストアンサー1

&追加のテストをしてみると結果がめちゃくちゃになりそうです。指摘した通りです&>/dev/null強く打つ文法、いいえシェン通事論。その結果、shサブシェルが作成され、背景に設定されます。もちろん、サブシェルはechostderrを生成しますが、私の理論は次のようになります。

  1. cronはサブシェルのstderrをキャプチャしません。
  2. サブシェルの背景は常に正常に完了します|| echo ...

...クローンジョブで出力が発生しないため、メールはありません。 vixie-cronのソースコードを読むと、ジョブのstderrとstdoutがcronによってキャプチャされますが、サブシェルによって確実に失われるようです。

/bin/sh環境で直接テストしてみてください(ここに「bar」というファイルがないとします)。

(grep foo bar) &
echo $?

おすすめ記事