3

I have a crontab (root) that runs a script and output is set to > /dev/null but I always get the emails whenever it runs. I only want to receive error emails.

# Rackspace driveclient update (12pm MST)
0 12 * * * /root/scripts/driveclient-update > /dev/null

The only way I can get it to turn off is to use > /dev/null 2>&1 but then I won't get error emails. This is happening on three different CentOS servers, two are 6.3 and one is 6.4.

NOTE: I have read over and over that > /dev/null is supposed to send stdout there and prevent the email if there is nothing but stdout from the script, so at works for at least some people; I cannot figure out why it is not working on these servers.

Here's an example of where > /dev/null is supposed to work:

Using the MAILTO variable

The MAILTO variable allows you to set the email address that the notification emails from Cron are sent to. You can suppress all emails from your Cron jobs by setting this to an empty string like so:

$ crontab -e

Now on the top of the file, add:

MAILTO=""

Then save and close the file.

Sending output to /dev/null

The /dev/null location in Linux is a "black hole" for data: any output sent here is gone, which makes it a great candidate for suppressing output from Cron jobs.

To suppress all output (STDOUT and STDERR) from your Cron job, append > /dev/null 2>&1 to the end of your job:

$ crontab -e

Example:

*/30 * * * * command  > /dev/null 2>&1

The number 2 represents the STDERR (standard error) stream, while 1 is the STDOUT (standard out) stream.

If you want to receive emails about errors only but not successes, append > /dev/null to your job to suppress output from STDOUT only:

*/30 * * * * command > /dev/null

Originally from alphadevx.com - Suppressing Cron Job Email Notifications (link is now dead)

7
  • Here is a perfect example of the behavior I'm looking for: alphadevx.com/a/384-Suppressing-Cron-Job-Email-Notifications Specifically the section: "If you want to receive emails about errors only but not successes..." Why does this not work on our CentOS servers? May 24, 2014 at 16:46
  • Just to be sure, your script is actually doing what it should, right? Please redirect STDOUT and STDERR to different files and check them afterwards. It probably just writes everything to STDERR.
    – Daniel B
    May 24, 2014 at 18:36
  • The script merely runs yum and wget; all output from those programs are emailed, and it's just normal output they print when running them manually on the command line. I have no explanation for why cron is ignoring > /dev/null for stdout for the programs but not when I use 2>&1 after that; it wouldn't make sense that the script's yum and wget output is being processed as STDERR if it's just normal output, right? I thought its "yes it's working" output was STDOUT. May 24, 2014 at 18:44
  • 1
    Just to clarify, it is ALL OR NOTHING with this crontab. Anything that uses > /dev/null (or doesn't) always emails everything; anything that uses 2>&1 AFTER THAT never emails anything. I cannot explain this behavior. There must be some configuration somewhere that I am not aware or I am not typing it exactly right. May 24, 2014 at 18:46
  • Yes yes. Now please append >/var/log/mycron.log 2>/var/log/mycron.err and see where that gets us. :)
    – Daniel B
    May 24, 2014 at 18:52

5 Answers 5

3

Set MAILTO="[email protected]" in the crontab file. And let your script 'echo' stderr or stderr when exceptions are thrown by a $(subshell). Anything can happen, so work with return values (0 is OK, anything else is an exception) like in this example:

#!/bin/bash
return=$(/usr/bin/curl --silent --show-error --fail "http://server/somestate" 2>&1)
exitcode=$?
if [ $exitcode != 0 ]
then
    echo "ERROR $HOSTNAME $0 $exitcode $return"
    logger "ERROR $HOSTNAME $0 $exitcode $return"
    exit $exitcode
else
    logger "INFO $HOSTNAME $0 $exitcode $return"
    exit 0
fi
5
  • The MAILTO is fine, it's what we want. The problem is crontab is emailing every output, not just stderr, so no matter what I'm echoing in the script, it will output, even if it's coming from a sub-process I have no control over. For instance, I run a yum check update or a wget and it outputs all its normal output and sends me the email. I'm reading everywhere that > /dev/null is supposed to prevent this but it doesn't. May 24, 2014 at 16:34
  • The trick is to run your scripts or subprocesses quietly, with a quiet/silent flag and redirect normal output to nirwana with > /dev/null. If you still get mail then it is an stderr output, exceptions that you need to solve. May 24, 2014 at 16:57
  • So every script in every cron that is run must have a silent flag instead of just behaving the way all tutorials I'm reading say it should? Go check that link I added in my original post. Why does it work there but not here? Your solution may work but it is a lot of stuff I have to add for every cron that should just behave the way the system is supposed to work. If cron will redirect 2>&1 then I don't understand why it won't redirect > /dev/null. It is not stderr that is being emailed, it is normal stdout, exactly what comes from yum and wget when things run fine. May 24, 2014 at 17:44
  • If you set MAILTO="" you won't get it. May 24, 2014 at 18:00
  • C'mon guys read the original post. I want emails only when there's an error. May 26, 2014 at 3:30
1

> only redirects std out/err, email is an internal function to the script most like. check the script -h for optional parameters or rackspace utility documents

3
  • > just redirects; > /dev/null is supposed to redirect stdout to /dev/null; 2>&1 redirects stderr to stdout, which I don't want. I wrote the script, I did not add a line to send an email. The email is coming from Cron Daemon. Please explain. Running the script with -h just runs the script (because I didn't program that option). May 16, 2014 at 4:07
  • email has nothing to do with stdout or stderr, thus redirecting those will not affect emails. Check your environment variables; is MAILTO set? env
    – EkriirkE
    May 16, 2014 at 6:18
  • You're not understanding; I want ONLY errors sent through email. Otherwise I don't want an email sent. May 24, 2014 at 16:31
0

I discovered wget and yum send stdout to stderr so I had to pipe everything to log files.

0

For later referance. You don't have to send everything to a logfile. It is possible to tell bash to also send output on STDERR to /dev/null.

# Rackspace driveclient update (12pm MST)
0 12 * * * /root/scripts/driveclient-update > /dev/null 2>&1

Note that all I did was append 2>&1 to the end of the file.

0

This is a solution I found a long time ago, use the following in crontab. This assumes you only want an email when the script returns non-zero.

# Rackspace driveclient update (12pm MST)
0 12 * * * if ! out="$(/root/scripts/driveclient-update 2>&1)"; then echo "$out"; fi

You must log in to answer this question.

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