Chronic - A constraints-based, opportunistic, application-level scheduler.
Chronic is a constraints-based, opportunistic, application-level scheduler. Unlike cron, that schedules according to a time specification, Chronic schedules tasks when the specified constraints are met. In other words, Chronic schedules during a window of opportunity when the circumstances are favorable.
The original motivation for Chronic was for me to be able to schedule high-impact, recurring tasks like updatedb, emerge rsync, webalizer when I was away from the computer. This proved to be useful enough to abstract the notion of a constraint and build an opportunistic scheduler that schedules according to combinations of arbitrary constraints. The current version of Chronic natively contains System Inactivity, Disk I/O, Load Average, Frequency and Xscreensaver constraints. Network IO activity, cron (that emulates cron), and file alterations under a specified directory, are some of the constraints planned for a future release.
Chronic is implemented as a Unix daemon, chronicd, that reads a chrontab file and executes tasks specified therein. A system level chrontab is placed in /etc/chrontab and user-specific chrontab's live in $HOME/.chrontab. The only option chronicd accepts at the moment is -fg that instructs the application to run in foreground and print debugging messages.
chrontab contains a task per line. A task consists of a command to be run, and one or more constraint's that must be met before the command is run. It should be noted that as of the current version, when more than one constraint is provided for a task, they are AND'ed together. The format of task specification is:
command = COMMAND; constraint = NAME, PARAMETERS; \ constraint = NAME, PARAMETERS; ...; eg: command = "emerge rsync"; constraint = Freq, 86400; \ constraint = Inactivity, 60;
A task specification can be split on multiple lines using the "\" character. It should be noted that constraint names are case-sensitive (and correspond to chucks of code with the same name).
Chronic supports the following constraints in the current version. This list is likely to grow with future releases, so you should check this manpage after upgrading Chronic.
The Inactivity constraint monitors system activity and is met when the system is inactive for a specified amount of time. Inactivity takes one parameter: the number of seconds for which the system must be inactive before the constraint is met. The following task will run updatedb when the system has been inactive for 120 seconds.
command = "/usr/bin/updatedb"; constraint = Inactivity, 120;
Inactivity is a wrapper around the DiskIO and Loadavg constraints, described later in this section. The constraint's notion of inactivity should be appropriate for most systems. Otherwise, it is possible to tune the notion of inactivity using the DiskIO and Loadavg constraints.
The Freq constraint specifies the maximum frequency of invocation of a task. Freq requires one parameter, the number of seconds, that is the minimum difference between two consecutive invocations. So, Freq, 86400 implies that the task should not be run more than once a day. Freq is usually coupled with another constraint (eg: Inactivity) to limit the frequency of opportunistic scheduling. For example:
command = "emerge rsync"; constraint = Inactivity, 120; \ constraint = Freq, 86400;
says, run "emerge rsync" once a day. However, if the system is not inactive for more than one day, "emerge rsync" won't be run till the system is inactive.
The Loadavg constraint monitors the load average of the system. It accepts two parameters: a load average threshold and the amount of time the system load should linger at or below the this threshold before the constraint is considered to be met. The syntax is Loadavg, TIME, LOADAVG. eg. Loadavg, 60, 0.02 is met when the system has a load average of 0.02 or lower for 60 consecutive seconds. Here's an example of usage:
command = "cd /home/user/project/; cvs update; make all"; \ constraint = Loadavg, 60, 0.0; constraint = Freq, 3600;
This task specifies invocation of CVS update under /home/user/project/ and make if the load average is 0.0 for 60 seconds. The Freq constraint additionally limits the task to no more than once in 3600 seconds (one hour).
The DiskIO constraint monitors the disk read/write activity through the vmstat program. It accepts three parameters: a threshold for number of blocks read from disk, a threshold for number of blocks written to disk and the amount of time for which read/write linger at or below these thresholds. DiskIO syntax is DiskIO, TIME, BLOCKS WRITTEN, BLOCKS READ. eg. DiskIO, 60, 10, 15 is met when 10 or less blocks READ> are written to disk and 15 or less blocks are read from disk for 60 consecutive seconds. Here's an example of usage:
command = "/usr/bin/updatedb"; constraint = DiskIO, 60, 0, 0; \ constraint = Freq, 3600;
The Xscreensaver constraints asynchronously monitors Xscreensaver through the xscreensaver-command program. It accepts one parameter: the number of seconds for which Xscreensaver must be enabled before the constraint is met. The syntax for the constraint is Xscreensaver, TIME. eg. Xscreensaver, 120 is met when Xscreensaver is locked for 120 or more seconds. The constraint is considered to be met until the screensaver is unlocked. Here's an example of usage:
command = "emerge rsync"; Constraint = Xscreensaver, 120; \ constraint = Freq, 86400;
The InXs constraint (unrelated to the POP band) combines the Xscreensaver and Inactivity constraints. It is met when either of the constraints is met. InXs is useful for scheduling high-load applications on end-user machines because it's a good indicator of the user being away from the computer. It accepts one parameter: the number of seconds for which either of the constraints is enabled before InXs is met. The syntax for the constraint is InXs, TIME. eg. InXs, 120. Here's an example of usage:
command = "emerge rsync"; Constraint = InXs, 120; \ constraint = Freq, 86400;
The Ping constraint sends a ping to a specified address. It accepts one parameter: IP address to be pinged. If the address is not specified,
188.8.131.52 is pinged -- an arbitrary address on the Internet. Ping syntax is Ping, IP. The constraint is considered to be met if the ping is successful. It should be noted that the current version of the constraint uses the external ping program to send a single ICMP packet to the IP. The Ping constraint is useful for tasks that need a connection to the Internet but might be run on machines that have intermittent connectivity to the Net.
The Concurrent constraint monitors the number of running processes of a specified application and enforces a specified level of concurrency. The systax is Concurrent, APPLICATION, MAX_PROCESSES. As an example, Concurrent, perl, 5 will be met if 4 or less perl's are running at the time of evaluation.
In addition to command and constraint keys, a chrontab task entry can also have the following optional keys.
notify is used to specify a recipient for an email notification that is sent with the task is executed. This notification contains information on timing and status of the executed task. Syntax notify = admin@domain.
only_once is used to indicate that the task should be executed only once. Once executed, the scheduler will remove the task from the chrontab.
Send a SIGHUP to chronicd to force it to re-read chrontabs.
Chronic is alpha software and many a things are likely to change, introduced or improve in future releases. If you have anything you'd like Chronic to do (or do differently), please add a feature request on the sourceforge site, http://sourceforge.net/projects/chronic or send mail to the author.
Vipul Ved Prakash, <firstname.lastname@example.org>
This software is distributed under the ARTISTIC license.