Cron job stderr to email AND log file?

前端 未结 9 1622
离开以前
离开以前 2021-01-06 07:57

I have a cron job:

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

Where SP_s is the path to the script and LP_s

相关标签:
9条回答
  • 2021-01-06 08:32

    A bit tricky if you want stdout and stderr combined in one file, with stderr yet tee'd into its own stream.

    This ought to do it (error-checking, clean-up and generalized robustness omitted):

    #! /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 is sent to a named pipe, picked up by tee(1) where it is appended to the logfile (wherein is also appended your command's stdout) and tee'd back to regular stderr.

    0 讨论(0)
  • 2021-01-06 08:34

    Not sure why nobody mentioned this.

    With CRON if you specify MAILTO= in the users crontab, STDOUT is already sent via mail.

    Example

    [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
    
    0 讨论(0)
  • 2021-01-06 08:35

    My experience (ubuntu) is that 'crontab' only emails 'stderr' (I have the output directed to a log file which is then archived). That is useful, but I wanted a confirmation that the script ran (even when no errors to 'stderr'), and some details about how long it took, which I find is a good way to spot potential trouble.

    I found the way I could most easily wrap my head around this problem was to write the script with some duplicate 'echo's in it. The extensive regular 'echo's end up in the log file. For the important non-error bits I want in my crontab 'MAILTO' email, I used an 'echo' that is directed to stderr with '1>&2'.

    Thus this:

        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
    

    Sends me an email containing this (when there are no errors, the lines beginning 'ssh:' and 'rsync:' do not appear):

    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.
    

    This doesn't satisfy my initial desire to "send both stdout AND stderr to the logfile" (stderr, and only the 'echo'ed lines with '1>&2' go to the email; stdout goes to the log), but I find this is better than my initially imagined solution, as the email finds me and I don't have to go looking for problems in the log file.

    0 讨论(0)
  • 2021-01-06 08:39

    You could try writing another cronjob to read the log file and "display" the log (really just let cron email it to you)

    0 讨论(0)
  • 2021-01-06 08:40

    I assume you are using bash, you redirect stdout and stderr like so

    1> LOG_FILE
    2> LOG_FILE
    

    to send a mail containing the stderr in the body something like this

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

    I'm not sure if you can do the above in only one passage as this

    /bin/mail -s "SUBJECT" "EMAIL_ADDRESS" <2
    
    0 讨论(0)
  • 2021-01-06 08:53

    If you can do with having stdout/err in separate files, this should do:

    ($SP_s/StartDailyS1.sh 2>&1 >$LP_s/MirrorLogS1.txt.stdout) | tee $LP_s/MirrorLogS1.txt.stderr
    
    0 讨论(0)
提交回复
热议问题