How to Schedule Job on Linux using Cron, Anacron and at Commands

schedule jobs linuxJob scheduling is a feature that allows a user to submit a command or program for execution at a specified time in the future. On a Linux server, it is important that certain tasks run at certain times The execution of the command or program could be one time or periodically based on a pre-determined time schedule. For example, scheduling system maintenance commands to run during nonworking hours is a good practice, as it does not disrupt normal business activities.

Understanding job scheduling

Linux has two daemons of scheduling jobs based on whether they’re regularly occurring: atd and crond. The cron system runs jobs repetitively at pre-specified times that can be monthly, weekly, daily, hourly, or even per minute while the at system is used for jobs scheduled one time in the future such as to run a job over the weekend. A third system, called anacron which is closely related to cron is used for running periodic jobs on a system that may not always be on like laptops. In this article, I will explain how you can use each command to schedule your tasks or jobs on your Linux server

1) Schedule tasks with the cron service

We typically schedule intensive jobs at times when the system is expected to be underused such as overnight. A daemon called crond runs in the background and check its configuration every minute to examine configuration files in order to execute commands or shell scripts specified if the time matches the time indicated. A series of configuration files under /etc can also contain jobs and control which users are allowed to add jobs using crontab.

# ls -ld /etc/cron*
drwxr-xr-x. 2 root root 4096 Aug 24 17:05 /etc/cron.d
drwxr-xr-x. 2 root root 4096 Aug 24 16:03 /etc/cron.daily
-rw-------. 1 root root 0 Mar 31 2016 /etc/cron.deny
drwxr-xr-x. 2 root root 4096 Jun 9 2014 /etc/cron.hourly
drwxr-xr-x. 2 root root 4096 Jun 9 2014 /etc/cron.monthly
-rw-r--r--. 1 root root 451 Jun 9 2014 /etc/crontab
drwxr-xr-x. 2 root root 4096 Jun 9 2014 /etc/cron.weekly

Managing the cron service is easy because it doesn't need to be reloaded or restarted to activate changes to their configuration. The cron daemon wakes up every minute and checks its configuration to see whether anything needs to be started. You can check its status as below

# systemctl status crond
● crond.service - Command Scheduler
   Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2017-08-19 03:12:38 UTC; 1 weeks 0 days ago
 Main PID: 3240 (crond)
   CGroup: /system.slice/crond.service
           └─3240 /usr/sbin/crond -n

a) Syntax of crontab files

crond executes cron jobs on a regular basis if they comply with the format defined in the /etc/crontab file. Crontables for users are located in the /var/spool/cron directory. The other location where system crontables are stored is the /etc/cron.d directory. Only the root user is allowed to create, modify, or delete them. The crond daemon scans entries in the files at the two locations to determine a job execution schedule. Instead of modifying /etc/crontab, different cron configuration files are used as cron files in /etc/cron.d or scripts in /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly, and /etc/cron.monthly.

A cron table includes six fields separated by space or tab characters. The first five fields specify the times to run the command, and the sixth field is the absolute pathname to the command to be executed. You can place commands in a shell script and schedule it to run repetitively while the sixth field is the absolute pathname to the shell script. The initial section of the cron table specifies the environment used while executing commands. The remainder of the file contains comments that identify the format of a cron table entry.

# 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

The columns, in order, are:

  • Minute of hour (0-59): 
  • Hour of day in 24 hour time (0-23): The hour of the day is listed in military time. For example, to indicate that a job is to run at 3:00 p.m., you would list 15 for that field
  • Day of month (1-31)
  • Month of year (1-12): you can use the first three letters of the name rather than a number if you prefer
  • Day of week (0-7): both 0 and 7 correspond to Sunday. You can use the first three letters of the name rather than a number if you prefer
  • Command or script to execute: after the username for the cron job, you can use a script which must be executed instead of the command

On Debian systems, the content of the crontab file looks differents as below

cat /etc/crontab 
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user	command
17 *	* * *	root    cd / && run-parts --report /etc/cron.hourly
25 6	* * *	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6	* * 7	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6	1 * *	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )

After the first five fields, /etc/crontab entries continue with the account name to be used when executing the program in the sixth field. For instance, a task definition in /etc/crontab can look as follows:

# This task would start 10 minutes after 5 a.m. on December 3 only.
10 5 3 12 * nobody /usr/bin/false
# run a task every minute between 5:00 a.m. and 5:59 a.m
* 5 * * * nobody /usr/bin/false

The anatomy of a single entry in this file is shown as described below

  • If you want to match all values for a column (any value), use an asterisk (*)
  • A list separated by commas such as 0,10,16 matches any of the specified values
  • Two values separated by a dash ( - ) indicate a range, inclusive of the end points
  • A slash, when used in conjunction with some other multi-value option, specifies stepped values. A stepped value is a range in which some members are skipped. For instance, */30 in the minute field indicates a job that’s run every 30 minutes
# execute the /root/process.sh shell script at 5:20 PM and 5:40 PM Monday to Friday regardless of the day of the month or month of the year
20,40 17 * * 1-5 root /root/script.sh

b) Create or edit user cron table

Normally all users are allowed to schedule jobs on Linux systems but only the root is authorized to edit the /etc/crontab file. To create a user cron job, you use the crontab utility, not to be confused with the/etc/crontab configuration file. The syntax for crontab is as below:

crontab [-u user] [-l | -e | -r] [file]

In detail, we have

  • -u: specifies the name of the user whose crontab is to be used (when listing) or modified (when editing)
  • -l: it displays the current user crontab file.
  • -r: removes the current user crontab file. All cron jobs will be removed
  • -e: it helps to edit the current user crontab file.

Schedule a cron to execute on every minute

Each individual user will have their own crontab file, you can use the-e option to the crontab command, which opens the vi editor or depending on your system will propose you a list texts editors. You can then enter the appropriate cron table entries:

$ crontab -e
  # display the date into a file every minute
  * * * * * echo "it is $(date)" >> date-file

Now you can see if a crontab file of our user "paul" has been created

$ cat /var/spool/cron/paul
  # display the date into a file every minute 
  * * * * * echo "it is $(date)" >> date-file

When we don't include the full path of the file, it means that the file will be created in the home directory of the user. Now we can look about our cron job

$ cat /home/paul/date-file 
it is Thu Aug 31 03:43:01 UTC 2017
it is Thu Aug 31 03:44:01 UTC 2017
it is Thu Aug 31 03:45:01 UTC 2017
it is Thu Aug 31 03:46:01 UTC 2017

If we didn't redirect the output into a file, it will get emailed every minute to the user

Schedule a cron to execute on every five (05) minutes

As root user, you can also edit or list the crontab of another user with-u parameter

# crontab -e -u stephen
  # ping the gateway every 05 minutes and redirect the result in a file 
  */5 * * * * ping -c 10 192.168.10.1 >> ping-file
# cat /home/stephen/ping-file 
PING 192.168.10.1 (192.168.10.1) 56(84) bytes of data.
64 bytes from 192.168.10.1: icmp_seq=1 ttl=255 time=2.07 ms
64 bytes from 192.168.10.1: icmp_seq=2 ttl=255 time=2.63 ms
64 bytes from 192.168.10.1: icmp_seq=3 ttl=255 time=1.35 ms
64 bytes from 192.168.10.1: icmp_seq=4 ttl=255 time=1.04 ms

To remove all the cron job of a user, use the command as below

# crontab -r -u paul

We can check the result as below

# crontab -l -u paul
no crontab for paul

Schedule a cron to execute a script during certain time on selected days of week

You can schedule a script instead of a command

# crontab -e -u paul
  #run a script to check the server cpu during the time where the charge can be max
  1-45 22-23 * * 0,1,4,6 /home/paul/check-cpu-script.sh >> check-cpu-file

We can check the result

# cat /home/paul/check-cpu-file 
CPU utilization percentage : 1%|avg=1%;40;70;0;100 cpu0=1%

Schedule multiple tasks in single cron during certain time on selected days of week

# crontab -e
11-45 18-20 * * 0,4,6 /home/paul/check-cpu-script.sh >> check-cpu-file; ping -c 10 192.168.10.1 >> check-cpu-file

we can check the file as below

# cat /home/paul/check-cpu-file
CPU utilization percentage : 1%|avg=1%;40;70;0;100 cpu0=1%
PING 192.168.10.1 (192.168.10.1) 56(84) bytes of data.
64 bytes from 192.168.10.1: icmp_seq=1 ttl=255 time=2.07 ms
64 bytes from 192.168.10.1: icmp_seq=2 ttl=255 time=2.63 ms

Schedule tasks with special syntax

Many administrative tasks are performed on an hourly, daily, weekly, or monthy basis. They are essential shortcuts for the equivalent numeric schedule specified:

  • @hourly for 0 * * * * to run once an hour, on the hour.
  • @daily for 0 0 * * * to run once a day at midnight
  • @weekly for 0 0 * * 0 to run once a week on Sunday at midnight.
  • @monthly for 0 0 1 * * to run at midnight on the first of the month. So schedule a cron job beginning of every month
  • @yearly for 0 0 1 1 * to run once a year at midnight on January 1. So, you can use it if you want a job to be executed on the first minute of every year
  • @reboot to run once after reboot

So you can schedule a backup as below

# the cron 0 0 * * * /usr/local/bin/backup.sh can be define as below
@daily /usr/local/bin/backup.sh

If you have a task of this type, you don’t need to create a system cron table. Instead, you can place a shell script that runs the appropriate commands in one of the following directories:

  • Scripts that should be executed hourly in the/etc/cron.hourly/directory
  • Scripts that should be executed daily in the/etc/cron.daily/ directory
  • Scripts that should be executed weekly in the/etc/cron.weekly/ directory
  • Scripts that should be executed monthly in the/etc/cron.monthly/ directory

The contents of these scripts is bash shell scripting code, and they don’t contain any of the time indicators that are specific to cron. For example, to execute the script below every hour, we have to move it in the /etc/cron.hourly/ directory

#vim /etc/cron.hourly/check-cpu.sh
  #!/bin/bash
  echo "it is $(date)" >> script-file-result
  /usr/lib/nagios/plugins/check_centreon_snmp_cpu -H localhost -C public -v 2c -w 40 -c 70 >> >> script-file-result

On Ubuntu systems, cron table entries within the/etc/crontab file are used to execute the contents of the /etc/cron.hourly/,/etc/cron.daily/,/etc/cron.weekly/, and/etc/cron.monthly/ directories.

Some cron scheduling explanation

I will give you some cron jobs scheduling explanation which can help you as below

  • 0 * 4 12 * command: every hours of the 4 December
  • 50 * * * * command: every hours at 50 minutes exactly.  So à 00 h 50, 4 h 50, 14 h 50, etc.
  • 0 0 * * 1 command: every mondays at midnight (the night from sunday to monday).
  • 45 7 1-10 * * command: every morning 7 h 45  from the 1st to 10th of every month.
  • 0 */2 * * * command: every 2 hours (00 h 00, 02 h 00, 04 h 00…)
  • 0 4 * 12 * command: every days of the December month at 4 AM
  • */10 * * * 1-5 command: every 10 minutes from monday to friday
  • 0 0 * * 1,3,4 command: midnight from monday, wednesday and thursday

Cron is great, but it has one weakness: it is designed for machines that are left running continuously. If your machine is turned off when a job falls due, it simply won't be run. It exists another solution which helps to execute the tasks when you server get up after.

2) Schedule tasks with the anacron service

Anacron is a simplified cron that complements the existing cron system. It is made to handle jobs that run daily or less frequently and jobs for which the precise time doesn’t matter. Anacron’s chief advantage over cron is that it runs jobs that were scheduled to go when the computer was off.

Anacron was developed to ensure that specific tasks will be executed at a guaranteed interval. That ensures that the task will also run if the system has been down for maintenance temporarily.

a) Syntax of anacron files

To ensure regular execution of the job, cron uses the anacron service. This service takes care of starting the hourly, daily, weekly, and monthly cron jobs, no matter at which exact time. To determine how this should be done, anacron uses the /etc/anacrontab file.

In/etc/anacrontab, the jobs to be executed are specified in lines that contain four fields

# cat /etc/anacrontab 
# /etc/anacrontab: configuration file for anacron

# See anacron(8) and anacrontab(5) for details.

SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# the maximal random delay added to the base delay of the jobs
RANDOM_DELAY=45
# the jobs will be started during the following hours only
START_HOURS_RANGE=3-22

#period in days   delay in minutes   job-identifier   command
1	5	cron.daily		nice run-parts /etc/cron.daily
7	25	cron.weekly		nice run-parts /etc/cron.weekly
@monthly 45	cron.monthly		nice run-parts /etc/cron.monthly

The syntax of anacron can be considered as explained below:

  • period (in days): The first field specifies the frequency of job execution, expressed in days. For example, a 1 (one) in this field means run it every day. We can use the special syntax "@"
  • delay (in minutes): the second column specifies how long anacron waits before executing the job. The delay feature is intended to help keep the system from being overloaded if anacron determines it needs to run several commands when it starts up
  • job-identifier: it identifies the command. Its purpose is to identify the job in messages, log files, and for special execution
  • command: the last field is the command that should be executed

The nice command runs the command at a lower priority. run-parts is a tool that comes with cron that runs each file in the given directory one after another.

b) Schedule task with anacron

As we have seen the syntax of the anacron file which already has a content, you can insert your job as below at the end of the file

@daily    15    rsync.daily   /bin/bash /home/steven/script/backuprsync.sh

if the system is down, anacron will execute the script 15 minutes after the system comes back up.

Although useful to know how anacron works, it typically is not a service that is often recommended to configure directly. The need to configure services through anacron is taken away by the cron.hourly, cron.daily, cron.weekly, and cron.monthly files. Of course, to do any good, the anacron utility must be called itself. To schedule a job in anacron you can just drop the script into the right folder and change the delay for your convenience.

Test the anacron syntax

It is possible to can check for any syntax error or other issues with the anacrontab file using the command below

# anacron -T

If there is any error, you will have a message as below which indicates the line of the error

anacron: /etc/anacrontab: Unknown named period on line 17, skipping

Run anacron job in foreground

Normally anacron forks background jobs, and it will just not display anything on the screen. But sometimes you can need to see the output on the screen itself. It is possible with the-d parameter of the command as below:

# anacron -d
Anacron started on 2017-09-01

Force the anacron job execution

To force the execution of anacron job you can use the-f option. This option has the particularity to still consider the delay specified in the anacrontab file.

# anacron -d -f
Anacron started on 2017-09-01
Will run job `cron.daily' in 34 min.
Will run job `rsync.daily' in 44 min.
Will run job `cron.weekly' in 54 min.
Will run job `cron.monthly' in 74 min.

Force the anacron job execution immediately

Despite the-f option which forces the execution by respecting the delay, the-n parameter forces the execution at the present instant that you launch it. It will not consider any delays.

# anacron -d -n
Anacron started on 2017-09-01
Checking against 0 with 31
Will run job `rsync.daily'
Jobs will be executed sequentially
Job `rsync.daily' started
Job `rsync.daily' terminated (exit status: 3) (mailing output)
Normal exit (1 job run)

There is no other script/job on the other cron folders

3) Schedule jobs with at service

Sometimes cron and anacron are overkill. Whereas cron is used to schedule jobs that need to be executed on a regular basis, the atd service is available for services that need to be executed only once. To run a job through the atd service, you would use the at command. The at command’s tasks or jobs are queued up in the /var/spool/at directory, with a single file representing each job.

a) at command syntax

In ordinary use, the at command only needs a single option: a time to run which can be

  • a specific time (time of day): You can specify the time of day as HH:MM, optionally followed by AM or PM if you use a 12-hour format. If the specified time has already passed, the operation is scheduled for the next occurrence of that time
  • a time indication: it exists keyword which stands for what you’d expect as noon (12:00), midnight (00:00), or teatime (16:00)
  • a specified day: to schedule an at job more than 24 hours in advance, you must add a date specification after the time-of-day specification. This can be done in the numeric form, using the format MMDDYY, MM/DD/YY, or DD.MM.YY. Alternatively, you can specify the date as month-name day or month-name day year.
  • a specified period in future: You can specify a time using the keywordnow, a plus sign +, and a time period to run a job at the time specified.

b) create, edit, list or remove "at" jobs

After you use the at command with one of the forms above, the at shell opens. From this shell, you can type several commands that will be executed at the specific time that is mentioned. After entering the commands, useCtrl-D to quit the at shell.

Schedule a task at a specified time

# at 2pm 
at> echo "Good afternoon" 
at> <EOT>

You should receive a mail with the message.

Schedule a task for the future

# at 04:47 09/08/17
at> tail -f -n 30 /var/log/centreon-engine/centengine.log >> /home/paul/centengine-log
at> <EOT>

You can schedule task for some weeks as below

# at now +2 weeks

List and remove scheduled tasks

After scheduling jobs with at, you can use the atq command ( q for queue ) to get an overview of all jobs currently scheduled. It is also possible to remove current at jobs with the atrm command

# atq
1	Fri Sep  1 06:19:00 2017 a root
2	Fri Sep  1 06:20:00 2017 a root
4	Fri Sep  1 05:30:00 2017 a root
3	Fri Sep  1 05:20:00 2017 a root
5	Fri Sep  1 14:00:00 2017 a root
10      Fri Sep  8 04:47:00 2017 a root

You can see the tasks which will be executed at the time specified. We can remove a task as below

# atrm 10 

We can check by listing again the scheduled tasks

# atq
1	Fri Sep  1 06:19:00 2017 a root
2	Fri Sep  1 06:20:00 2017 a root
4	Fri Sep  1 05:30:00 2017 a root
3	Fri Sep  1 05:20:00 2017 a root
5	Fri Sep  1 14:00:00 2017 a root

4) Allowed and disallowed users for scheduled job

By default, all users can schedule jobs and it is possible to limit which user is allowed to schedule jobs by using some special or permissive files

a) Managing "cron" security

It is possible to limit which user is allowed to schedule cron jobs by using the/etc/cron.allow and/etc/cron.deny configuration files. If the cron.allow file exists, a user must be listed in it to be allowed to use cron. If the cron.deny file exists, a user must not be listed in it to be allowed to set up cron jobs. If neither file exists, only root can manage cron jobs

b) Managing "at" security

at has a set of security files,/etc/at.allow and /etc/at.deny, which allow users to or prevent users from queuing up at jobs. If the at.allow file exists and contains usernames, only those users, and the root user are allowed to use at. If the /etc/at.deny file exists and contains usernames, those users are denied and all others are allowed. If neither file exists, only the root user is allowed to submit at jobs.

5) Issues about path and global environment

Scripts can work fine when running in the command line but don’t work when running from cron and it is a common problem. The environment is different because cron doesn’t run the.bash_profile and.bashrc scripts. Therefore, you can expect a minimal environment, including a basic PATH. You can also indicate your shell environment then, follow with the cron job

# crontab -e
PATH=/your_script_path:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
SHELL=/bin/bash
15 1 * * 3-7 script.sh >> script-result

We learned how to schedule jobs for future execution, to configure cron to execute jobs repeatedly at a specific time. We learned that different methods exist to tell cron when a job should be executed. Periodic tasks can be run through cron or anacron so that the systems administrator doesn’t need to run the jobs manually. If a computer is off when a scheduled cron job was to run, the job won’t be executed. Anacron solves this problem by running the job when the computer is turned on. The at facility lets you run ad-hoc jobs at a particular future time.

About Alain Francois

IT Linux administrator passionate of free and open source software, I work on Linux Systems since some years on installations and deployments of certain solutions. I like to share my experiences with a wider audience by training and conferences.

Author Archive Page

Have anything to say?

Your email address will not be published. Required fields are marked *

All comments are subject to moderation.