Cron hints

09 Jan 2020

Cron is the default scheduler in linux distributions. Here’s a couple of easy helpers

Background

Command Description
crontab -e Open the Cron for the current user
crontab -l List Cron tasks for the current user
crontab -u username -l View the Cron tasks of another user

Cron tasks are added by adding rows at the bottom of the crontab file using the following syntax

1 2 3 4 5 /path/to/command arg1 arg2

or

1 2 3 4 5 /path/to/script.sh

Where,

  1. Minute (0-59)
  2. Hours (0-23)
  3. Day (0-31)
  4. Month (0-12 [12 == December])
  5. Day of the week(0-7 [7 or 0 == sunday]) /path/to/command – Script or command name to schedule
* * * * * command to be executed
- - - - -
| | | | |
| | | | ----- Day of week (0 - 7) (Sunday=0 or 7)
| | | ------- Month (1 - 12)
| | --------- Day of month (1 - 31)
| ----------- Hour (0 - 23)
------------- Minute (0 - 59)

Each value can be made using

Syntax Description
* any value
, value list separator
- range of values
/ step values
whitespace value separator

Examples

syntax result
0 * * * * “At minute 0”
0 * * * * “Every 60 minutes”
* * * * * “Every minute”
*/2 * * * * Every 2 minutes
1-59/2 * * * * Every 2nd minute, from 1 through 59
*/5 * * * * Every 5 minutes
*/15 * * * * Every 15 minutes
0 */2 * * * Every 2 hours, at zero past the hour
0 0 * * * Every day at midnight
0 9-18 * * * Every hour, at zero past the hour, between 9am and 6pm
0 1 * * * Every day at 1am
0 9 * * * Every morning (at 9am)
0 0 * * SUN Every Sunday, just after midnight on Saturday
0 0 * * MON Every Monday, just after midnight on Sunday
0 0 * * TUE Every Tuesday, just after midnight on Monday
0 0 * * WED Every Wednesday, just after midnight on Tuesday
0 0 * * THU Every Thursday, just after midnight on Wednesday
0 0 * * FRI Every Friday, just after midnight Thursday
0 0 * * SAT Every Saturday, just after midnight Friday
0 0 * * 1-5 Every weekday
0 0 * * 0 Every week (On Sunday in this case)
0 0 * * 6,0 Every Weekend day, both on Saturday and Sunday
0 0 1 * * Every month, (on 1st day of the month in this case)
0 0 1 */2 * Every 2nd month
0 0 1 */6 * Every 6 months
0 0 1 1 * Every year

There are some alias helpers which are not universally supported

Syntax Description
@yearly Yearly tasks
@annually Annual tasks
@monthly Monthly tasks
@weekly Weekly tasks
@daily Daily tasks
@hourly Hourly tasks
@reboot Upon reboot

Cron with Seconds resolution

CRON has 60 second resolution, so to get sub minute events, you need to add a cron task more than once.

i.e. Every 30 seconds

* * * * * command
* * * * * sleep 30 && command

Cron location

Path Description Notes
/etc/cron.d Ad-hoc cron file can be placed here  
/etc/crontab System level cron tasks  
/etc/cron.hourly Hourly cron tasks Must be root owner
/etc/cron.daily Daily cron tasks Must be root owner
/etc/cron.weekly Weekly cron tasks Must be root owner
/etc/cron.monthly Monthly cron tasks Must be root owner

Troubleshooting

  1. Checking Start

    When a Cron task starts it is logged in the syslog found at /var/log/syslog also accessible using dmesg for recent events only.

    A cron task executing a script such as 0 * * * * /path/to/script.sh will appear in the log as script.sh, and as a result you can find the task executing using grep.

    grep <pattern> /var/log/syslog which should list every time the pattern is matched in the syslog, and therefore listing every time cron started the task.

    i.e. grep my_script.sh /var/log/syslog

  2. Checking simultaneous execution

    ps aux | grep <pattern> can be used to show all current processes which match a pattern.

    i.e. ps aux | grep my_script.sh

    Sometimes it is worth adding this check into the Cron script to determine whether to bail out preventing multiple copies of a script to execute in parallel

    Example: */2 * * * * /path/to/myscript.sh

     #!/bin/sh
     if ps -ef | grep -v grep | grep doctype.php ; then
             exit 0
     else
             /home/user/bin/doctype.php >> /home/user/bin/spooler.log &
             #mailing program
             /home/user/bin/simplemail.php "Print spooler was not running...  Restarted."
             exit 0
     fi
    

    Another alternative to prevent multiple execution can be achieved via flock

    i.e. * * * * * /usr/bin/flock -n /tmp/fcj.lockfile /usr/local/bin/frequent_cron_job

  3. Logging Errors

    42 1 * * * /path/to/real/job || echo $? will write an error code to the syslog, if the first script fails

    /var/log/auth.log records when authentication occurs, and can therefore be used to determine when processes such as the cron script starts and stops.

    A script which doesn’t report a consistent error already, can be corrected

    • Add set -e -u to top of the script file, under the #! line
    • Then change the cron task script to sh -x main_script.sh || echo Cron task failed: $? and note -x causes each line to be printed out before it is executed
    • Then grep the syslog to find the task grep 'Cron' /var/log/syslog