Command the Command Line

Part IV - Managing Systems

Scheduling (TODO)

This chapter has yet to be completed.

If you've been following along through the previous chapters, you can now write some pretty sophisticated scripts that perform all sorts of administrative tasks. But the only way we know to start them is by typing a command into a terminal. For all the automation techniques we've learned up to this point, we're still a bit limited in how we kick things off.

What if you want something to happen even if you step away from the keyboard? Or what if you'd simply rather not have to act as a timekeeper and enter the same commands over and over again?

Fortunately, Unix-like systems have answers for this--multiple answers, in fact. In this chapter, we'll explore some of the ways you can create task schedules.

cron

a pocket watch

"Cronos" by Pablo is licensed under CC BY-SA 2.0

cron is a "job scheduler"--an application which runs in the background and executes commands (the "jobs") on some interval as specified by its configuration files (the "schedule").

We use many of the utilities covered in this course by executing them from the command line. Because cron is constantly running in the background, we won't interact with it by running it from the command line. Instead, we'll give it instructions by modifying configuration files; it constantly reads these files to determine what to do next.

(By the way: there are actually many software projects which offer this specific functionality; the name cron is a way to reference any one of them generically. The core functionality is specified by POSIX, making the different implementations largely interchangeable. If you limit yourself to using just the features covered in this chapter, then you won't have to worry about which cron implementation is installed.)

crontab

Configure the "table" that cron uses to schedule tasks for a specific user

vm$ crontab -l
no crontab for vagrant
vm$ 

Users on the system can define their own "table" of cron jobs. Invoking crontab with the -l option will show the current user's cron jobs.

vm$ crontab -
​cron is reading what I type to the standard input stream.
​It will try to "install" whatever I type,
​but if my input isn't valid syntax, then cron will reject it.
"-":0: bad minute
errors in crontab file, can't install.
vm$ crontab -l
no crontab for vagrant
vm$ crontab -
​0 0 1 1 0 echo 'This is a valid (though useless) entry.'
vm$ crontab -l
0 0 1 1 0 echo 'This is a valid (though useless) entry.'
vm$ 

If invoked with a dash (-), then crontab will read from the standard input stream and write the result to the current user's configuration file. We use this command rather than editing a file directly because doing so lets cron validate our input before making any changes. That saves us from making typos which could otherwise be very difficult to debug.

There are better ways to edit the cron "table", but we'll use this to learn about the crontab syntax.

crontab syntax

vm$ crontab -l
# cron ignores lines beginning with the `#` character. You can
# use them to explain details of your crontab.
#
#    .------------------------- These characters tell cron when
#    |                          to perform the job.
#    |
#    |             .----------- The rest of the line is the
#    |             |            command to execute to perform
#    |             |            the job.
#.-------. .----------------.
 0 0 1 1 0 echo Hello, world.
vm$ 

cron ignores lines beginning with the number sign (#). We can write whatever we want on lines which start that way, and it won't effect how cron behaves at all. They're often called "comments," and they are a good way to explain details of the other lines which might not be obvious.

Besides the comments, this particular "crontab" has just one entry. The entry has two main parts: a set of characters which tell cron when to perform the job, and the command to execute in order to perform the job.

vm$ crontab -l
 0 0 1 1 0 echo Hello, world.
#^ ^ ^ ^ ^
#| | | | '--------------------- day of the week (0 through 6)
#| | | '----------------------- month of the year (1 through 12)
#| | '------------------------- day of the month (1 through 31)
#| '--------------------------- hour of the day (0 through 23)
#'----------------------------- minute of the hour (0 through 59)
vm$ 

"Execute the command echo Hello, world. at midnight on January first and at midnight on every Sunday in January."

Each of the five values are separated by a space, and they each describe a different aspect of the schedule.

The first value describes the minute of the hour on which cron should run the job. The number zero represents the first minute, the number one represents the second minute, and so on until 59, representing the final minute of the hour.

The second value describes the hour of the day on which cron should run the job. The number zero resents the first hour, the number one represents the second hour, and so on until twenty-three, representing the final hour of the day.

The third value describes the day of the month on which cron should run the job. The number one represents the first of the month, two represents the second, and so on until 31, representing the final day of the month.

The fourth describes the day of the month on which cron should run the job. The number one represents January, two represents February, and so on until twelve, representing December.

The fifth value describes the day of the week on which cron should run the job. The number zero represents Sunday, one represents Monday, and so on until seven, representing Saturday.

cron calculates the intersection of most of the values. In this example, the first two values are zero. This means "the first minute and the first hour of the day" (i.e. "once at midnight"), and not "the first minute or the first hour of the day (i.e. "at the top of every hour").

The "day of week" and "day of month" specifiers are an exception. cron interprets the union of these values. In this example, "day of month" is 1 and "day of week" is 0. cron runs the job on the first day in January and on every Sunday in January (and not on just Sundays which are also the first day of January).