53

I create cron-jobs in Ubuntu by placing the executable in one of /etc/cron.{daily,hourly,monthly,weekly}. There are lots of directories starting with cron:

kent@rat:~$ ls -ld /etc/cron*
drwxr-xr-x 2 root root 4096 2009-06-06 18:52 /etc/cron.d
drwxr-xr-x 2 root root 4096 2009-07-16 13:17 /etc/cron.daily
drwxr-xr-x 2 root root 4096 2009-06-06 18:52 /etc/cron.hourly
drwxr-xr-x 2 root root 4096 2009-06-06 18:52 /etc/cron.monthly
-rw-r--r-- 1 root root  724 2009-05-16 23:49 /etc/crontab
drwxr-xr-x 2 root root 4096 2009-06-06 18:52 /etc/cron.weekly

I would like to get e-mail from my scripts when:

  1. A script fails and gives an exit code of non-zero.
  2. The script has something to tell me

I have SSMTP installed and working, I send my mail from my Google-account. The fact that SSMTP can only send mail using one account isn't a problem for me. It's just a home server and the users I have do not have the ability to add cron-jobs.

I would like to know how the mailing from scripts usually works in Linux/Unix in general and in Ubuntu specifically. I would also like to know of a good way for me to get mails in the two situations above.

Deleted
  • 1,832
  • 7
  • 23
  • 31

7 Answers7

67

By default, cron will email the owner of the account under which the crontab is running.

The system-wide crontab is in /etc/crontab runs under the user `root'

Because root is used widely, I'd recommend adding a root alias to your /etc/aliases file anyways. (run 'newaliases' after)

The normal way to structure this is for root to be aliased to another user on the system, e.g. for me I'd alias 'root' to 'phil' (my user account) and alias 'phil' to my external email address.

If you have a specific user cron that you'd like emailed to you on output, you can use /etc/aliases again (providing you have superuser access) to redirect the user to another email address, or you can use the following at the top of your crontab:

MAILTO="email@domain.com"

If mail should be sent to a local user, you may put just the username instead:

MAILTO=someuser

If you need more information see crontab(5) by running:

man 5 crontab
runejuhl
  • 124
  • 6
Philip Reynolds
  • 9,751
  • 1
  • 32
  • 33
  • Aren't `/etc/aliases` entries supposed to follow [the format](http://www.postfix.org/aliases.5.html) `name: value1, value2, ...`? I don't know, maybe the format was changed at some point in the last 8 years. – Nathan Jones Jan 18 '17 at 22:07
  • 1
    "for me I'd alias 'root' to 'phil' (my user account) and alias 'phil' to my external email address." How to alias 'phil' to an external email address? – Howard Lee Jun 16 '17 at 17:15
31

In order to get email sent from vixie cron you will need something that replicates the sendmail command. So installing postfix or SSMTP will sort this part out. If your using postfix then the aliases file can be used to map system users to real email addresses.

Adding MAILTO="foo@bar.com" to the top of a crontab will cause any output from the cron job to be emailed. This is regardless of error code.

For scripts that output errors correctly into STDERR then its easy to get emailed only when they go wrong just do this:

MAILTO="foo@bar.com"
0 5 * * * /bin/some_script > /dev/null

This will redirect just the STDOUT to null. If any STDERR messages are present they will get email to you.

However, I've found some scripts will output errors incorrectly as STDOUT and set the exit code to 1. I have not figure out a way to grab the output from these, but ignore the output if the exit code is 0. The only method I can think of is to redirect the output to a file, then if the exit code is not 0 output that file for cron to grab. Seems pretty horrible though.

Theozaurus
  • 411
  • 4
  • 3
8

If you want to send all output (stdout and stderr) to a specific address then you can use the MAILTO variable. For example, place the following at the top of the script.

MAILTO="address@example.com"
Dan Carley
  • 25,189
  • 5
  • 52
  • 70
5

try adding "root: your@email.address" to /etc/aliases

that will send all messages for that user to your email. if you don't want all messages, you could create a user specifically for this.

As long as the script outputs something, you will get a mail.

Daniel P
  • 185
  • 7
3

On all of my productions servers which typically run about 20 cronjobs daily I swear by the python-cronwrap package. Check it out here: http://pypi.python.org/pypi/cronwrap. It's really easy to configure and most of all reliable.

Low Kian Seong
  • 341
  • 2
  • 3
  • 10
2

I don't think SSMTP is up to what you need it to do. You need something that can "receive" mail from the cron processes and then send it out to your real mailbox.

I use Sendmail, but that's because I'm an old Sun hand; I know it gets laughed at by all the cool kids these days who use Postfix. Your ubuntu community can guide you with setting up your mail system.

David Mackintosh
  • 14,223
  • 6
  • 46
  • 77
2

An alternative - I archive all root mail to some files, and then delete the original mail.

I cron a script (here is the key part) -

#!/bin/bash
if `/usr/bin/mail -e`; then
   /usr/bin/mail --print 2>&1 > /tmp/email_${date +"%Y-%m-%d_%H.%M").log
   echo ‘d *’ | /usr/bin/mail -N > /dev/null
fi
exit 0

This keeps things tidy and I can keep an eye on it. I could email a daily mail file out to an external email id, etc...

irdroid3
  • 82
  • 1
  • 5