cron

To list the cron schedule...

crontab -l

To edit the cron schedule...

crontab -e

This edits the crontab in your default editor (usually vi)

# ┌───────────── minute (0 - 59)

# │ ┌───────────── hour (0 - 23)

# │ │ ┌───────────── day of the month (1 - 31)

# │ │ │ ┌───────────── month (1 - 12)

# │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday; 7 is also Sunday on some systems)

# │ │ │ │ │ ┌───────────── year (on AWS)                                 

# │ │ │ │ │ │

# │ │ │ │ │ │

# * * * * * * <command to execute>

Run at Reboot

@reboot <command to execute>

Allow / Deny

Anacron

Status

ls /etc/cron.hourly/jobs.deny 2>/dev/null | grep 0anacron | wc -l

Return values:0 - Anacron is Enabled1 - Anacron is Disabled

Configuration

cat /etc/anacrontab

RANDOM_DELAY - specifies the maximum random number of minutes that can be added to the start time of each job. 0 = no Random Delay.START_HOURS_RANGE - specifies a time window (start hour to end hour) when jobs can run.
For each job...[Interval] [Delay] [JobName] [Command]
Interval can be an integer or a macro name...1 = Every 1 day (or use the macro @daily)2 = Every 2 days3 = Every 3 days7 = Every 7 days (or use the macro @weekly)30 = Every 30 days@monthly = once a month, irrespective of number of days in that month
Delay specifies a fixed delay (in minutes) after a job becomes runnable (i.e. machine is running, start_hours_range has started, and interval has passed) before executing a job. (The Random Delay is added to the fixed delay).0 = no delay5 = 5 minute delay60 = 1 hour delay
JobName can, theoretically, be any arbitrary name but, in practice, tends to be:cron.dailycron.weeklycron.monthly
Command can, theoretically, be any command but, in practice, tends to be:nice run-parts /etc/cron.dailynice run-parts /etc/cron.weeklynice run-parts /etc/cron.monthly
The run-parts command will run all executables in the specified directory.You can see what run-parts will run, without running it, by using:
run-parts --test /etc/cron.daily
# /etc/anacrontab: configuration file for anacron
# See anacron(8) and anacrontab(5) for details.
SHELL=/bin/shPATH=/sbin:/bin:/usr/sbin:/usr/binMAILTO=root# the maximal random delay added to the base delay of the jobsRANDOM_DELAY=45# the jobs will be started during the following hours onlySTART_HOURS_RANGE=3-22
#period in days   delay in minutes   job-identifier   command1       5       cron.daily              nice run-parts /etc/cron.daily7       25      cron.weekly             nice run-parts /etc/cron.weekly@monthly 45     cron.monthly            nice run-parts /etc/cron.monthly

Randomization

To avoid spikes where jobs are run on multiple systems at the same time (which could cause issues where any resources are shared e.g. shared disk, or virtualised environments or where there could be a bottleneck in onward processing) configure randomization in /etc/sysconfig/run-parts...

RANDOMIZE=1

Can be 1 (enabled) or 0 (disabled)

RANDOM=5

Can be any integer. 

TODO

Lock/Mutex files

It is good practice to use a lockfile to prevent multiple instances of your job from running. You can either code this manually or install commands like lockfile or flock.

Note that lockfile has a dependency on postfix which you may not want installed.

Using a lockfile containing PID (do this as first step in your script)...

myLF=/var/lock/myscript.lock

touch ${myLF}

read myPID < ${myLF}

[ ! -z "${myPID}" -a -d /proc/${myPID} ] && exit

echo $$ > ${myLF}

...


# Set variable with lockfile name

# Create an empty lockfile if it doesn't exist

# Read any PID from the lockfile

# If PID is not null and the process exists, then exit

# Add the PID of the current script to the lockfile

# Your script steps go here

Using an empty lockfile...

myLF=/var/lock/myscript.lock

trap " [ -f ${myLF} ] && /bin/rm -f ${myLF}" 0 1 2 3 13 15 

[ -f ${myLF} ] && exit

touch ${myLF}

...

rm -f ${myLF}


# Set variable with lockfile name

# Delete the lockfile when the script terminates

# Check if the lockfile exists and exit if it does

# Create the lockfile

# Your script steps go here

# Delete the file (but trap should handle it if you don't)

Using an empty diretory as a lockfile...

myLF=/var/lock/myscript.lock

trap " [ -d ${myLF} ] && /bin/rmdir ${myLF}" 0 1 2 3 13 15 

[ -d ${myLF} ] && exit

mkdir ${myLF} || exit

...

Works in a similar way to the empty lockfile above but avoids the theoretical situation where two scripts run at almost the same instant, both think the file does not exist, and both touch the same file (which is a valid operation and will not throw an error).

Using lockfile...

myLF=/var/lock/myscript.lock

trap " [ -f ${myLF} ] && /bin/rm -f ${myLF}" 0 1 2 3 13 15 

lockfile -r 0 ${myLF} || exit 1

...

The lockfile -r flag specifies the number of retries

# Set variable with lockfile name

# Delete the lockfile when the script terminates

# Check if the lockfile exists and exit if it does

# Your script steps go here

# Delete the file (but trap should handle it if you don't)

Using flock...

flock -n /var/lock/myscript.lock /tmp/myscript.sh



Flock needs no changes to your script. It uses the PID method under the covers. The -n flag forces it to exit if the process is running. Without it flock will wait for the existing process to finish.

Last Modification Date

To see the timestamp of the last change to the crontab...

Solaris

ls -l /var/spool/cron/crontabs/user

Bibliography