How to set up a Cron Job in Linux (bonus: systemd timer)

Code on black

Setting up a Cron Job is a basic task in Linux, however it can be quite daunting for a new system administrator to set up one. The syntax isn’t intuitive and chances are many will make one or two mistakes even when experienced. Learn today how to set up a Cron Job on Linux!

What is Cron?

Cron is a job scheduler based on time for Unix-like systems. There are many cases you want to execute a command based on a time schedule. Imagine taking backups or flushing log files. These tasks usually don’t require manual intervention and can be easily automated.

Cron assumes the machine stays always powered on, if a machine is powered off in the period scheduled for a cron job to run, it will not get executed. If you need to make sure a task is executed, anacron is a better alternative to cron.

If you need to schedule a command to only run once, it’s best to use at instead of cron.

Finally there is a new way to set up scheduled jobs using systemd called systemd timers. They are effective replacements of cron commands, they offer more structure and accuracy, but they are also more complex.

The Cron syntax

# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12)
# │ │ │ │ ┌───────────── day of week (0 - 6) (Sunday to Saturday;
# │ │ │ │ │                                       7 is also Sunday on some systems)
# │ │ │ │ │
# │ │ │ │ │
# * * * * *  command to execute

The diagram above is quite self-explanatory, however keep in mind it is easy to commit a mistake when writing a cron job without the diagram in front of you. There are also some special values such as * and */n where n is a number. Let’s take a look at them by example:

# This command is executed every 3th day of the month at 00:20
0 20 3 * * /bin/command
# This command is executed every 2 hours of every day
* */2 * * * /bin/command
# This command is executed every monday and saturday at 07:23
23 07 * * 1,5 /bin/command

Setting up cron and crontabs

Now that you are familiar the cron syntax a question arises: “Where do I put the schedules?”. Traditionally there has always been one cron file called crontab, but many systems nowadays include:

  • A cron.d directory, all files inside this directory are treated as crontab files.
  • Various files such as: cron.hourlycron.dailycron.weekly, cron.monthly. These are crontab files that are executed every hour, day, week or month.

You must also know that there is a single “system crontab” located in /etc/crontab, and that every user can have his own crontab file usually located in /var/spool/cron/crontabs/.

To edit a crontab file you can simply do: crontab -e, by default this will edit the current user’s crontab. In case you want to modify a specific crontab you can do crontab -e /path/to/crontab. If you want to modify the file of another user/as another user (e.g. when you’re root) you can use the following: crontab -u username -e.

Regardless of the options the crontab command will open the default editor, which is in most of the cases vi/vim. Most of the times this can confuse newbie administrators, if you find vim too difficult to use you can change to something of your liking such as nano. You can do so by issuing EDITOR=nano, you must also make sure you have the editor installed.

Setting up anacron

Cron assumes the machine stays always powered on, if a machine is powered off in the period scheduled for a cron job to run, it will not get executed. If you need to make sure a task is executed, anacron is a better alternative to cron.

The only file used by anacron is located in /etc/anacrontab, but the syntax differs significantly from cron:

period delay job-identifier command

The period uses days while the delay is in minutes. The job-identifier is just an identifier used in log files. You can immediately notice that you don’t have the same precision you get with cron. As a matter of fact anacron just ensures the command is executed every period days.

Scheduling one-time commands with “at”

The easiest option to schedule commands that will run only once at a predetermined time is the “at” command. The “at” command is also the one with the easiest syntax to remember:

at -f /path/to/command -v datetime

The -v flag isn’t actually required but it allows you to review the date and time you scheduled. As a matter of fact the datetime value is quite complex, I suggest you to review the at man page to get a better understanding.

If you want to list scheduled at jobs you can do: atq .

If you want to delete an at job you can do: atrm job-number . You can get the job-number from atq.

Systemd timers: a new way to handle schedules

Systemd timers are systemd’s own take at scheduling jobs. They are alternative to cron, but not as easy. First and foremost you will need to create a systemd unit file containing the command you want to execute and place it in /etc/systemd/system directory:

[Unit]
Description=I am an example service!

[Service]
Type=oneshot
ExecStart=/path/to/command

Let’s say this service is called my-command.service. Now you will need to create a timer (file name ending in .timer) and place it in /etc/systemd/system directory:

[Unit]
Description=Execute backup every day at midnight

[Timer]
OnCalendar=*-*-* 00:05:00
Unit=backup.service

[Install]
WantedBy=multi-user.target

Let’s say this time is called my-command-timer.timer. The timer will be executed every day at 05:00, the three asterisk follow the cron syntax but represent year-month-day. Before your timer actually starts working you need to enable it in a systemd fashion:

# systemd enable my-command-timer.timer

There are way more options to systemd timers, and the rabbit hole only gets deeper.

Image courtesy of rh2ox
mark

You may also like...

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.