Schedule tasks to run at a set date and time
To run tasks at a specific time in the future different services are available:
at
specifies a one-time task that runs at a certain timecron
can schedule tasks on a repetitive basis, such as daily, weekly, or monthlyanacron
can be used to execute commands periodically, with a frequency specified in days, but unlike cron, it does not assume that the machine is running continuously.
Cron
The crond daemon is the background service that enables cron functionality.
The cron service checks for files in the /var/spool/cron
and /etc/cron.d
directories and the /etc/anacrontab
file. The contents of these files define cron jobs that are to be run at various intervals. The individual user cron files are located in /var/spool/cron, and system services and applications generally add cron job files in the /etc/cron.d directory.
The cron utility runs based on commands specified in a cron table (crontab). Each user, including root, can have a cron file. These files don't exist by default, but can be created in the /var/spool/cron directory using the crontab -e
command that's also used to edit a cron file:
SHELL=/bin/bash
MAILTO=root@example.com
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
# For details see man 4 crontabs
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
# backup using the rsbu program to the internal 4TB HDD and then 4TB external
01 01 * * * /usr/local/bin/rsbu -vbd1 ; /usr/local/bin/rsbu -vbd2
# Set the hardware clock to keep it in sync with the more accurate system clock
03 05 * * * /sbin/hwclock --systohc
# Perform monthly updates on the first of the month
# 25 04 1 * * /usr/bin/dnf -y update
The first three lines in the code above set up a default environment. The environment must be set to whatever is necessary for a given user because cron does not provide an environment of any kind.
Warning: If no user is specified, the job is run as the user that owns the crontab file, root in the case of the root crontab.
To prevent possible misuse, you can control access to the crontab
command by using two files in the /etc/cron.d directory: cron.deny
and cron.allow
. These files permit only specified users to perform crontab command tasks such as creating, editing, displaying, or removing their own crontab files.
The cron.deny and cron.allow files consist of a list of user names, one user name per line.
These access control files work together as follows:
- if cron.allow exists, only the users who are listed in this file can create, edit, display, or remove crontab files
- if cron.allow does not exist, all users can submit crontab files, except for users who are listed in cron.deny
- if neither cron.allow nor cron.deny exists, superuser privileges are required to run the crontab command.
Anacron
The anacron program performs the same function as crond, but it adds the ability to run jobs that were skipped, such as if the computer was off or otherwise unable to run the job for one or more cycles. The anacron program provides some easy options for running regularly scheduled tasks. Just install your scripts in the /etc/cron.[hourly|daily|weekly|monthly]
directories, depending how frequently they need to be run (but see below tip). Alternatively, specify the job to run in /etc/anacrontab
as you would do with the crontab but with anacron-specific syntax (see below).
anacron itself doesn't run as a service/daemon, but as a cron job: /etc/cron.d/anacron. So cron is running and checking if anacron is present for the daily, weekly and monthly tasks (it would be duplication of effort to have both running preriod-fixed tasks), but not for the hourly tasks. cron runs the hourly tasks.
So, actually anacron uses a variety of methods to run:
- if the system is running systemd, it uses a systemd timer (in the Debian package, you'll see it in /lib/systemd/system/anacron.timer)
- if the system isn't running systemd, it uses a system cron job (in /etc/cron.d/anacron)
- in all cases it runs daily, weekly and monthly cron jobs (in /etc/cron.{daily,weekly,monthly}/0anacron)
- it also runs at boot (from /etc/init.d/anacron or its systemd unit).
anacron will check if a job has been executed within the specified period in the period field. If not, it executes the command specified in the command field after waiting the number of minutes specified in the delay field. Once the job has been executed, it records the date in a timestamp file in the /var/spool/anacron directory with the name specified in the job-id field:
cat /var/spool/anacron/bck.weekly
>20210328
To quickly check if anacron jobs are really executed, you can force immediately their execution: anacron -f -n
Note: The specified delay times in each line help prevent these jobs from overlapping themselves and other cron jobs.
Tip: Instead of placing whole bash programs in the cron.X directories, just install them in the
/usr/local/bin
directory, which will allow you to run them easily from the command line. Then, add a symlink in the appropriate cron directory, such as/etc/cron.daily
.
Examples of job definition syntax:
Every minute of every day:
# m h dom mon dow command
* * * * * /home/user/command.sh
# or
0-59 0-23 0-31 0-12 0-7 /home/user/command.sh
Every 15 minutes of every day:
# m h dom mon dow command
*/15 * * * * /home/user/command.sh
# or
0-59/15 * * * * /home/user/command.sh
# or
0,15,30,45 * * * * /home/user/command.sh
Note: The division expressions must result in a remainder of zero for the job to run.
Every 5 minutes of the 2 am hour starting at 2:03:
# m h dom mon dow command
03-59/5 02 * * * /home/user/command.sh
# This runs at 2:03, 2:08, 2:13, 2:18, 2:23, and so on until 2:58
Every day at midnight:
# m h dom mon dow command
0 0 * * * /home/user/command.sh
# or
0 0 * * 0-7 /home/user/command.sh
Twice a day:
# m h dom mon dow command
0 */12 * * * /home/user/command.sh
# or
# m h dom mon dow command
0 0-23/12 * * * /home/user/command.sh
# or
0 0,12 * * * /home/user/command.sh
Every weekday at 2 am:
# m h dom mon dow command
0 02 * * 1-5 /home/user/command.sh
Weekends at 2 am:
# m h dom mon dow command
0 02 * * 6,7 /home/user/command.sh
# or
0 02 * * 6-7 /home/user/command.sh
Once a month on the 15th at 2 am:
# m h dom mon dow command
0 02 15 * * /home/user/command.sh
Every 2 days at 2 am:
# m h dom mon dow command
0 02 */2 * * /home/user/command.sh
Every 2 months at 2 am on the 1st:
# m h dom mon dow command
0 02 1 */2 * /home/user/command.sh
Shortcuts
The are shortcuts which can be used to replace the five fields usually used to specify times. The @
character is used to identify shortcuts to cron. The list below, taken from the crontab(5) man page, shows the shortcuts with their equivalent meanings.
@reboot
: run once after reboot@yearly
: run once a year, i.e.0 0 1 1 *
@annually
: run once a year, i.e.0 0 1 1 *
@monthly
: run once a month, i.e.0 0 1 * *
@weekly
: run once a week, i.e.0 0 * * 0
@daily
: run once a day, i.e.0 0 * * *
@hourly
: run once an hour, i.e.0 * * * *
These shortcuts can be used in any of the crontab files.
At
at
is an interactive command-line utility that allows you to schedule commands to be executed at a particular time. Jobs created with at are executed only once.
The at command takes the date and time (runtime) when you want to execute the job as a command-line parameter, and the command to be executed from the standard input.
Let's create a job that will be executed at 9:00 am: at 09:00
Once you hit Enter, you'll be presented with the at command prompt that most often starts with at>
. You also see a warning that tells you the shell in which the command will run:
warning: commands will be executed using /bin/sh
at>
Enter one or more command you want to execute: tar -xf /home/linuxize/file.tar.gz
When you're done entering the commands, press Ctrl-D to exit the prompt and save the job:
at> <EOT>
job 4 at Tue May 5 09:00:00 2020
The command will display the job number and the execution time and date.
There are also other ways to pass the command you want to run, besides entering the command in the at prompt. One way is to use echo and pipe the command to at:
echo "command_to_be_run" | at 09:00
The at utility accepts a wide range of time specifications. You can specify time, date, and increment from the current time:
-
time: to specify a time, use the
HH:MM
orHHMM
form. To indicate a 12-hour time format, useam
orpm
after the time (e.g.at 1pm + 2 days
). You can also use strings likenow
,midnight
,noon
, orteatime
(16:00). If the specified time is passed, the job will be executed the next day. -
date: the command allows you to schedule job execution on a given date. The date can be specified using the month name followed by the day and an optional year. You can use strings, such as
today
,tomorrow
, or weekday. The date can be also indicated using theMMDD[CC]YY
,MM/DD/[CC]YY
,DD.MM.[CC]YY
or[CC]YY-MM-DD
formats (e.g.at 12:30 102120
). -
increment: at also accepts increments in the
now + count time-unit
format, wherecount
is a number andtime-unit
can be one of the following strings:minutes
,hours
,days
, orweeks
(e.g.at sunday +10 minutes
).
Time, date and increment can be combined.
Alternatively, use a here document or pass a file with -f
.
To list the user's pending jobs run the atq or at -l command: atq
To remove a pending job invoke the atrm or at -r command followed by the job number: atrm 9