5750646317dc7ea3f8b7e57be19e80b214783386
[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 [variable=value ...]
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 Examine running jobs:
28
29  whenjobs --jobs
30  whenjobs --cancel serial
31  whenjobs --start "name"
32  whenjobs --tail serial
33
34 =head1 DESCRIPTION
35
36 Whenjobs is a powerful but simple replacement for cron.  It lets you
37 run jobs periodically like cron, but it also lets you trigger jobs to
38 run when user-defined variables are set or change value.
39
40 Periodic jobs are written like this:
41
42  every 10 minutes :
43  <<
44    # Get the current load average.
45    load=`awk '{print $1}' /proc/loadavg`
46    whenjobs --set --type float load=$load
47  >>
48
49 When-statements let you create jobs that run based on variables set
50 elsewhere:
51
52  when load >= 6 :
53  <<
54    mail -s "ALERT: high load average: $load" $LOGNAME < /dev/null
55  >>
56
57 (When statements are "edge-triggered", meaning that this job will only
58 run when the load goes from under 6 to E<ge> 6).
59
60 Like L<crontab(5)>, whenjobs are controlled by a jobs file which can
61 be edited from the command line:
62
63  $ whenjobs -e
64
65 Whenjobs uses a daemon called L<whenjobsd(8)>.  Unlike crond, this
66 daemon runs as the same user.  Each user who wants to use whenjobs
67 starts their own daemon:
68
69  $ whenjobs --daemon-start
70
71 You can also have the daemon start as you when the machine boots by
72 adding the following line to a boot file such as C</etc/rc.local>.
73 Replace C<username> with your username:
74
75  su username -c /usr/sbin/whenjobsd
76
77 Variables are the key to expressing dependencies between whenjobs.
78 Variables are stored (per-user) in the daemon.  You can use the
79 command line tool to examine and set variables:
80
81  $ whenjobs --variables
82  load=0.9
83  $ whenjobs --set cat=sushi
84  $ whenjobs --get cat
85  sushi
86
87 The act of setting a variable (using I<--set>) can trigger jobs to run.
88
89 =head1 OPTIONS
90
91 =over 4
92
93 =item B<--cancel> serial
94
95 Cancel the job with the given serial number.
96
97 Use I<--jobs> to list running jobs along with their serial numbers.
98 The serial number is also available in the job script (as
99 C<$JOBSERIAL>) and in the log file.
100
101 =item B<--daemon-start>
102
103 =item B<--daemon-stop>
104
105 Start and stop the per-user daemon.
106
107 =item B<--daemon-status>
108
109 Prints the status of the daemon: C<up> or C<down>.
110
111 =item B<--daemon-restart>
112
113 Restart the daemon.  (If it is not running, then this command
114 starts it).
115
116 =item B<-e>
117
118 =item B<--edit>
119
120 Edit the jobs script.  If you make changes to the jobs script, then it
121 is automatically uploaded to the daemon.
122
123 The C<$EDITOR> environment variable is used for editing.  If not set,
124 C<vi> is used.
125
126 =item B<--get> variable
127
128 Print the value of a variable.
129
130 =item B<--jobs>
131
132 List all running jobs.
133
134 Note that it is possible for the same job to be running more than once
135 (for example, a periodic job that takes longer than the period to run).
136
137 =item B<-l>
138
139 =item B<--list>
140
141 List the jobs script.
142
143 =item B<--lib> directory
144
145 Set the library directory which needs to contain the auxiliary files
146 C<pa_when.cmo> and C<whenlib.cma>.  Normally you do not need to
147 specify this.  However if you are running whenjobs without installing
148 it, then you need to point this to the C<lib/> directory from the
149 source, eg:
150
151  whenjobs --lib $builddir/lib -e
152
153 =item B<--set> variable=value [variable=value ...]
154
155 =item B<--type> bool|int|float|string|unit
156
157 I<--set> sets the variable named C<variable> to the new C<value>.  The
158 variable is created if it does not already exist.  Note that setting a
159 variable can cause jobs to run immediately.
160
161 To unset a variable, set it to the empty string like this:
162
163  whenjobs --set var=
164
165 By default variables are strings.  You can also set the type of a
166 variable when setting it by adding the optional I<--type> parameter.
167 The I<--type> parameter should come I<before> the variable
168 declaration, like this:
169
170  whenjobs --set --type int free_space=10000
171
172 See the discussion of variable types in the L</REFERENCE> section
173 below.
174
175 You can set multiple variables.  When setting multiple variables in a
176 single command, the values are all changed in a single atomic
177 operation.
178
179  whenjobs --set cat=sushi food=fish
180
181 When using I<--type> and multiple variables, the type changes the
182 remaining command line parameters until the next I<--type>, eg:
183
184  whenjobs --set cat=sushi --type float weight=3.5 --type string food=fish
185
186 (C<cat> and C<food> are strings, and C<weight> is a float).
187
188 =item B<--start> "job name"
189
190 Start the job immediately and unconditionally.
191
192 This runs the job even if its normal preconditions are not met.  This
193 may cause unexpected results, so use with caution.
194
195 =item B<--tail> serial
196
197 Tail the output of the running job identified by its serial number.
198 Use the I<--jobs> flag to get a list of running jobs.
199
200 =item B<--upload>
201
202 Compile the jobs script and upload it to the daemon, without editing.
203 Note that the I<--edit> option does this automatically.  Furthermore,
204 when the daemon is started it checks for a jobs script and loads it if
205 found.
206
207 =item B<--variables>
208
209 Display all the variables and their values, in the format C<name=value>.
210
211 =item B<-V>
212
213 =item B<--version>
214
215 Display the name and version of the program and exit.
216
217 =item B<-help>
218
219 =item B<--help>
220
221 Display brief usage and exit.
222
223 =back
224
225 =head1 REFERENCE
226
227 A whenjobs file consists of a series of one or more "every" or "when"
228 statements.
229
230 Comments in the file can be written using C<(* ... *)>.  Comments
231 may be nested.
232
233 Shell script fragments are written using C<E<lt>E<lt> ... E<gt>E<gt>>.
234 Within shell script fragments, use C<#> for comments (as in ordinary
235 shell scripts).  Because C<E<gt>E<gt>> has a special meaning, it
236 cannot be used in the shell script (ie. for redirection).  You have to
237 write C<E<gt>\E<gt>> instead which is replaced with C<E<gt>E<gt>> when
238 the shell script is parsed.
239
240 =head2 EVERY STATEMENTS (PERIODIC JOBS)
241
242 An every statement has the form:
243
244  every <period> :
245  <<
246    # shell script
247  >>
248
249 where C<E<lt>periodE<gt>> is a I<period expression>, which may take
250 one of the forms below.  Don't forget the colon character between the
251 period expression and the shell script.
252
253 An every statement is a job which runs periodically.
254
255 =head3 PERIOD EXPRESSIONS
256
257 =over 4
258
259 =item B<every second>
260
261 The job runs every second.
262
263 =item B<every minute>
264
265 The job runs every minute.
266
267 =item B<every hour>
268
269 The job runs every hour.
270
271 =item B<every day>
272
273 The job runs every day, at midnight UTC.
274
275 =item B<every week>
276
277 The job runs every week, on a Thursday at midnight UTC.
278
279 =item B<every month>
280
281 The job runs every month, on the first of the month at midnight UTC.
282
283 =item B<every year>
284
285 The job runs every year, on the first day of the year at midnight UTC.
286
287 =item B<every decade>
288
289 =item B<every century>
290
291 =item B<every millenium>
292
293 The job runs every 10, 100 or 1000 years.
294
295 =item B<every I<N> seconds>
296
297 The job runs every I<N> seconds (I<N> is any number E<ge> 1).
298
299 =item B<every I<N> minutes>
300
301 The job runs every I<N> minutes.
302
303 =item B<every I<N> hours>
304
305 The job runs every I<N> hours.
306
307 =item B<every I<N> days>
308
309 The job runs every I<N> days.
310
311 =item B<every I<N> weeks>
312
313 The job runs every I<N> weeks.
314
315 =item B<every I<N> months>
316
317 The job runs every I<N> months.
318
319 =item B<every I<N> years>
320
321 =item B<every I<N> decades>
322
323 =item B<every I<N> centuries>
324
325 =item B<every I<N> millenia>
326
327 The job runs every I<N>, I<10*N>, I<100*N> or I<1000*N> years.
328
329 =back
330
331 =head2 WHEN STATEMENTS (DEPENDENT JOBS)
332
333 A when statement has the form:
334
335  when <expr> :
336  <<
337    # shell script
338  >>
339
340 where C<E<lt>exprE<gt>> is a I<when expression>, described below.
341 Don't forget the colon character between the period expression and the
342 shell script.
343
344 A when statement is a job which runs when the conditions described in
345 its when-expression become true.
346
347 When jobs are I<edge triggered>.  This means that they run when the
348 condition changes from false to true (or in the case where the
349 expression has not been evaluated before, when it evaluates initially
350 to true).
351
352 =head3 WHEN EXPRESSIONS
353
354 When expressions are fully recursive expressions constructed from the
355 following elements:
356
357 =over 4
358
359 =item I<expr> B<&&> I<expr>
360
361 =item I<expr> B<||> I<expr>
362
363 The boolean "and" or "or" of the two sub-expressions.
364
365 =item I<expr> B<E<lt>> I<expr>
366
367 =item I<expr> B<E<lt>=> I<expr>
368
369 =item I<expr> B<==> I<expr>
370
371 =item I<expr> B<E<gt>=> I<expr>
372
373 =item I<expr> B<E<gt>> I<expr>
374
375 The two sub-expressions are evaluated and the usual comparison
376 operator is performed.
377
378 If the sub-expressions are numeric, then numeric comparison is done.
379 If either sub-expression is non-numeric, then both expressions are
380 converted (if necessary) to strings and string comparison is done.
381
382 =item B<!> I<expr>
383
384 Boolean negative of I<expr>.
385
386 =item I<expr> B<+> I<expr>
387
388 For numeric sub-expressions, this performs addition.
389
390 If both sub-expressions are strings, this performs string
391 concatenation.
392
393 Other types give an error.
394
395 =item I<expr> B<-> I<expr>
396
397 =item I<expr> B<*> I<expr>
398
399 =item I<expr> B</> I<expr>
400
401 =item I<expr> B<mod> I<expr>
402
403 Both sub-expressions are evaluated, and if both are numeric, then the
404 result is subtraction, multiplication, division or modulo.
405
406 Other types give an error.  Note that I<mod> really is an infix
407 operator.
408
409 =item B<len> I<expr>
410
411 If I<expr> is a string, this returns the length of the string.
412
413 =item I<variable>
414
415 The value of the named variable.
416
417 Previously undefined variables are automatically initialized to the
418 empty string.
419
420 =item B<prev> I<variable>
421
422 The I<previous> value of the named variable.  This means, the value
423 that it had last time this when-job ran.
424
425 If the when-job has not run yet, then this returns C<"">.
426
427 Job state is preserved across file reloads, but I<only> for jobs that
428 are explicitly named.  If you find that jobs using C<prev>, C<changes>
429 etc are running unnecessarily when the jobs file is edited or
430 uploaded, try giving the jobs an explicit name.
431
432 =item B<changes> I<variable>
433
434 If the named variable has changed since this job last ran, then this
435 evaluates to true, else false.
436
437 This is the same as writing C<prev variable == variable>.
438
439 =item B<increases> I<variable>
440
441 If the named variable has changed and increased since this job last
442 ran, then this evaluates to true, else false.
443
444 This is the same as writing C<prev variable E<lt> variable>.
445
446 =item B<decreases> I<variable>
447
448 If the named variable has changed and decreased since this job last
449 ran, then this evaluates to true, else false.
450
451 This is the same as writing C<prev variable E<gt> variable>.
452
453 B<Note:> There is a subtle gotcha with the I<decreases> operator: The
454 first time the expression is evaluated, the job has (by definition)
455 not yet run.  Therefore C<prev variable> evaluates to C<""> (see
456 definition of I<prev> above).  Since it is always true that
457
458  "" < anything
459
460 the I<decreases> operator evaluates to false, and since this usually
461 means the job does not run, the operator always evaluates to false.
462
463 To fix this, ensure that the variable is initialized (see
464 L</SETTING THE INITIAL VALUE OF VARIABLES> below).
465
466 =item B<reloaded ()>
467
468 This evaluates to true the first time the expression is evaluated
469 after the jobs file has been reloaded or the daemon restarted.
470 Thereafter it evaluates to false.
471
472 Don't use this to initialize variables: it won't do what you mean.
473
474 =item B<false>
475
476 =item B<true>
477
478 Constants that evaluate to boolean false or true respectively.
479
480 =item I<"any string">
481
482 Any string.
483
484 In a boolean context, the empty string evaluates to false, and
485 non-empty strings evaluate to true.
486
487 =item I<N>
488
489 Any integer.  (Arbitrarily large integers are supported.)
490
491 In a boolean context, 0 evaluates to false, and non-zero evaluates to
492 true.
493
494 =item I<N.>
495
496 =item I<.N>
497
498 =item I<N.N>
499
500 =item I<N.NeN>
501
502 Any floating point number.
503
504 In a boolean context, 0 evaluates to false, and non-zero evaluates to
505 true.
506
507 =back
508
509 =head2 SHELL SCRIPTS
510
511 The code between C<E<lt>E<lt> ... E<gt>E<gt>> is a shell script.  It
512 is executed using C<$SHELL>, or if that environment variable is not
513 set then C</bin/sh>.
514
515 =head3 SHELL SCRIPT VARIABLES
516
517 Every variable that has been set (using the whenjobs I<--set> option)
518 is exported to the script, so you can simply get the value of any
519 variable by writing C<$name>.
520
521 In addition, there are some special variables available:
522
523 =over 4
524
525 =item C<$JOBNAME>
526
527 The name of the job.  If the job has been named explicitly, then that
528 name is available through this variable, else it will be some implicit
529 name like C<job$1>.
530
531 =item C<$JOBSERIAL>
532
533 The serial number of the job.  This is simply a variable that
534 increments each time a job is run, and is unique to that run of the
535 job.
536
537 =back
538
539 Other environment variables such as C<$HOME>, C<$LOGNAME> etc are
540 available as normal.
541
542 =head3 SHELL SCRIPT TEMPORARY CURRENT DIRECTORY
543
544 The shell script runs with its current directory set to a temporary
545 directory.  The temporary directory is removed when the shell script
546 exits.  Therefore you can write temporary files here without worrying
547 about cleaning them up.
548
549 If you want to store permanent state, then you have to save it to a
550 well-known directory, eg. C<$HOME>, C</var> etc.
551
552 =head3 SHELL SCRIPT USER
553
554 The shell script runs as the ordinary user.  It has no special
555 privileges.
556
557 =head2 JOB NAMES
558
559 Jobs are given implicit names (C<job$1>, C<job$2> etc.).  You can also
560 name jobs explicitly by preceeding the "every" or "when" statement
561 with C<job "name">:
562
563  job "poll source"
564  every 10 seconds :
565  <<
566    # ...
567  >>
568
569 The job name is passed to the shell script in the C<$JOBNAME>
570 environment variable.
571
572 =head2 OCAML EXPRESSIONS
573
574 As well as simple "every" and "when" expressions, advanced users may
575 want to use arbitrary OCaml expressions, functions, etc in the jobs
576 script.  These are useful for factoring common code or strings, for
577 setting the initial values of variables, or for defining pre and post
578 functions.
579
580 A simple example of an OCaml expression is:
581
582  let prefix = "daily_"
583  
584  job (prefix ^ "virus_scan")
585  every day :
586  <<
587    # ...
588  >>
589  
590  job (prefix ^ "disk_check")
591  every day :
592  <<
593    # ...
594  >>
595
596 which creates two jobs called C<"daily_virus_scan"> and
597 C<"daily_disk_check"> (C<^> is the OCaml string concatenation
598 operator).
599
600 OCaml expressions have access to a library of functions called
601 B<Whentools> which is described below.  It lets you set variables,
602 create jobs algorithmically, etc.
603
604 The OCaml expressions run once, when the jobs file is being loaded or
605 reloaded.
606
607 =head3 SETTING THE INITIAL VALUE OF VARIABLES
608
609 Variables are created when they are referenced, and until set they
610 have the value empty string (just like the shell).  Across file
611 reloads, the previous values of variables are preserved.
612
613 To initialize a variable to a known value when the jobs file is
614 loaded, call one of the C<Whentools.set_variable*> functions as in
615 this example:
616
617  let () =
618    Whentools.set_variable "name" "Richard";
619    Whentools.set_variable_int "counter" 0
620
621 =head3 PRE FUNCTIONS
622
623 Before a job runs, you can arrange that a C<pre> function is called.
624 This function may decide not to run the job (by returning C<false>).
625
626 One use for this is to prevent a particular job from running if there
627 is already an instance of the same job running:
628
629  job "only one"
630  pre (Whentools.one ())
631  every 10 seconds :
632  <<
633    # Takes longer than 10 seconds to run, but 'Whentools.one ()'
634    # will ensure only one is ever running.
635    sleep 11
636  >>
637
638 When using pre functions, jobs must be given an explicit name, ie.
639 you must use the C<job> statement.
640
641 A number of pre functions are available in the library; see below.
642
643 You can also write your own post functions (in OCaml).  The function
644 is passed one argument which is a C<Whentools.preinfo> struct, defined
645 below.  It should return a boolean: C<true> if the job should run, and
646 C<false> if the job should not run.
647
648 Note that a fresh serial number (see L</JOBSERIAL>) is assigned to
649 each run, whether or not the job actually runs because of
650 preconditions.
651
652 =head3 POST FUNCTIONS
653
654 After a job runs, you can control what happens to its output by
655 writing a C<post> function.  To write a post function you have to
656 name the job (ie. have an explicit C<job> statement).  Put C<post ...>
657 after the job name like this:
658
659  job "poll source"
660  post (Whentools.mailto "you@example.com")
661  every 10 seconds :
662  <<
663    # ...
664  >>
665
666 A number of post functions are available in the library; see below.
667
668 You can also write your own post functions (in OCaml).  The
669 function is passed one argument which is a C<Whentools.result> struct,
670 defined below.
671
672 =head3 WHENTOOLS LIBRARY
673
674 =head4 Functions
675
676 =over 4
677
678 =item B<Whentools.mailto> [I<~only_on_failure:true>]
679 [I<~from:from_address>] I<email_address> I<result>
680
681 This built-in post function sends the result of the script by email to
682 the given email address.
683
684 If the optional C<~only_on_failure:true> flag is set, then it is only
685 sent out if the script failed.
686
687 If the optional C<~from> flag is set, then the from address is set
688 accordingly.  This is sometimes needed when sending mail.
689
690 Note the C<result> parameter is passed implicitly by the daemon.  You
691 do not need to add it.
692
693 Here are some examples of using the mailto function:
694
695  job "ex.1"
696  post (Whentools.mailto "you@example.com")
697  every 10 seconds :
698  <<
699    # do something
700  >>
701
702  job "ex.2"
703  post (Whentools.mailto ~only_on_failure:true
704                         "you@example.com")
705  every 10 seconds :
706  <<
707    # do something
708  >>
709
710  let from = "me@example.com"
711  let to_addr = "you@example.com"
712  
713  job "ex.3"
714  post (Whentools.mailto ~from to_addr)
715  every 10 seconds :
716  <<
717    # do something
718  >>
719
720 =item B<Whentools.max> I<n>
721
722 This built-in pre function ensures that a maximum of I<n> instances of
723 the job are running.
724
725 It checks the list of running jobs, and if I<n> or more instances are
726 already running, then it returns C<false>, which ensures that the new
727 job is not started.
728
729 =item B<Whentools.one> I<()>
730
731 This built-in pre function ensures that only one instance of the job
732 is running.  It is the same as calling:
733
734  Whentools.max 1
735
736 =item B<Whentools.set_variable> I<name> I<string>
737
738 Set variable I<name> to the string.
739
740 =item B<Whentools.set_variable_bool> I<name> I<b>
741
742 Set variable I<name> to the boolean value I<b>.
743
744 =item B<Whentools.set_variable_int> I<name> I<i>
745
746 Set variable I<name> to the integer value I<i>.
747
748 =item B<Whentools.set_variable_string> I<name> I<s>
749
750 Set variable I<name> to the string value <s>.  This is
751 the same as I<Whentools.set_variable>.
752
753 =item B<Whentools.set_variable_float> I<name> I<f>
754
755 Set variable I<name> to the floating point value I<f>.
756
757 =back
758
759 =head4 Structures
760
761 =over 4
762
763 =item B<Whentools.preinfo>
764
765 This structure is passed to pre functions.  It has the following
766 fields:
767
768  type preinfo = {
769    pi_job_name : string;           # Job name.
770    pi_serial : Big_int.big_int;    # Job serial number.
771    pi_variables : (string * variable) list; # Variables set in job.
772    pi_running : preinfo_running_job list;   # List of running jobs.
773  }
774  and preinfo_running_job = {
775    pirun_job_name : string;        # Running job name.
776    pirun_serial : Big_int.big_int; # Running job serial number.
777    pirun_start_time : float;       # Running job start time.
778    pirun_pid : int;                # Running job process ID.
779  }
780
781 =item B<Whentools.result>
782
783 This structure is passed to post functions.  It has the following
784 fields:
785
786  type result = {
787    res_job_name : string;  # job name
788    res_serial : big_int;   # job serial (same as $JOBSERIAL)
789    res_code : int;         # return code from the shell script
790    res_tmpdir : string;    # temporary directory script ran in
791    res_output : string;    # filename of stdout/stderr output
792    res_start_time : float; # when the job started
793  }
794
795 =back
796
797 =head1 FILES
798
799
800
801 =head1 ENVIRONMENT VARIABLES
802
803
804
805 =head1 SEE ALSO
806
807 L<whenjobsd(8)>
808
809 =head1 AUTHOR
810
811 Richard W.M. Jones L<http://people.redhat.com/~rjones/>
812
813 =head1 COPYRIGHT
814
815 Copyright (C) 2012 Red Hat Inc.
816
817 This program is free software; you can redistribute it and/or modify
818 it under the terms of the GNU General Public License as published by
819 the Free Software Foundation; either version 2 of the License, or
820 (at your option) any later version.
821
822 This program is distributed in the hope that it will be useful,
823 but WITHOUT ANY WARRANTY; without even the implied warranty of
824 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
825 GNU General Public License for more details.
826
827 You should have received a copy of the GNU General Public License
828 along with this program; if not, write to the Free Software
829 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.