fd0a6e72117cc1f4b52a9c84d4b77ed69d6f9f38
[whenjobs.git] / tools / whenjobs.pod
1 =encoding utf8
2
3 =head1 NAME
4
5 whenjobs - A powerful but simple cron replacement
6
7 =head1 SYNOPSIS
8
9 Editing the jobs script:
10
11  whenjobs -e | --edit
12  whenjobs -l | --list
13
14 Get and set variables:
15
16  whenjobs --get variable
17  whenjobs --set variable value [--type bool|int|float|string]
18  whenjobs --variables
19
20 Start and stop the per-user daemon:
21
22  whenjobs --daemon-start
23  whenjobs --daemon-stop
24  whenjobs --daemon-status
25  whenjobs --daemon-restart
26
27 =head1 DESCRIPTION
28
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.
32
33 Periodic jobs are written like this:
34
35  every 10 minutes :
36  <<
37    # Get the current load average.
38    load=`awk '{print $1}' /proc/loadavg`
39    whenjobs --set load $load --type float
40  >>
41
42 When-statements let you create jobs that run based on variables set
43 elsewhere:
44
45  when load >= 6 :
46  <<
47    mail -s "ALERT: high load average: $load" $LOGNAME < /dev/null
48  >>
49
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).
52
53 Like L<crontab(5)>, whenjobs are controlled by a jobs file which can
54 be edited from the command line:
55
56  $ whenjobs -e
57
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:
61
62  $ whenjobs --daemon-start
63
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:
67
68  su username -c /usr/sbin/whenjobsd
69
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:
73
74  $ whenjobs --variables
75  load=0.9
76  $ whenjobs --set cat sushi
77  $ whenjobs --get cat
78  sushi
79
80 The act of setting a variable (using I<--set>) can trigger jobs to run.
81
82 =head1 OPTIONS
83
84 =over 4
85
86 =item B<--daemon-start>
87
88 =item B<--daemon-stop>
89
90 Start and stop the per-user daemon.
91
92 =item B<--daemon-status>
93
94 Prints the status of the daemon: C<up> or C<down>.
95
96 =item B<--daemon-restart>
97
98 Restart the daemon.  (If it is not running, then this command
99 starts it).
100
101 =item B<-e>
102
103 =item B<--edit>
104
105 Edit the jobs script.  If you make changes to the jobs script, then it
106 is automatically uploaded to the daemon.
107
108 The C<$EDITOR> environment variable is used for editing.  If not set,
109 C<vi> is used.
110
111 =item B<--get> variable
112
113 Print the value of a variable.
114
115 =item B<-l>
116
117 =item B<--list>
118
119 List the jobs script.
120
121 =item B<--lib> directory
122
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
127 source, eg:
128
129  whenjobs --lib $builddir/lib -e
130
131 =item B<--set> variable value
132
133 =item B<--type> bool|int|float|string|unit
134
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.
138
139 To unset a variable, set it to the empty string:
140
141  whenjobs --set var ""
142
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:
145
146  whenjobs --set free_space 10000 --type int
147
148 See the discussion of variable types in the L</REFERENCE> section
149 below.
150
151 =item B<--upload>
152
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
156 found.
157
158 =item B<--variables>
159
160 Display all the variables and their values, in the format C<name=value>.
161
162 =item B<-V>
163
164 =item B<--version>
165
166 Display the name and version of the program and exit.
167
168 =item B<-help>
169
170 =item B<--help>
171
172 Display brief usage and exit.
173
174 =back
175
176 =head1 REFERENCE
177
178 A whenjobs file consists of a series of one or more "every" or "when"
179 statements.
180
181 Comments in the file can be written using C<(* ... *)>.  Comments
182 may be nested.
183
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.
190
191 =head2 EVERY STATEMENTS (PERIODIC JOBS)
192
193 An every statement has the form:
194
195  every <period> :
196  <<
197    # shell script
198  >>
199
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.
203
204 An every statement is a job which runs periodically.
205
206 =head3 PERIOD EXPRESSIONS
207
208 =over 4
209
210 =item B<every second>
211
212 The job runs every second.
213
214 =item B<every minute>
215
216 The job runs every minute.
217
218 =item B<every hour>
219
220 The job runs every hour.
221
222 =item B<every day>
223
224 The job runs every day, at midnight UTC.
225
226 =item B<every week>
227
228 The job runs every week, on a Thursday at midnight UTC.
229
230 =item B<every month>
231
232 The job runs every month, on the first of the month at midnight UTC.
233
234 =item B<every year>
235
236 The job runs every year, on the first day of the year at midnight UTC.
237
238 =item B<every decade>
239
240 =item B<every century>
241
242 =item B<every millenium>
243
244 The job runs every 10, 100 or 1000 years.
245
246 =item B<every I<N> seconds>
247
248 The job runs every I<N> seconds (I<N> is any number E<ge> 1).
249
250 =item B<every I<N> minutes>
251
252 The job runs every I<N> minutes.
253
254 =item B<every I<N> hours>
255
256 The job runs every I<N> hours.
257
258 =item B<every I<N> days>
259
260 The job runs every I<N> days.
261
262 =item B<every I<N> weeks>
263
264 The job runs every I<N> weeks.
265
266 =item B<every I<N> months>
267
268 The job runs every I<N> months.
269
270 =item B<every I<N> years>
271
272 =item B<every I<N> decades>
273
274 =item B<every I<N> centuries>
275
276 =item B<every I<N> millenia>
277
278 The job runs every I<N>, I<10*N>, I<100*N> or I<1000*N> years.
279
280 =back
281
282 =head2 WHEN STATEMENTS (DEPENDENT JOBS)
283
284 A when statement has the form:
285
286  when <expr> :
287  <<
288    # shell script
289  >>
290
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
293 shell script.
294
295 A when statement is a job which runs when the conditions described in
296 its when-expression become true.
297
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
301 to true).
302
303 =head3 WHEN EXPRESSIONS
304
305 When expressions are fully recursive expressions constructed from the
306 following elements:
307
308 =over 4
309
310 =item I<expr> B<&&> I<expr>
311
312 =item I<expr> B<||> I<expr>
313
314 The boolean "and" or "or" of the two sub-expressions.
315
316 =item I<expr> B<E<lt>> I<expr>
317
318 =item I<expr> B<E<lt>=> I<expr>
319
320 =item I<expr> B<==> I<expr>
321
322 =item I<expr> B<E<gt>=> I<expr>
323
324 =item I<expr> B<E<gt>> I<expr>
325
326 The two sub-expressions are evaluated and the usual comparison
327 operator is performed.
328
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.
332
333 =item B<!> I<expr>
334
335 Boolean negative of I<expr>.
336
337 =item I<expr> B<+> I<expr>
338
339 For numeric sub-expressions, this performs addition.
340
341 If both sub-expressions are strings, this performs string
342 concatenation.
343
344 Other types give an error.
345
346 =item I<expr> B<-> I<expr>
347
348 =item I<expr> B<*> I<expr>
349
350 =item I<expr> B</> I<expr>
351
352 =item I<expr> B<mod> I<expr>
353
354 Both sub-expressions are evaluated, and if both are numeric, then the
355 result is subtraction, multiplication, division or modulo.
356
357 Other types give an error.  Note that I<mod> really is an infix
358 operator.
359
360 =item B<len> I<expr>
361
362 If I<expr> is a string, this returns the length of the string.
363
364 =item I<variable>
365
366 The value of the named variable.
367
368 Previously undefined variables are automatically initialized to the
369 empty string.
370
371 =item B<prev> I<variable>
372
373 The I<previous> value of the named variable.  This means, the value
374 that it had last time this when-job ran.
375
376 If the when-job has not run yet, then this returns C<"">.
377
378 =item B<changes> I<variable>
379
380 If the named variable has changed since this job last ran, then this
381 evaluates to true, else false.
382
383 This is the same as writing C<prev variable == variable>.
384
385 =item B<increases> I<variable>
386
387 If the named variable has changed and increased since this job last
388 ran, then this evaluates to true, else false.
389
390 This is the same as writing C<prev variable E<lt> variable>.
391
392 =item B<decreases> I<variable>
393
394 If the named variable has changed and decreased since this job last
395 ran, then this evaluates to true, else false.
396
397 This is the same as writing C<prev variable E<gt> variable>.
398
399 B<Note:> There is a subtle gotcha with the I<decreases> operator: The
400 first time the expression is evaluated, the job has (by definition)
401 not yet run.  Therefore C<prev variable> evaluates to C<""> (see
402 definition of I<prev> above).  Since it is always true that
403
404  "" < anything
405
406 the I<decreases> operator evaluates to false, and since this usually
407 means the job does not run, the operator always evaluates to false.
408
409 To fix this, ensure that the variable is initialized (see
410 L</SETTING THE INITIAL VALUE OF VARIABLES> below).
411
412 =item B<reloaded ()>
413
414 This evaluates to true the first time the expression is evaluated
415 after the jobs file has been reloaded or the daemon restarted.
416 Thereafter it evaluates to false.
417
418 Don't use this to initialize variables: it won't do what you mean.
419
420 =item B<false>
421
422 =item B<true>
423
424 Constants that evaluate to boolean false or true respectively.
425
426 =item I<"any string">
427
428 Any string.
429
430 In a boolean context, the empty string evaluates to false, and
431 non-empty strings evaluate to true.
432
433 =item I<N>
434
435 Any integer.  (Arbitrarily large integers are supported.)
436
437 In a boolean context, 0 evaluates to false, and non-zero evaluates to
438 true.
439
440 =item I<N.>
441
442 =item I<.N>
443
444 =item I<N.N>
445
446 =item I<N.NeN>
447
448 Any floating point number.
449
450 In a boolean context, 0 evaluates to false, and non-zero evaluates to
451 true.
452
453 =back
454
455 =head2 SHELL SCRIPTS
456
457 The code between C<E<lt>E<lt> ... E<gt>E<gt>> is a shell script.  It
458 is executed using C<$SHELL>, or if that environment variable is not
459 set then C</bin/sh>.
460
461 =head3 SHELL SCRIPT VARIABLES
462
463 Every variable that has been set (using the whenjobs I<--set> option)
464 is exported to the script, so you can simply get the value of any
465 variable by writing C<$name>.
466
467 In addition, there are some special variables available:
468
469 =over 4
470
471 =item C<$JOBNAME>
472
473 The name of the job.  If the job has been named explicitly, then that
474 name is available through this variable, else it will be some implicit
475 name like C<job$1>.
476
477 =item C<$JOBSERIAL>
478
479 The serial number of the job.  This is simply a variable that
480 increments each time a job is run, and is unique to that run of the
481 job.
482
483 =back
484
485 Other environment variables such as C<$HOME>, C<$LOGNAME> etc are
486 available as normal.
487
488 =head3 SHELL SCRIPT TEMPORARY CURRENT DIRECTORY
489
490 The shell script runs with its current directory set to a temporary
491 directory.  The temporary directory is removed when the shell script
492 exits.  Therefore you can write temporary files here without worrying
493 about cleaning them up.
494
495 If you want to store permanent state, then you have to save it to a
496 well-known directory, eg. C<$HOME>, C</var> etc.
497
498 =head3 SHELL SCRIPT USER
499
500 The shell script runs as the ordinary user.  It has no special
501 privileges.
502
503 =head2 JOB NAMES
504
505 Jobs are given implicit names (C<job$1>, C<job$2> etc.).  You can also
506 name jobs explicitly by preceeding the "every" or "when" statement
507 with C<job "name">:
508
509  job "poll source"
510  every 10 seconds :
511  <<
512    # ...
513  >>
514
515 The job name is passed to the shell script in the C<$JOBNAME>
516 environment variable.
517
518 =head2 OCAML EXPRESSIONS
519
520 As well as simple "every" and "when" expressions, advanced users may
521 want to use arbitrary OCaml expressions, functions, etc in the jobs
522 script.  These are useful for factoring common code or strings, for
523 setting the initial values of variables, or for defining cleanup
524 functions.
525
526 A simple example of an OCaml expression is:
527
528  let prefix = "daily_"
529  
530  job (prefix ^ "virus_scan")
531  every day :
532  <<
533    # ...
534  >>
535  
536  job (prefix ^ "disk_check")
537  every day :
538  <<
539    # ...
540  >>
541
542 which creates two jobs called C<"daily_virus_scan"> and
543 C<"daily_disk_check"> (C<^> is the OCaml string concatenation
544 operator).
545
546 OCaml expressions have access to a library of functions called
547 B<Whentools> which is described below.  It lets you set variables,
548 create jobs algorithmically, etc.
549
550 The OCaml expressions run once, when the jobs file is being loaded or
551 reloaded.
552
553 =head3 SETTING THE INITIAL VALUE OF VARIABLES
554
555 Variables are created when they are referenced, and until set they
556 have the value empty string (just like the shell).  Across file
557 reloads, the previous values of variables is preserved.
558
559 To initialize a variable to a known value when the jobs file is
560 loaded, call one of the C<Whentools.set_variable*> functions as in
561 this example:
562
563  let () =
564    Whentools.set_variable "name" "Richard";
565    Whentools.set_variable_int "counter" 0
566
567 =head3 CLEANUP FUNCTIONS
568
569 After a job runs, you can control what happens to its output by
570 writing a cleanup function.  To write a cleanup function you have to
571 name the job (ie. have an explicit C<job> statement).  Put C<cleanup ...>
572 after the job name like this:
573
574  job "poll source"
575  cleanup (Whentools.mailto "you@example.com")
576  every 10 seconds :
577  <<
578    # ...
579  >>
580
581 A number of cleanup functions are available in the library; see below.
582
583 You can also write your own cleanup functions (in OCaml).  The
584 function is passed one argument which is a C<Whentools.result> struct,
585 defined below.
586
587 =head3 WHENTOOLS LIBRARY
588
589 =head4 Functions
590
591 =over 4
592
593 =item B<Whentools.mailto> [I<~only_on_failure:true>]
594 [I<~from:from_address>] I<email_address> I<result>
595
596 Send the result of the script by email to the given email address.
597
598 If the optional C<~only_on_failure:true> flag is set, then it is only
599 sent out if the script failed.
600
601 If the optional C<~from> flag is set, then the from address is set
602 accordingly.  This is sometimes needed when sending mail.
603
604 Note the C<result> parameter is passed implicitly by the daemon.  You
605 do not need to add it.
606
607 Here are some examples of using the mailto function:
608
609  job "ex.1"
610  cleanup (Whentools.mailto "you@example.com")
611  every 10 seconds :
612  <<
613    # do something
614  >>
615
616  job "ex.2"
617  cleanup (Whentools.mailto ~only_on_failure:true
618                            "you@example.com")
619  every 10 seconds :
620  <<
621    # do something
622  >>
623
624  let from = "me@example.com"
625  let to_addr = "you@example.com"
626  
627  job "ex.3"
628  cleanup (Whentools.mailto ~from to_addr)
629  every 10 seconds :
630  <<
631    # do something
632  >>
633
634 =item B<Whentools.set_variable> I<name> I<string>
635
636 Set variable I<name> to the string.
637
638 =item B<Whentools.set_variable_bool> I<name> I<b>
639
640 Set variable I<name> to the boolean value I<b>.
641
642 =item B<Whentools.set_variable_int> I<name> I<i>
643
644 Set variable I<name> to the integer value I<i>.
645
646 =item B<Whentools.set_variable_string> I<name> I<s>
647
648 Set variable I<name> to the string value <s>.  This is
649 the same as I<Whentools.set_variable>.
650
651 =item B<Whentools.set_variable_float> I<name> I<f>
652
653 Set variable I<name> to the floating point value I<f>.
654
655 =back
656
657 =head4 Structures
658
659 =over 4
660
661 =item B<Whentools.result>
662
663 This structure is passed to cleanup functions.  It has the following
664 fields:
665
666  type result = {
667    res_job_name : string; # job name
668    res_code : int;        # return code from the shell script
669    res_tmpdir : string;   # temporary directory script ran in
670    res_output : string;   # filename of stdout/stderr output
671  }
672
673 =back
674
675 =head1 FILES
676
677
678
679 =head1 ENVIRONMENT VARIABLES
680
681
682
683 =head1 SEE ALSO
684
685 L<whenjobsd(8)>
686
687 =head1 AUTHOR
688
689 Richard W.M. Jones L<http://people.redhat.com/~rjones/>
690
691 =head1 COPYRIGHT
692
693 Copyright (C) 2012 Red Hat Inc.
694
695 This program is free software; you can redistribute it and/or modify
696 it under the terms of the GNU General Public License as published by
697 the Free Software Foundation; either version 2 of the License, or
698 (at your option) any later version.
699
700 This program is distributed in the hope that it will be useful,
701 but WITHOUT ANY WARRANTY; without even the implied warranty of
702 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
703 GNU General Public License for more details.
704
705 You should have received a copy of the GNU General Public License
706 along with this program; if not, write to the Free Software
707 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.