Cron

From Just another day in the life of a linux sysadmin
Jump to navigation Jump to search

What is cron?

cron itself is a daemon, which means it is running but dormant until one of the scheduled times is hit. It is used to schedule events to run at a specified time.

The following is a narrated "What is cron?" video. It is hosted on YouTube, and features the cast of Team Fortress 2.

What does a cron look like?

Basic cron structure

 *    *    *    *    *    *  user command/to/execute
 ┬    ┬    ┬    ┬    ┬    ┬  
 │    │    │    │    │    │
 │    │    │    │    │    └ year (optional category) 1970-2099
 │    │    │    │    └───── day of week (0 - 6 Sun - Sat)
 │    │    │    └────────── month (1 - 12)
 │    │    └─────────────── day of month (1 - 31)
 │    └──────────────────── hour (0 - 23)
 └───────────────────────── min (0 - 59)


Template:Notice

Short Cuts

Entry Description Equal to
@reboot Run once at startup None
@yearly / @anually Run one a year 0 0 1 1 *
@monthly Run once a month 0 0 1 * *
@weekly Run once a week 0 0 * * 0
@daily / @midnight Run once a day 0 0 * * *
@hourly Run once an hour 0 * * * *

So a cron using a short cut may look like this:

@hourly /usr/local/bin/php /home/user/script.php

Special Characters

Field Allowed Values Allowed Characters
Minutes 0-59 * / , -
Hours 0-23 * / , -
Day of Month 1-31 * / , - L W
Month 1-12 or jan - dec * / , -
Day of Week 0-7 or sun-sat * / , - L #
Year* 1970-2099 * / , -

Template:Info

But what do they mean?

Asterisk ( * ) - Indicates that the cron expression matches for all values of the field.

Slash ( / ) - Describes increments of ranges. */5 **** is every 5 minutes

Comma ( , ) - Used to separate items of a list. Using "MON,FRI" in the 5th field (day of week) means Mondays and Fridays.

Hyphen ( - ) - Defines ranges. 2013-2015 indicates every year between 2013 and 2015.

L - stands for "last". When used in the day-of-week field, it allows you to specify constructs such as "the last Friday" ("5L") of a given month.

W - Allowed for the day-of-month field, W is used to specify the weekday nearest the given day.

Hash ( # ) - Allowed for the day-of-week field, and must be followed by a number between one and five. It allows you to specify "the first Monday" of a given month.


So a cron that runs on the last Friday of every month would look like this:

* * * * 5L /some/command

Where are crons found?

/etc/cron.d/

/etc/cron.daily/

/etc/cron.hourly/

/etc/cron.monthly/

/etc/cron.weekly/

/var/spool/cron/<user>

/etc/cron.d/

These look just like a regular entry from crontab but add the option to mail to and define the shell.

Example:

MAILTO=
SHELL=/bin/bash
*/3 * * * * root /usr/local/sbin/bfd -q

/etc/cron.$timeframe

Crons found in daily, hourly, monthly and weekly do not need any scheduling definitions added. Generally these are in the form of a script. There is a check that runs, if the cron has not fired within the specified time it will run the file.

Example: If /etc/cron.hourly/foo.pl has not run in the past 60 minutes when the check fires off, this script will be run.

/var/spool/cron/<user>

You can edit this by using the crontab command or through the cPanel cron editor.

crontab

  • -l list current crontab
  • -r remove current crontab
  • -e edit current crontab
  • -u edit other users' crontabs (must be root or sudo; must be used with the other above flags)
   Ex. crontab -u username -e

Template:Warning

/etc/cron.deny and /etc/cron.allow

These files will restrict access to cron for the specified users

/etc/cron.allow

If this file exists the user MUST be listed here in order to run cronjobs.

/etc/cron.deny

This file is generally present on all servers. It by default lists nobody in its body. If you would like to allow crons for everyone on the server except for a specific user this file is going to be more friendly than the .allow file.


Logs?

/var/log/cron

/var/log/messages

/var/log/syslog

Template:Info


Troubleshooting Cron Problems

If a customer is complaining because their cron jobs are not working at the correct time, there is a chance that the system clock is not set correctly. Here are the steps for fixing this.

1. Check the date from command line.

[root@host ~]# date
Fri May 16 09:57:12 EDT 2014

This will give you the date, time and time zone.

2. Compare the previous output with the settings in the php.ini file.

[root@host ~]# grep timezone /usr/local/lib/php.ini
date.timezone="America/New_York"

Verify they are using the default php.ini file. If there are multiple, make sure the timezone is set in each one as required--------

3. Finally check the hardware clock. This is the equivalent of the bios clock in a standard PC. It is running independent of WHM.

[root@host ~]# hwclock
Fri 16 May 2014 10:00:14 AM EDT  -0.688859 seconds

4. If date and hwclock do not match, then there will be a discrepancy in the time that cron jobs run. Here is an example of that, it was causing the crons to be 2 hours off

root@host [/var/log]# date
Fri May 9 11:33:10 MDT 2014
root@host [/var/log]# hwclock
Fri 09 May 2014 05:33:16 PM MDT -0.640659 seconds

5. The fix is simple. First, follow the NTP wiki to update the system time. https://wiki.int.liquidweb.com/articles/NTP Next, run the following command.

root@host [/var/log]# hwclock --systohc

This will match the hwclock to the system clock.

You should now see the following output

root@host [/var/log]# date
Fri May 9 12:00:42 MDT 2014
root@host [/var/log]# hwclock
Fri 09 May 2014 12:00:50 PM MDT -0.203498 seconds

6. Watch the cron logs by running:

tail -f /var/log/cron

If the timestamps are still wrong there, try restarting rsyslog, ntpd, and then crond:

/etc/init.d/rsyslog restart; /etc/init.d/syslogd restart # Different cent versions use different variants on syslog, apparently.
/etc/init.d/ntpd restart
/etc/init.d/crond restart