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