Cron jobs can handle everything from system maintenance to running backups, but monitoring their success or failure can be difficult. One effective way to handle cron job errors is by utilizing a Bash script that sends the output to stderr only if the job fails, which generally makes cron to notify the user about the error that occurred.
Script overview
The script provided below ensures that any command passed to it will redirect its output to a temporary file. If the command fails (i.e., returns a non-zero exit code), the script sends the content of the temporary file to stderr, which causes cron to notify the user.
Here is the complete script to be installed in /usr/local/bin/outonerror
:
#!/usr/bin/env bash
# Description:
# Redirect the command's output to stderr only if the command fails (non-zero
# exit code). No output is shown when the command succeeds.
#
# Author: James Cherti
# License: MIT
# URL: https://www.jamescherti.com/cron-email-output-failed-commands-only/
set -euf -o pipefail
if [[ "$#" -eq 0 ]]; then
echo "Usage: $0 <command> [args...]" >&2
exit 1
fi
cleanup() {
if [[ "$OUTPUT_TMP" != "" ]] && [[ -f "$OUTPUT_TMP" ]]; then
rm -f "$OUTPUT_TMP"
fi
OUTPUT_TMP=""
}
trap 'cleanup' INT TERM EXIT
OUTPUT_TMP=$(mktemp --suffix=.outonerror)
ERRNO=0
"$@" >"$OUTPUT_TMP" 2>&1 || ERRNO="$?"
if [[ "$ERRNO" -ne 0 ]]; then
cat "$OUTPUT_TMP" >&2
echo "$0: '$*' exited with status $ERRNO" >&2
fi
cleanup
exit "$ERRNO"
Code language: Bash (bash)
To use this script with a cron job, save it as
and make it executable by runnning:/usr/local/bin/outonerror
chmod +x /usr/local/bin/outonerror
Code language: plaintext (plaintext)
Integration with Cron
Cron sends an email by default whenever a job produces output, whether standard output or error output. This is typically configured through the MAILTO
environment variable in the crontab file. If MAILTO
is not set, cron sends emails to the user account under which the cron job runs. Cron will only be able to send emails if the mail transfer agent (e.g., Postfix, Exim, Sendmail) is configured properly.
Here is how to schedule the cron job to use the outonerror
script:
MAILTO="your-email@example.com"
* * * * * /usr/local/bin/outonerror your_command_here
Code language: plaintext (plaintext)
With this setup, the cron job will execute your_command_here
and only send an email if it fails, thanks to cron’s default behavior of emailing stderr output to the user.
Conclusion
This script is a simple yet effective solution for improving cron jobs by ensuring that the user is notified only when something goes wrong. It reduces unnecessary notifications for successful executions and provides clear error messages when failures occur.