How can I only receive emails from cron if there are errors?

In the overwhelmingly vast majority of cases, the tasks will run just fine - and I truly do not care about the output.

It is only in the rare case of a failure that I want/need to know.

I have procmail available - but am not sure if what I'm describing is possible to manage externally to cron "correctly".

  • 1
    What if crond itself isn't running? Or the machine is offline? That's why I never bother with emails from cron and use a dedicated cron monitoring service. I'm partial to WDT.io and recommend it. Jun 20, 2017 at 5:23

5 Answers 5


The chronic command from moreutils runs a command quietly unless it fails.

Quoting from its manual:

chronic runs a command, and arranges for its standard out and standard error to only be displayed if the command fails (exits nonzero or crashes). If the command succeeds, any extraneous output will be hidden.

A common use for chronic is for running a cron job. Rather than trying to keep the command quiet, and having to deal with mails containing accidental output when it succeeds, and not verbose enough output when it fails, you can just run it verbosely always, and use chronic to hide the successful output.

  • Using it too, but slightly unhappy it doesn't send emails on empty stderr but nonzero exit code.
    – cmc
    Jun 11, 2021 at 10:58
  • @cmc it doesn't send email at all, cron does. Make sure your errors produce output, or cheat with chronic -v Jun 11, 2021 at 13:00
  • Politowski I am slightly unhappy chronic doesn't compel cron to send emails on nonzero exit code and no error output. -v will do nicely, thank you very much
    – cmc
    Jun 11, 2021 at 14:46

As you are not caring for the output, you can redirect the STDOUT of a job to /dev/null and let the STDERR being send via mail (using MAILTO environment variable).

So, for example:

[email protected]
* * * * * /my/script.sh >/dev/null

will send mail when there is output only on STDERR (with the STDERR), and will discard the STDOUT.

This of course assumes that when a program has written on STDERR, has failed; this might not be always the case. If you have control over the program, you can make it do so. For any complex case, you should write a wrapper of some kind that runs the command(s) and send mail accordingly. And put the wrapper as the cron job.

  • 1
    The downside of this approach is when it fails you only get the STDERR output which may make diagnosis harder than if you had the full output.
    – plugwash
    Jun 20, 2017 at 14:24

How can I only receive emails from cron if there are errors?

You could wrap your cron invocations with cronic, a shell script which eats cron output unless the return code of the invoked process is non-zero or there is non-trace error output.

To use cronic, download the script to a suitable location, such as /usr/local/bin. Your crontab entries must be prefixed with the path to the script (e.g. /usr/local/bin/cronic), or simply cronic, provided your PATH is set properly.

Do note that "errors" is an ill-defined term in your question and requires careful definition. For cronic to be useful, you must ensure the jobs you wrap with cronic report errors in one of the ways it defines an error condition. Implicit methods of reporting, such as writing text strings to STDOUT, will require further thought to make this compatible with cronic or another cron reporting mechanism.

Other wrappers are available, as linked from the cronic site:

  • 1
    Is cronic related to chronic, or is that just coincidence? Jun 20, 2017 at 14:25
  • @TobySpeight Coincidence it seems. cronic is implemented in bash, chronic as suggested in the earlier answer is a Perl script. Jun 20, 2017 at 23:07
  • Used to use this, stopped because it cannot be configured to ignore stderr with an exit code of zero.
    – cmc
    Jun 11, 2021 at 10:59
  • @cmc This annoys me aswell, did you find an alternative?
    – Hameno
    Sep 14, 2021 at 16:05

Here is another variation that I've successfully utilized for many years - capture output and print it out only on error. 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:

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.

  • You should put $OUTPUT in quotes: "$OUTPUT". Nov 30, 2018 at 13:58
  • @G-Man Fair point, there is always a chance that the output may contain "-n" or something similar.
    – Akom
    Dec 1, 2018 at 14:02
  • Possibly stating the obvious, but this only works if the script (flexbackup in this case) has a non-zero exit status. That is, if it's a shell script that executes various other things, some of them can fail and print errors but if the last command in it ran succesfully, no mail is sent.
    – MSpreij
    Apr 5, 2022 at 9:58
  • Thanks. So far, best solution I found to use with the borg backup sample script :) Simple is beautiful!!! (wish I had thought of this before, now you showed us, seems so obvious) Sep 17, 2022 at 7:16

I have probably not thought this all the way through, but

* * * * * yourthing.sh >/tmp/yourthing.log && rm -f /tmp/yourthing.log; cat /tmp/yourthing.log 2>/dev/null

would, in ordinary cases, redirect everything to a temporary file (you probably would want to use mktemp to obtain a unique filename), delete that if the file was successful, and then cat the contents again, if they still exist (i.e. yourthing.sh exited with error condition), to be picked up by the cron mailer.

If memory serves, cron already does not send anything if there was no output, so if the log file is empty or does not exist, nothing happens. (We redirect the error message away.)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .