Cron: Only get errors in emails?

Solution 1:

Ideally you'd want your backup script to output nothing if everything goes as expected and only produce output when something goes wrong. Then use the MAILTO environment variable to send any output generated by your script to your email address.

[email protected]
0 */2 * * * /bin/backup.sh

If your script normally produces output but you don't care about it in cron, just sent it to /dev/null and it'll email you only when something is written to stderr.

[email protected]
0 */2 * * * /bin/backup.sh > /dev/null

Solution 2:

Using cronic wrapper script looks like a good idea; to use it you don't have to change your scripts.

Instead of:

 0 1 * * * /bin/backup.sh 2>&1 | mail -s "Backup status" [email protected]

do:

 [email protected]
 0 1 * * * cronic /bin/backup.sh

Simply put; it will run silent if everything runs smooth (exit status 0), but it will report verbosely if not, and let cron handle the mail reporting.

More info on https://habilis.net/cronic/.


Solution 3:

Here is another variation that I've successfully utilized for many years - capture output and print it out only on error, triggering an email. This requires no temp files, and preserves all output. The important part is the 2>&1 that redirects STDERR to STDOUT.

Send the entire output via default cron mailer config:

1 2 * * * root OUTPUT=`flexbackup -set all 2>&1` || echo "$OUTPUT"

Same but with a specific address and subject:

(address can also be changed by setting MAILTO=xxxx for the entire crontab file)

1 2 * * * root OUTPUT=`flexbackup -set all 2>&1` || echo "$OUTPUT" | mail -s "Failed to backup" [email protected]

You can even perform multiple actions on error and add to email:

1 2 * * * root OUTPUT=`flexbackup -set all 2>&1` || {echo "$OUTPUT" ; ls -ltr /backup/dir ; }

This will work for simple commands. If you are dealing with complex pipes (find / -type f | grep -v bla | tar something-or-other), then you're better off moving the command into a script and running the script using the aforementioned approach. The reason is that if any part of the pipe outputs to STDERR, you'll still get emails.


Solution 4:

You are specifically instructing cron to always send email, even when /bin/backup.sh (by the way, it should be in /usr/local/bin) succeeds. Just omit the | mail -s "Backup status" [email protected] part and email will only be sent when there is output. You can probably (depending on your cron) explicitly set the email address to mail to as an assignment in the crontab file.

For details, see

man 5 crontab

Solution 5:

You should be directing the stderr anmd not both stdout and stderr.

Use 1> /dev/null not 2>&1 and it should be fine. Also, you may need to report the error correctly in your backup script.