Назад | Перейти на главную страницу

Cron: отправлять почту, только если вывод содержит строку

Могу ли я заставить cron отправлять электронную почту только в том случае, если вывод (stderr) содержит определенную строку?

Я в курсе этот ответ но команда, которую я запускаю, не различает stdout/stderr, он всегда просто выводит на stdout, поэтому мне нужно искать строку.

Пока я получил это, и он в основном работает, КРОМЕ grep не передает вывод в команду mail, поэтому я просто получаю пустое электронное письмо:

0 5 * * * root mycommand | grep -q 'Renewal was done' && mail -s 'Renewal completed' my@email.com

Как я могу получить весь вывод моей команды включен в электронное письмо?

Я настоятельно рекомендую вам поместить логику в скрипт и запустить этот скрипт в cron, а не пытаться создать однострочный скрипт в cron. Таким образом, вы можете легко протестировать его вне cron, например:

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

rm -f $tmp
exit 0

Вы можете добавить проверку статуса выхода моей команды, передать выполняемую команду, сопоставляемую строку и адрес электронной почты в качестве параметров и т. Д.

Это может сработать.

#!/bin/sh
COMMAND=`mycommand`
FINDSTR="renewal was done"

ANSWER = `$COMMAND | grep $FINDSTR` 

if $ANSWER; then
  echo $ANSWER > mail -s 'Renewal Completed' my@email.com
fi

Вот как я это делаю:

В этом сценарии у меня есть 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, заменяются словом 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='no-reply@hostname.com'
MAIL_TO='user@hostname.com'
MAIL_SUBJECT="[$HOSTNAME] [Backup Report: Databases] %status  [$(date +%Y-%m-%d)]"
MAIL_SERVER='smtp.gmail.com:587'
MAIL_USER='no-reply@hostname.com'
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 lp@10.10.10.14::backup/ /mnt/hdd3/ylatis-cy/ 1>/dev/null 2>$CY_ERR
cy_status=$?
rsync -azv --chown root:root lp@10.10.10.10::ylatisug/ /mnt/hdd3/ylatis-ug/ 1>/dev/null 2>$UG_ERR
ug_status=$?
rsync -azv --chown root:root lp@10.10.10.10::ylatisrw/ /mnt/hdd3/ylatis-rw/ 1>/dev/null 2>$RW_ERR
rw_status=$?
rsync -azv --chown root:root lp@10.10.10.10::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). Вы можете просто использовать оператор >>, если хотите сохранить весь вывод. Вы также можете настроить включение журнала в сообщение вместо вложения для удобства, если вы читаете почту с терминала.

Может быть, это кажется излишним для относительно простого вопроса, но я думаю, что он хорошо описывает то, что вы пытаетесь сделать. Вам нужно создать свое сообщение во время выполнения вашей команды через промежуточный скрипт и отправить его позже. Если вы найдете приведенный выше код полезным и у вас есть какие-либо вопросы по нему, не стесняйтесь спрашивать в комментариях.