5 whenjobs - A powerful but simple cron replacement
9 Editing the jobs script:
14 Get and set variables:
16 whenjobs --get variable
17 whenjobs --set variable value [--type bool|int|float|string]
20 Start and stop the per-user daemon:
22 whenjobs --daemon-start
23 whenjobs --daemon-stop
24 whenjobs --daemon-status
25 whenjobs --daemon-restart
29 Whenjobs is a powerful but simple replacement for cron. It lets you
30 run jobs periodically like cron, but it also lets you trigger jobs to
31 run when user-defined variables are set or change value.
33 Periodic jobs are written like this:
37 # Get the current load average.
38 load=`awk '{print $1}' /proc/loadavg`
39 whenjobs --set load $load --type float
42 When-statements let you create jobs that run based on variables set
47 mail -s "ALERT: high load average: $load" $LOGNAME < /dev/null
50 (When statements are "edge-triggered", meaning that this job will only
51 run when the load goes from under 6 to E<ge> 6).
53 Like L<crontab(5)>, whenjobs are controlled by a jobs file which can
54 be edited from the command line:
58 Whenjobs uses a daemon called L<whenjobsd(8)>. Unlike crond, this
59 daemon runs as the same user. Each user who wants to use whenjobs
60 starts their own daemon:
62 $ whenjobs --daemon-start
64 You can also have the daemon start as you when the machine boots by
65 adding the following line to a boot file such as C</etc/rc.local>.
66 Replace C<username> with your username:
68 su username -c /usr/sbin/whenjobsd
70 Variables are the key to expressing dependencies between whenjobs.
71 Variables are stored (per-user) in the daemon. You can use the
72 command line tool to examine and set variables:
74 $ whenjobs --variables
76 $ whenjobs --set cat sushi
80 The act of setting a variable (using I<--set>) can trigger jobs to run.
86 =item B<--daemon-start>
88 =item B<--daemon-stop>
90 Start and stop the per-user daemon.
92 =item B<--daemon-status>
94 Prints the status of the daemon: C<up> or C<down>.
96 =item B<--daemon-restart>
98 Restart the daemon. (If it is not running, then this command
105 Edit the jobs script. If you make changes to the jobs script, then it
106 is automatically uploaded to the daemon.
108 The C<$EDITOR> environment variable is used for editing. If not set,
111 =item B<--get> variable
113 Print the value of a variable.
119 List the jobs script.
121 =item B<--lib> directory
123 Set the library directory which needs to contain the auxiliary files
124 C<pa_when.cmo> and C<whenlib.cma>. Normally you do not need to
125 specify this. However if you are running whenjobs without installing
126 it, then you need to point this to the C<lib/> directory from the
129 whenjobs --lib $builddir/lib -e
131 =item B<--set> variable value
133 =item B<--type> bool|int|float|string|unit
135 I<--set> sets the variable named C<variable> to the new C<value>. The
136 variable is created if it does not already exist. Note that setting a
137 variable can cause jobs to run immediately.
139 To unset a variable, set it to the empty string:
141 whenjobs --set var ""
143 By default variables are strings. You can also set the type of a
144 variable when setting it by adding the optional I<--type> parameter:
146 whenjobs --set free_space 10000 --type int
148 See the discussion of variable types in the L</REFERENCE> section
153 Compile the jobs script and upload it to the daemon, without editing.
154 Note that the I<--edit> option does this automatically. Furthermore,
155 when the daemon is started it checks for a jobs script and loads it if
160 Display all the variables and their values, in the format C<name=value>.
166 Display the name and version of the program and exit.
172 Display brief usage and exit.
178 A whenjobs file consists of a series of one or more "every" or "when"
181 Comments in the file can be written using C<(* ... *)>. Comments
184 Shell script fragments are written using C<E<lt>E<lt> ... E<gt>E<gt>>.
185 Within shell script fragments, use C<#> for comments (as in ordinary
186 shell scripts). Because C<E<gt>E<gt>> has a special meaning, it
187 cannot be used in the shell script (ie. for redirection). You have to
188 write C<E<gt>\E<gt>> instead which is replaced with C<E<gt>E<gt>> when
189 the shell script is parsed.
191 =head2 EVERY STATEMENTS (PERIODIC JOBS)
193 An every statement has the form:
200 where C<E<lt>periodE<gt>> is a I<period expression>, which may take
201 one of the forms below. Don't forget the colon character between the
202 period expression and the shell script.
204 An every statement is a job which runs periodically.
206 =head3 PERIOD EXPRESSIONS
210 =item B<every second>
212 The job runs every second.
214 =item B<every minute>
216 The job runs every minute.
220 The job runs every hour.
224 The job runs every day, at midnight UTC.
228 The job runs every week, on a Thursday at midnight UTC.
232 The job runs every month, on the first of the month at midnight UTC.
236 The job runs every year, on the first day of the year at midnight UTC.
238 =item B<every decade>
240 =item B<every century>
242 =item B<every millenium>
244 The job runs every 10, 100 or 1000 years.
246 =item B<every I<N> seconds>
248 The job runs every I<N> seconds (I<N> is any number E<ge> 1).
250 =item B<every I<N> minutes>
252 The job runs every I<N> minutes.
254 =item B<every I<N> hours>
256 The job runs every I<N> hours.
258 =item B<every I<N> days>
260 The job runs every I<N> days.
262 =item B<every I<N> weeks>
264 The job runs every I<N> weeks.
266 =item B<every I<N> months>
268 The job runs every I<N> months.
270 =item B<every I<N> years>
272 =item B<every I<N> decades>
274 =item B<every I<N> centuries>
276 =item B<every I<N> millenia>
278 The job runs every I<N>, I<10*N>, I<100*N> or I<1000*N> years.
282 =head2 WHEN STATEMENTS (DEPENDENT JOBS)
284 A when statement has the form:
291 where C<E<lt>exprE<gt>> is a I<when expression>, described below.
292 Don't forget the colon character between the period expression and the
295 A when statement is a job which runs when the conditions described in
296 its when-expression become true.
298 When jobs are I<edge triggered>. This means that they run when the
299 condition changes from false to true (or in the case where the
300 expression has not been evaluated before, when it evaluates initially
303 =head3 WHEN EXPRESSIONS
305 When expressions are fully recursive expressions constructed from the
310 =item I<expr> B<&&> I<expr>
312 =item I<expr> B<||> I<expr>
314 The boolean "and" or "or" of the two sub-expressions.
316 =item I<expr> B<E<lt>> I<expr>
318 =item I<expr> B<E<lt>=> I<expr>
320 =item I<expr> B<==> I<expr>
322 =item I<expr> B<E<gt>=> I<expr>
324 =item I<expr> B<E<gt>> I<expr>
326 The two sub-expressions are evaluated and the usual comparison
327 operator is performed.
329 If the sub-expressions are numeric, then numeric comparison is done.
330 If either sub-expression is non-numeric, then both expressions are
331 converted (if necessary) to strings and string comparison is done.
335 Boolean negative of I<expr>.
337 =item I<expr> B<+> I<expr>
339 For numeric sub-expressions, this performs addition.
341 If both sub-expressions are strings, this performs string
344 Other types give an error.
346 =item I<expr> B<-> I<expr>
348 =item I<expr> B<*> I<expr>
350 =item I<expr> B</> I<expr>
352 =item I<expr> B<mod> I<expr>
354 Both sub-expressions are evaluated, and if both are numeric, then the
355 result is subtraction, multiplication, division or modulo.
357 Other types give an error. Note that I<mod> really is an infix
362 If I<expr> is a string, this returns the length of the string.
366 The value of the named variable.
368 Previously undefined variables are automatically initialized to the
371 =item B<prev> I<variable>
373 The I<previous> value of the named variable. This means, the value
374 that it had last time this when-job ran.
376 If the when-job has not run yet, then this returns C<"">.
378 =item B<changes> I<variable>
380 If the named variable has changed since this job last ran, then this
381 evaluates to true, else false.
383 This is the same as writing C<prev variable == variable>.
385 =item B<increases> I<variable>
387 If the named variable has changed and increased since this job last
388 ran, then this evaluates to true, else false.
390 This is the same as writing C<prev variable E<lt> variable>.
392 =item B<decreases> I<variable>
394 If the named variable has changed and decreased since this job last
395 ran, then this evaluates to true, else false.
397 This is the same as writing C<prev variable E<gt> variable>.
399 B<Note:> There is a subtle and difficult problem with using the
400 I<decreases> operator: The first time the expression is evaluated, the
401 job has (by definition) not yet run. Therefore C<prev variable>
402 evaluates to C<""> (see definition of I<prev> above). Since
403 C<"" E<lt> everything>, the I<decreases> operator evaluates to
404 false, and since this usually means the job does not run, the
405 operator always evaluates to false. A future version of whenjobs
406 will address this problem.
410 This evaluates to true the first time the expression is evaluated
411 after the jobs file has been reloaded or the daemon restarted.
412 Thereafter it evaluates to false.
414 You can use this to initialize variables, but note that this does not
415 solve the I<decreases> operator problem described above, because
416 variables are initialized too late to affect that.
422 Constants that evaluate to boolean false or true respectively.
424 =item I<"any string">
428 In a boolean context, the empty string evaluates to false, and
429 non-empty strings evaluate to true.
433 Any integer. (Arbitrarily large integers are supported.)
435 In a boolean context, 0 evaluates to false, and non-zero evaluates to
446 Any floating point number.
448 In a boolean context, 0 evaluates to false, and non-zero evaluates to
455 The code between C<E<lt>E<lt> ... E<gt>E<gt>> is a shell script. It
456 is executed using C<$SHELL>, or if that environment variable is not
459 =head3 SHELL SCRIPT VARIABLES
461 Every variable that has been set (using the whenjobs I<--set> option)
462 is exported to the script, so you can simply get the value of any
463 variable by writing C<$name>.
465 In addition, there are some special variables available:
471 The name of the job. If the job has been named explicitly, then that
472 name is available through this variable, else it will be some implicit
477 The serial number of the job. This is simply a variable that
478 increments each time a job is run, and is unique to that run of the
483 Other environment variables such as C<$HOME>, C<$LOGNAME> etc are
486 =head3 SHELL SCRIPT TEMPORARY CURRENT DIRECTORY
488 The shell script runs with its current directory set to a temporary
489 directory. The temporary directory is removed when the shell script
490 exits. Therefore you can write temporary files here without worrying
491 about cleaning them up.
493 If you want to store permanent state, then you have to save it to a
494 well-known directory, eg. C<$HOME>, C</var> etc.
496 =head3 SHELL SCRIPT USER
498 The shell script runs as the ordinary user. It has no special
503 Jobs are given implicit names (C<job$1>, C<job$2> etc.). You can also
504 name jobs explicitly by preceeding the "every" or "when" statement
513 The job name is passed to the shell script in the C<$JOBNAME>
514 environment variable.
527 =head1 ENVIRONMENT VARIABLES
537 Richard W.M. Jones L<http://people.redhat.com/~rjones/>
541 Copyright (C) 2012 Red Hat Inc.
543 This program is free software; you can redistribute it and/or modify
544 it under the terms of the GNU General Public License as published by
545 the Free Software Foundation; either version 2 of the License, or
546 (at your option) any later version.
548 This program is distributed in the hope that it will be useful,
549 but WITHOUT ANY WARRANTY; without even the implied warranty of
550 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
551 GNU General Public License for more details.
553 You should have received a copy of the GNU General Public License
554 along with this program; if not, write to the Free Software
555 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.