38

I finally set up a realistic backup schedule on my data through a shell script, which are handled by cron on tight intervals. Unfortunately, I keep getting empty emails each time the CRON has been executed and not only when things go wrong.

Is it possible to only make CRON send emails when something goes wrong, ie. my TAR doesn't execute as intended?

Here's how my crontab is setup for the moment;

0 */2 * * * /bin/backup.sh 2>&1 | mail -s "Backup status" email@example.com

Thanks a lot!

53

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.

MAILTO=email@example.com
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.

MAILTO=email@example.com
0 */2 * * * /bin/backup.sh > /dev/null
  • 9
    This is hardly ideal. You generally want the entire output (stdout + stderr) e-mailed to you when the command ends with a non-zero error code. Otherwise, it is generally fine to gobble at least stdout. To me, this is a design flaw of cron. – Witiko Jan 18 '17 at 0:12
  • 3
    @Witiko I agree; I found this question trying to fix that. I guess you can make your cron command /bin/backup.sh > log_file || (echo Backup failed with exit status $?; cat log_file)? – Daniel H Oct 17 '17 at 14:08
22

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@example.com

do:

 MAILTO=email@example.com
 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/.

  • I really don't see how that will help when the problem is nothing more than an incorrect cron line and cron is doing exactly what it is told to do. – John Gardeniers Feb 14 '12 at 0:17
  • 3
    @JohnGardeniers it helps because sometimes you have output without an error. – Mikhail Aug 31 '14 at 19:59
  • 11
    Alternatively, chronic from the moreutils package: joeyh.name/code/moreutils – Vladimir Panteleev May 29 '15 at 22:05
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@example.com 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
3

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.

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" an@email.address

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.