Crontab Basics
tl;dr
crontab -l # List crontab entries
crontab -e # Edit a crontab using the EDITOR specified (export EDITOR=nano)
crontab -r # Remove a crontab
sudo crontab -e # Edit root user’s crontab
crontab my-crontab # add cron jobs by giving a file to crontab
- If you are adding a script in any of the cron directories, it has to be executable
- Use absolute paths for files, directories and executable commands
- it should link to the absolute path of the executables (commands). e.g.
/bin/echo
instead ofecho
. Find out absolute paths with thewhich
command, e.g.which echo
(or consider adding PATH at the top of the crontab file) - Commands that need to be run with
sudo
should be added to theroot
user’s crontab - Have your script create a file that log success or failure, makes it easier to troubleshoot cron
echo "Nightly Backup Successful: $(date)" >> /tmp/mybackup.log
- Recommended is to add cron jobs to any of the cron directories (e.g.
/etc/cron.d
) instead of editing a user’s crontab (crontab -e
) - The user adding the crons needs to be in
cron.allow
(if it exists) - User access is determined by
/etc/cron.allow
and/etc/cron.deny
, if they exist. Blank/etc/cron.deny
means only root is allowed access, plus everyone who’s in/etc/cron.allow
. Nocron.allow
andcron.deny
means everyone has access
Where to add your cron jobs?
There are plenty of places where you can place your cron jobs. You can
- edit the user’s crontab
/var/spool/cron/crontabs/$USER
– not recommended,/var/spool
is considered temp/working directory, could wipe out with updates - edit
/etc/crontab
– This file could be used for other cron commands, but probably shouldn’t be. It is not usual to add commands to this file. While an experienced user should know about it, it is not recommended that you add anything to /etc/crontab. Apart from anything else, this could cause a problem if the /etc/crontab file is affected by updates! - place a file in
/etc/cron.d
– This directory can contain crontab files. The directory is often used by packages, and the crontab files allow a user to be associated with the commands in them. This would not be affected by updates but is a well known location - place a file in
/etc/cron.hourly
,/etc/cron.daily
,/etc/cron.weekly
, or/etc/cron.monthly
It is recommended to add individual scripts in the cron directories instead of editing the user’s crontab, as it can get wiped when you update the cron
package (link). A user’s crontab is stored under the /var/spool
dircetory, which is considered a temporary/working directory and is likely to get deleted during an update
See if a cron has run
Edits to a user’s crontab and the cron jobs run are all logged by default to /var/log/syslog
and that’s the first place to check if things are not running as you expect.
# search the /var/log/syslog for 'CRON' or 'crontab'
#cat /var/log/syslog | grep cron
grep CRON /var/log/syslog
grep -i CRON /var/log/syslog # will show results for both CRON and crontab
Aug 15 06:17:01 amiranzur CRON[14961]: (root) CMD ( cd / && run-parts --report /etc/cron.hourly)
By default cron will email you the output of any program it runs. Popular destinations for cron logs include /var/log/cron
, /var/log/messages
and /var/log/syslog
See if a user has access
- If
/etc/cron.allow
file exists, user must be in it in order to run crontab - If
/etc/cron.deny
file exists, user must NOT be in it in order to run crontab - No
cron.allow
orcron.deny
files exist in a standard Ubuntu install, so all users should have cron available by default, until one of those files is created. - If a blank
cron.deny
file has been created, that will change to the standard behavior users of other operating systems might expect: cron only available to root or users incron.allow
.
Absolute paths
One major pitfall to cron is cron runs in an extremely limited shell environment, as a result a lot of variables aren’t exported in to the environment, mainly
$PATH
. Make sure you use all absolute paths to executable, including common functions likeecho
,uptime
,date
, etc all need to use full paths (/bin/echo
,/bin/date
,/usr/bin/uptime
). To determine the path to an executable, you can use the which command like so:which echo
- this will show you the full path to that tool.
Or, you can expand root users PATH variable by putting the following line at the top of the root crontab file:
PATH=/usr/sbin:/usr/bin:/sbin:/bin
Emails and logging
- By default cron will email you the output of any program it runs. Default email address is
root@yourhost
- You can use a
MAILTO=...
line in the crontab file to have cron send email to a specific address, which should make it easier to grep the mailer daemon logs
MAILTO=my.offsite.email@example.org
00 15 * * * echo "Just testing if crond sends email"
- You can set the cron to explicitly log output to a file by redirecting it (
> /var/log/myjob.log 2>&1
will append all output to /var/log/myjob.log,2>&1
indicates that the standard error (2>) is redirected to the same file descriptor that is pointed by standard output (&1).) You can also use&>>
for the same purpose. &>>
works in Bash whereas2>&1
works in normal shell.You can specify the Shell in the crontab by adding
SHELL=/bin/bash
in thecrontab -e
file. It’ll work for most but not all cron implemetations.If you’re not getting emails than check the system logs. Popular locations are
/var/log/cron
,/var/log/messages
and/var/log/syslog
. Usegrep
to get cron related stuff (cat /var/log/syslog | grep cron
)
Examples
touch /etc/cron.daily/certbot
echo "
# Check and Renew Let's Encrypt SSLs
# run twice a day (12:15am, 12:15pm) as per recommendation
15 0,12 * * * root /usr/bin/certbot renew" > /etc/cron.daily/certbot
chmod +x /etc/cron.daily/certbot
Troubleshooting
- If you have recently changed the server’s timezone then you might need to restart the cron server so it would evaluate the cron times in the proper timezone