The simpler alternative to cron: Whenjobs
CountingTime
One of the many heirlooms from early Unix (since V7 Unix to be exact) is the cron daemon, which still runs regular jobs on today's Linux and BSD systems. Although some alternatives to cron have since been developed, such as fcron [1] and anacron [2], the principle itself has barely changed.
Red Hat programmer Richard W.M. Jones has now broken with tradition and come up with a new cron alternative – a project called Whenjobs. Basically, Whenjobs [3] offers two advantages to cron: simpler syntax for defining jobs and execution times and a system that allows users to define dependencies between jobs.
Prebuilt Whenjobs packages are already available for Fedora 17, but users of other distributions will have to build the tool themselves. To install, you can check Whenjobs out from the Git repository. However, it is easier to download the latest tarfile, because then you don't have to do battle with autoconf and automake.
Because Whenjobs is written in the functional programming language, Ocaml, you will need the matching compiler and a few packages. You can install these with the following command, for example, on Ubuntu 12.10:
sudo apt-get install ocaml ocaml-findlib libcalendar-ocaml libcalendar-ocaml-devcamlp4-extra libocamlnet-ocaml-bin
The ./configure
command starts the configuration step, which tells you whether all the necessary packages are installed. During testing, I saw the following error when I ran make
: error: Unbound value XDR.safe_add
. I resolved this by deleting the generated files lib/whenproto_aux.ml
and lib/whenproto_aux.mli
. Calling make install
installs Whenjobs globally on the system.
Startup Aid
When launched with the --help
option, whenjobs
outputs a short help text, listing the available options and parameters (Figure 1). The command whenjobs -e
tells the program to launch an editor, which comes up with a Whenjobs file, although it only contains a comment (Figure 2). The vi editor in the figure shows this to be the .$HOME/whenjobs/jobs.ml
file.
In the case of syntax errors in the jobs file, Whenjobs is not very helpful; in fact, it simply outputs a compiler error message, although it still saves the file. Instead of a file, you can also store several files with the .ml
extension in .whenjobs
; however, you will then need to edit them manually. Additionally, the file names have to obey Ocaml rules; for example, they are not allowed to contain hyphens.
The basics of Whenjobs files are explained in this comment. Comments start with (*
and end with *)
– this is a subtle hint that Whenjobs files themselves are Ocaml files – however, you don't normally need to worry about the programming language when you use Whenjobs. A time starts with the every
keyword and ends with a colon, for example:
every 10 minutes:
The characters <<
then introduce a block of shell commands, which is terminated by the >>
characters.
Variables
The example in the comment in Figure 2 illustrates some Whenjobs features, such as setting variables. To do this, the tool offers the --set
option, which you can extend by indicating the variable type (--type
). The following code thus runs the stat
command first and assigns the results to the free
shell variable. The second line reads this variable and assigns it to the Whenjobs free_space
variable as an integer; the latter is then available to other jobs.
free=`stat -f -c %b /home` whenjobs --set --type int free_space=$free
The lower code segment in Figure 1 shows how to execute new jobs with Whenjobs, depending on certain conditions. The syntax for this is:
when <condition> : <jobcode>
For example, the Whenjobs changes
function lets you monitor when a variable changes. Using the above variables, you can thus formulate a condition such as "if free_space changes and if the value is less than 10,000 (blocks)":
when changes free_space && free_space < 100000 :
For this to work, the Whenjobs daemon (whenjobsd
) must be running; the daemon stores the variables and executes the jobs. It can be started using the whenjobs
front end and the --daemon-start
option. Alternatively, you can also start whenjobsd
directly; then, you can use the -f
option to prevent the daemon from running in the background and the -d
option to turn on debug messages. The whenjobs --variables
command tells the tool to output the list of currently stored variables.
If you do not want a change to a variable to trigger a change event, you can additionally set the --whisper
option:
whenjobs --set free_space=0 --whisper
Whenjobs shows you which jobs are active when you stipulate the --jobs
parameter and which jobs are loaded when you use the --job-names
parameter. You can set the name by adding it before the line that begins with a when
or every
:
job "disk monitoring" every 15 minutes :
You can run individual jobs manually by typing whenjobs --start jobname
. Active jobs can be canceled by typing whenjobs --cancel <number>
– using --jobs
shows the number, and typing:
whenjobs --tail <number>
will show you the output from an active job.
Millennium Proof
When it comes to defining times for scheduled jobs, the tool offers a whole range of options: second
, minute
, hour
, day
, week
, month
, year
, and even decade
, century
, and millenium
[sic]. These options can be combined with every
or with a number: For example, every hour
runs a script once an hour, and every 15 minutes
runs a script every 15 minutes.
Whenjobs also offers a wealth of expressions: They can be linked with logical and (&&
) and or (||
) operators and also negated. Comparisons of two expressions with various combinations of greater than, less than, and equals signs can be numerical or based on string comparisons.
Other built-in functions can compare variables with their previous
values or determine whether a value increases
or decreases
. Also, users can program their own expressions in Ocaml. More information about this is available in the detailed man page provided by the tool.