Linux systems come with a number of tools for scheduling tasks on a system. The traditional way to do this is to use the
cron daemon for persistant scheduled jobs or the
at command for non-persistant jobs. The new alternative is to use systemd timers as it is more flexible and more reliable.
Scheduled commands with cron
Cron is a system for scheduling tasks to be run periodically with a precission of one minute. Multiple implementations are available, but most Linux distributions use the anacron implementation. The name is derived from the name of the greek god Cronos, the god of time.
Using cron itself is simple, but defining the tasks is a bit more involved as you need to figure out the correct scheduling syntax. Let start with option
-l to list all available tasks that are defined for the current user.
$ crontab -l no crontab for user01
With the option
-e you can edit the cron file as cron makes a copy of the crontab file and lets you edit it via the editor specified in the
EDITOR environment variable or specified as the system default as a fallback.
$ crontab -e
-r will remove all tasks from the crontab file without prompting for confirmation. Some users confuse this with the
-e option which will edit the crontab file or to view the crontab file in read-only mode.
Removing all tasks from the crontab file can be done with the option
$ crontab -r
All actions are performed on the crontab file for the current user, but with the following option
-u <user> you can also perform them on the crontab file for another user.
# crontab -u user01 -l
Beside the crontab files per user in /var/spool/cron there is also a cron file for the system cron daemon in /etc/crontab and a cron file for the root user in /etc/cron.d. Taking a closer look at /etc/crontab you can see that the system cron daemon is using the cron file for the root user and can run commands under a different user.
$ cat /etc/crontab SHELL=/bin/bash PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root # 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
Crontab settings per user are located in /var/spool/cron and are similar to the crontab file for the system cron daemon, but without the option to switch to a different user. For all these values you can combine them as single value, a list of values or a range of values, but also divide them to get a matching schedule. Some examples are listed in the table below.
Every Friday (5) the is on April (4) 3th at 2:01am
Every day at 4:30am
Every day at 4:30am, 5:30am and 6:30am
Every day at 4:30am, 6:30am, 8:30am
Every day at 4:30am, 6:30am and 8:30am
Every workday during an even month at 15:00 and 20:00
Every 10 minutes between 8am and 5pm and between 10pm and 11pm
Scheduled commands with at
at [-V] [-q queue] [-f file] [-mMlv] timespec...
at [-V] [-q queue] [-f file] [-mMkv] [-t time]
at -c job [job...]
atq [-V] [-q queue]
at [-rd] job [job...]
atrm [-V] job [job...]
# systemctl list-timers NEXT LEFT LAST PASSED UNIT ACTIVATES Wed 2021-11-17 02:00:00 CET 15s left Wed 2021-11-17 01:50:34 CET 9min ago sysstat-collect.timer sysstat-collect.service Wed 2021-11-17 03:19:18 CET 1h 19min left Wed 2021-11-17 01:22:46 CET 36min ago dnf-makecache.timer dnf-makecache.service Wed 2021-11-17 21:30:46 CET 19h left Tue 2021-11-16 11:17:42 CET 14h ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service Thu 2021-11-18 00:00:00 CET 22h left Wed 2021-11-17 00:45:27 CET 1h 14min ago logrotate.timer logrotate.service Thu 2021-11-18 00:00:00 CET 22h left Wed 2021-11-17 00:45:27 CET 1h 14min ago mlocate-updatedb.timer mlocate-updatedb.service Thu 2021-11-18 00:00:00 CET 22h left Wed 2021-11-17 00:45:27 CET 1h 14min ago unbound-anchor.timer unbound-anchor.service Thu 2021-11-18 00:07:00 CET 22h left Wed 2021-11-17 00:45:27 CET 1h 14min ago sysstat-summary.timer sysstat-summary.service Mon 2021-11-22 01:07:18 CET 4 days left Mon 2021-11-15 01:00:34 CET 2 days ago fstrim.timer fstrim.service n/a n/a Mon 2021-11-15 00:00:35 CET 2 days ago rdiff-backup.timer rdiff-backup.target 9 timers listed. Pass --all to see loaded but inactive timers, too
$ systemctl --user stop schedule-test.timer
$ systemctl --user disable schedule-test.timer
$ systemctl --user stop schedule-test.service
$ systemctl --user disable schedule-test.service
$ systemctl --user daemon-reload
$ systemctl --user reset-failed
[Unit] Description=Schedule a message every 1 minute RefuseManualStart=no # Allow manual starts RefuseManualStop=no # Allow manual stops [Timer] #Execute job if it missed a run due to machine being off Persistent=true #Run 120 seconds after boot for the first time OnBootSec=120 #Run every 1 minute thereafter OnUnitActiveSec=60 #File describing job to execute Unit=schedule-test.service [Install] WantedBy=timers.target
Transient timer units
# systemd-run --on-active=30 /bin/touch /tmp/foo
# systemd-run --on-active="1h 5m" --unit app.service