web-dev-qa-db-ja.com

cron:出力に文字列が含まれている場合にのみメールを送信する

出力(stderr)に特定の文字列が含まれている場合にのみ、cronに電子メールを送信させることはできますか?

私は この答え を知っていますが、実行するコマンドはstdout/stderrを区別しません。常にstdoutに出力するだけです。だから私は文字列を探す必要があります。

これまでのところ、これを取得しましたが、grepが出力をmailコマンドに渡さないことを除いて、基本的には機能するため、空の電子メールを受け取るだけです。

0 5 * * * root mycommand | grep -q 'Renewal was done' && mail -s 'Renewal completed' [email protected]

電子メールに含まれているmycommandから全体の出力を取得するにはどうすればよいですか?

2
TheStoryCoder

Cronでワンライナースクリプトを作成するのではなく、ロジックをスクリプトに入れて、そのスクリプトをcronで実行することを強くお勧めします。そうすれば、cronの外部で簡単にテストできます。例:

#!/bin.bash
tmp=/tmp/t$$
mycommand > $tmp 
if grep -q 'Renewal was done' $tmp
then
    mail -s 'Renewal completed' [email protected] < $tmp
fi

rm -f $tmp
exit 0

Mycommandの終了ステータスのチェックを追加したり、実行中のコマンド、一致した文字列、電子メールアドレスをパラメーターとして渡すことができます。

2
iheggie

これはうまくいくかもしれません。

#!/ bin/sh 
 COMMAND = `mycommand` 
 FINDSTR =" renewal was done "
 
 ANSWER =` $ COMMAND | grep $ FINDSTR` 
 
 if $ ANSWER; then 
 echo $ ANSWER> mail -s '更新が完了しました' [email protected] 
 fi 
1
Jeff W.

これが私がそれをする方法です:

このシナリオでは、4つのデータベース(ダンプ)をバックアップする必要があります。すべてが正常に行われた場合は、そのことを記載したメールを受け取ります。エラーが発生した場合は、別の件名のメッセージで指摘してください。失敗したデータベースはメッセージ本文に含まれ、エラーログは電子メールに添付されます。

最初のファイル(/ root/templates/ylatis-backup.txt)は、単なるメッセージ本文テンプレートです。

バックアップステータスレポート:%hostname

ネットワーク設定:
%net_config

データベースのバックアップ:
ylatis-cy:%cy_status
ylatis-ug:%ug_status
ylatis-rw:%rw_status
ylatis-lc:%lc_status

接頭辞%が付いているすべての単語は変数として扱われ、スクリプトの後半でsedに置き換えられます。
%hostnameと%net_configは、電子メールの送信元のコンピューターを識別するために使用されます。
_statusで終わる変数はWord NORMALまたはERRORに置き換えられているため、何が問題だったかを知ることができます。

#!/bin/bash

NET_CONFIG=$(ifconfig |grep inet |grep -v inet6 |grep -v '127.0.0.1')
MESSAGE_TEMPLATE=/root/templates/ylatis-backup.txt
REPORT_FILE=/tmp/bkup-report-$$.txt
MESSAGE=$(cat $MESSAGE_TEMPLATE)

MAIL_FROM='[email protected]'
MAIL_TO='[email protected]'
MAIL_SUBJECT="[$HOSTNAME] [Backup Report: Databases] %status  [$(date +%Y-%m-%d)]"
MAIL_SERVER='smtp.gmail.com:587'
MAIL_USER='[email protected]'
MAIL_PASS='**********'

CY_ERR=/tmp/ylatis-cy_err.$$
UG_ERR=/tmp/ylatis-ug_err.$$
RW_ERR=/tmp/ylatis-rw_err.$$
LC_ERR=/tmp/ylatis-lc_err.$$

ERROR_LOG=/tmp/error_log-$$.txt

MESSAGE=$(echo "$MESSAGE" |sed 's@%hostname@'"$HOSTNAME"'@g')
MESSAGE=$(echo "$MESSAGE" |sed 's@%net_config@'"$NET_CONFIG"'@g')

mount -a
rsync -azv --chown root:root [email protected]::backup/ /mnt/hdd3/ylatis-cy/ 1>/dev/null 2>$CY_ERR
cy_status=$?
rsync -azv --chown root:root [email protected]::ylatisug/ /mnt/hdd3/ylatis-ug/ 1>/dev/null 2>$UG_ERR
ug_status=$?
rsync -azv --chown root:root [email protected]::ylatisrw/ /mnt/hdd3/ylatis-rw/ 1>/dev/null 2>$RW_ERR
rw_status=$?
rsync -azv --chown root:root [email protected]::labco/ /mnt/hdd3/ylatis-labco/ 1>/dev/null 2>$LC_ERR
lc_status=$?

if [ $cy_status -eq 0 ] && [ $ug_status -eq 0 ] && [ $rw_status -eq 0 ] && [ $lc_status -eq 0 ]; then
##########
#ALL GOOD#
##########

MAIL_SUBJECT=$(echo "$MAIL_SUBJECT" |sed 's@%status@[NORMAL]@g')

MESSAGE=$(echo "$MESSAGE" |sed 's@%cy_status@NORMAL@g')
MESSAGE=$(echo "$MESSAGE" |sed 's@%ug_status@NORMAL@g')
MESSAGE=$(echo "$MESSAGE" |sed 's@%rw_status@NORMAL@g')
MESSAGE=$(echo "$MESSAGE" |sed 's@%lc_status@NORMAL@g')

echo "$MESSAGE" >$REPORT_FILE
sendemail -f $MAIL_FROM -t $MAIL_TO -u $MAIL_SUBJECT -o message-      file=$REPORT_FILE -s $MAIL_SERVER -xu $MAIL_USER -xp $MAIL_PASS

else
################
#ERRORS OCCURED#
################

MAIL_SUBJECT=$(echo "$MAIL_SUBJECT" |sed 's@%status@[ERROR]@g')

if [ $cy_status -eq 0 ]; then
  MESSAGE=$(echo "$MESSAGE" |sed 's@%cy_status@NORMAL@g')
else
  MESSAGE=$(echo "$MESSAGE" |sed 's@%cy_status@ERROR@g')
fi

if [ $ug_status -eq 0 ]; then
  MESSAGE=$(echo "$MESSAGE" |sed 's@%ug_status@NORMAL@g')
else
  MESSAGE=$(echo "$MESSAGE" |sed 's@%ug_status@ERROR@g')
fi

if [ $rw_status -eq 0 ]; then
  MESSAGE=$(echo "$MESSAGE" |sed 's@%rw_status@NORMAL@g')
else
  MESSAGE=$(echo "$MESSAGE" |sed 's@%rw_status@ERROR@g')
fi

if [ $lc_status -eq 0 ]; then
  MESSAGE=$(echo "$MESSAGE" |sed 's@%lc_status@NORMAL@g')
else
  MESSAGE=$(echo "$MESSAGE" |sed 's@%lc_status@ERROR@g')
fi

  echo "$MESSAGE" >$REPORT_FILE

  cat /dev/null >$ERROR_LOG
  find /tmp/ -name \*.$$ -exec cat {} \; >>$ERROR_LOG
  cp $ERROR_LOG .
  sendemail -f $MAIL_FROM -t $MAIL_TO -u $MAIL_SUBJECT -o message-file=$REPORT_FILE -a error_log-$$.txt -s $MAIL_SERVER -xu $MAIL_USER -xp  $MAIL_PASS
  rm error_log-$$.txt

fi

#Cleanup
rm /tmp/*.$$ 2>/dev/null
rm /tmp/*$$.txt 2>/dev/null

Rsyncの終了ステータスを監視して、メールのメッセージと件名を判断する方法に注意してください。私の場合、通常の出力(1>/dev/null)を破棄し、標準エラー出力(2> $ error_log)のみを保持しています。すべての出力を保持したい場合は、>>演算子を使用できます。端末からメールを読んでいる場合、便宜上、添付ファイルの代わりにログをメッセージに含めるように調整することもできます。

多分それは比較的単純な質問に対してはやり過ぎのように見えますが、私はあなたが何をしようとしているのかをよく表しています。中間スクリプトを介してコマンドを実行しながらメッセージを作成し、後で送信する必要があります。上記のコードが有用で、質問がある場合は、コメントでお気軽に質問してください。

0