电子邮件和日志文件的Cron作业stderr?

时间:2009-08-20 20:02:43

标签: unix cron redirect

我有一份cron工作:

$SP_s/StartDailyS1.sh >$LP_s/MirrorLogS1.txt

其中SP_s是脚本的路径,LP_s是日志文件的路径。这会将stdout发送到日志文件并将stderr发送到我的电子邮件。

我如何?: 1)将stdout和stderr发送到日志文件,
2)并将stderr发送到电子邮件

或换句话说:stderr同时记录日志文件和电子邮件,stdout只记录日志文件。

更新: 到目前为止,我得到的答案都没有遵循我提出的标准,或者似乎适合CRON工作。

我看到了这个,其目的是“将STDOUT和STDERR从一个命令发送到一个文件,然后只将STDERR发送到另一个文件”(由unix.com上的zazzybob发布),这似乎接近我想要的我和我想知道它是否会激发比我更聪明的人:

(( my_command 3>&1 1>&2 2>&3 ) | tee error_only.log ) > all.log 2>&1 

我希望cron将STDERR发送到电子邮件而不是“另一个文件”。

9 个答案:

答案 0 :(得分:3)

由于我只是在查看tee的信息页面(试图找出如何做同样的事情),我可以为你回答最后一点。

这就是大部分时间:

(( my_command 3>&1 1>&2 2>&3 ) | tee error_only.log ) > all.log 2>&1

但将“error_only.log”替换为“>(email_command)”

(( my_command 3>&1 1>&2 2>&3 ) | tee >(/bin/mail -s "SUBJECT" "EMAIL") ) > all.log 2>&1

注意:根据tee的文档,这将在bash中起作用,但在/ bin / sh中不起作用。如果你把它放在一个cron脚本中(比如/etc/cron.daily/)那么你可以只在#!/ bin / bash顶部。但是,如果你把它作为单行代码放在crontab中,那么你可能需要将它包装在bash -c“”

答案 1 :(得分:3)

不确定为什么没有人提到这一点。

如果在用户crontab中指定MAILTO =,则使用CRON, STDOUT已经通过邮件发送。

实施例

[temp]$ sudo crontab -u user1 -l
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=user1
# transfer order shipping file every 3 minutes past the quarter hour
3,19,33,48 * * * * /home/user1/.bin/trans.sh

答案 2 :(得分:2)

如果你可以在单独的文件中使用stdout / err,那么应该这样做:

($SP_s/StartDailyS1.sh 2>&1 >$LP_s/MirrorLogS1.txt.stdout) | tee $LP_s/MirrorLogS1.txt.stderr

答案 3 :(得分:1)

除非我遗漏了什么:

command 2>&1 >> file.log | tee -a file.log

2>& 1将stderr重定向到stdout

>>将常规命令stdout重定向到logfile

| tee将stderr(从2>& 1)复制到logfile并将其传递给stdout,由cron邮寄给MAILTO

我用

测试了它
(echo Hello & echo 1>&2 World) 2>&1 >> x | tee -a x

确实在控制台中显示了World,在x

中显示了两个文本

丑陋的是重复的文件名。而stdout / stderr的不同缓冲可能会使file.log中的文本有点混乱。

答案 4 :(得分:0)

如果您希望将 stdout stderr 组合在一个文件中,并且 stderr 已经开始进入自己的流中,那就有点棘手。< / p>

这应该这样做(省略错误检查,清理和广义稳健性):

#! /bin/sh

CMD=..../StartDailyS1.sh
LOGFILE=..../MirrorLogS1.txt
FIFO=/tmp/fifo

>$LOGFILE

mkfifo $FIFO 2>/dev/null || :

tee < $FIFO -a $LOGFILE >&2 &

$CMD 2>$FIFO >>$LOGFILE

stderr 被发送到命名管道,由tee(1)选取,并附加到日志文件中(其中还附加了命令的 stdout )和回到常规 stderr

答案 5 :(得分:0)

我的经验(ubuntu)是&#39; crontab&#39;只有电子邮件&stderr&#39; (我将输出定向到一个日志文件,然后存档)。这很有用,但我希望确认脚本运行(即使没有错误到#st;&#39;),以及有关花了多长时间的一些细节,我发现这是发现潜在问题的好方法。

我发现我可以最容易地解决这个问题的方法就是在脚本中写上一些重复的回声。广泛的常规回声最终会出现在日志文件中。对于我想要在我的crontab&#39; MAILTO&#39;中所需的重要非错误位。电子邮件,我用了一个回声&#39;用&#39; 1&gt;&amp; 2&#39;指向stderr。

因此:

    Frmt_s="+>>%y%m%d %H%M%S($HOSTNAME): " # =Format of timestamp: "<YYMMDD HHMMSS>(<machine name>): "
    echo `date "$Frmt_s"`"'$0' started." # '$0' is path & filename
    echo `date "$Frmt_s"`"'$0' started."  1>&2 # message to stderr

# REPORT:
    echo ""
    echo "================================================"
    echo "================================================" 1>&2 # message to stderr
    TotalMins_i=$(( TotalSecs_i / 60 )) # calculate elapsed mins
    RemainderSecs_i=$(( TotalSecs_i-(TotalMins_i*60) ))
    Title_s="TOTAL run time"
    Summary_s=$Summary_s$'\n'$(printf "%-20s%3s:%02d" "$Title_s" $TotalMins_i $RemainderSecs_i)
    echo "$Summary_s"
    echo "$Summary_s" 1>&2 # message to stderr
    echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
    echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" 1>&2 # message to stderr
    echo ""
    echo `date "$Frmt_s"`"TotalSecs_i: $TotalSecs_i"
    echo `date "$Frmt_s"`"'$0' concluded." # '$0' is path & filename
    echo `date "$Frmt_s"`"'$0' concluded."  1>&2 # message to stderr

向我发送一封包含此内容的电子邮件(如果没有错误,则行开头&#39; ssh:&#39;和&#39; rsync:&#39;不显示):

170408 030001(sb03): '/mnt/data1/LoSR/backup_losr_to_elwd.sh' started.
ssh: connect to host 000.000.000.000 port 0000: Connection timed out
rsync: connection unexpectedly closed (0 bytes received so far) [Receiver]
rsync error: unexplained error (code 255) at io.c(226) [Receiver=3.1.0]
ssh: connect to host 000.000.000.000 port 0000: Connection timed out
rsync: connection unexpectedly closed (0 bytes received so far) [Receiver]
rsync error: unexplained error (code 255) at io.c(226) [Receiver=3.1.0]
================================================
S6 SUMMARY (mins:secs):
'Templates'           2:07
'Clients'             2:08
'Backups'             0:10
'Homes'               0:02
'NetAppsS6'          10:19
'TemplatesNew'        0:01
'S6Www'               0:02
'Aabak'               4:44
'Aaldf'               0:01
'ateam.ldf'           0:01
'Aa50Ini'             0:02
'Aadmin50Ini'         0:01
'GenerateTemplates'   0:01
'BackupScripts'       0:01
TOTAL run time       19:40
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
170408 031941(sb03): '/mnt/data1/LoSR/backup_losr_to_elwd.sh' concluded.

这并不能满足我最初的愿望,即将stdout和stderr发送到日志文件&#34; (stderr,只有&#39; echo&#39; ed行&#39; 1&gt;&amp; 2&#39;进入电子邮件; stdout进入日志),但我发现这比我最初更好想象的解决方案,因为电子邮件找到了我,我不必去寻找日志文件中的问题。

答案 6 :(得分:0)

我认为解决方案是:

$SP_s/StartDailyS1.sh 2>&1 >> $LP_s/MirrorLogS1.txt | tee -a $LP_s/MirrorLogS1.txt

这将:

  • 将标准输出附加到$LP_s/MirrorLogS1.txt
  • 将标准错误附加到$LP_s/MirrorLogS1.txt
  • 打印标准错误,以便cron在发生错误时发送邮件

答案 7 :(得分:-1)

我假设您正在使用bash,您重定向stdout和stderr就像这样

1> LOG_FILE
2> LOG_FILE

发送包含身体中的stderr的邮件

2> MESSAGE_FILE
/bin/mail -s "SUBJECT" "EMAIL_ADDRESS" < MESSAGE_FILE

我不确定你是否可以只在一个段落中执行上述操作

/bin/mail -s "SUBJECT" "EMAIL_ADDRESS" <2

答案 8 :(得分:-1)

您可以尝试编写另一个cronjob来读取日志文件并“显示”日志(真的只是让cron通过电子邮件发送给您)