Ubuntu Server 18.04 – Scheduling tasks with cron

How to Create a Droplet with DigitalOcean

Earlier in this chapter, we worked through starting processes and enabling them to run all the time and as soon as the server boots. In some cases, you may need an application to perform a job at a specific time, rather than always be running in the background. This is where cron comes in. With cron, you can set a process, program, or script to run at a specific time-down to the minute. Each user is able to have his or her own set of cron jobs (known as a crontab), which can perform any function that a user would be able to do normally. The root user has a crontab as well, which allows system-wide administrative tasks to be performed. Each crontab includes a list of cron jobs (one per line), which we’ll get into shortly. To view a crontab for a user, we can use the crontab command:

crontab -l 

With the -l option, the crontab command will show you a list of jobs for the user that executed the command. If you execute it as root, you’ll see root’s crontab. If you execute it as user jdoe, you’ll see the crontab for jdoe, and so on. If you want to view a crontab for a user other than yourself, you can use the -u option and specify a user, but you’ll need to execute it as root or with sudo to view the crontab of other users:

sudo crontab -u jdoe -l 

By default, no user has a crontab until you create one or more jobs. Therefore, you’ll probably see output such as the following when you check the crontabs for your current users:

no crontab for jdoe 

To create a cron job, first log in as the user account you want the task to run under. Then, issue the following command:

crontab -e 

If you have more than one text editor on your system, you may see output similar to the following:

Selecting an editor for use with the crontab command

In this case, you’ll simply press the number corresponding to the text editor you’d like to use when creating your cron job. To choose an editor and edit your crontab with a single command, the following will work:

EDITOR=vim crontab -e 

In that example, you can replace vim with whatever text editor you prefer. At this point, you should be placed in a text editor with your crontab file open. The default crontab file for each user features some helpful comments that give you some useful information regarding how cron works. To add a new job, you would scroll to the bottom of the file (after all the comments) and insert a new line. Formatting is very particular here, and the example comments in the file give you some clue as to how each line is laid out. Specifically, this part:

m h dom mon dow command 

Each cron job has six fields, each separated by at least one space or tab spaces. If you use more than one space, or tab, cron is smart enough to parse the file properly. In the first field, we have the minute in which we would like the job to occur. In the second field, we place the hour in the 24-hour format, from 0-23. The third field represents the day of the month. In this field, you can place a 5 (5th of the month), 23 (23rd of the month), and so on. The fourth field corresponds to the month, such as 3 for March or 12 for December. The fifth field is the day of the week, numbered from 0-6 to represent Sunday through Saturday. Finally, in the last field, we have the command to be executed. A few example crontab lines are as follows:

3 0 * * 4 /usr/local/bin/cleanup.sh 
* 0 * * * /usr/bin/apt-get update 
0 1 1 * * /usr/local/bin/run_report.sh 

With the first example, the cleanup.sh script, located in /usr/local/bin, will be run at 12:03 a.m. every Friday. We know this because the minute column is set to 3, the hour column is set to 0, the day column is 4 (Friday), and the command column shows a fully qualified command of /usr/local/bin/cleanup.sh.

A command being fully qualified is important with cron. For example, in the second example, we could have simply typed apt-get update for the command and that would probably have worked just fine. However, not including the full path to the program is considered bad cron etiquette. While the command would probably execute just fine, it depends on the application being found in the PATH of the user that’s calling it. Not all servers are set up the same, so this might not work depending on how the shell is set up. If you include the full path, the job should run regardless of how the underlying shell is configured.

If you don’t know what the fully qualified command is, all you have to do is use the which command. This command, when used with the name of a command you’d like to run, will give you the fully qualified command if the command is located on your system.

Continuing with the second example, we’re running /usr/bin/apt-get update to update our server’s repository index every morning at midnight. The asterisks on each line refer to any, so with the minute column being simply *, that means that this task is eligible for any minute. Basically, the only field we clarified was the hour field, which we set to 0 in order to represent 12:00 am.

With the third example, we’re running the /usr/local/bin/run_report.sh script on the first day of every month at 1:00 am. If you notice, we set the third column (day of month) to 1, which is the same as February 1st, March 1st, and so on. This job will be run if it’s the first day of the month, but only if the current time is also 1:00 am, since we filled in the first and second column, which represent the minute and hour respectively.

Once you finish editing a user’s crontab and save it, cron is updated and from that point forward will execute the task at the time you select. The crontab will be executed according to the current time and date on your server, so you want to make sure that that is correct as well, otherwise you’ll have your jobs execute at unexpected times. You can view the current date and time on your server by simply issuing the date command.

To get the hang of creating jobs with cron, the best way (as always) is to practice. The second example cron job is probably a good one to experiment with, as updating your repository index isn’t going to hurt anything.

Comments are closed.