[bug#77041,v2,16/16] doc: Document Shepherd timers and recommend against mcron.

Message ID 521517bc62856586343fd55dad508a32cc3a29d1.1742642743.git.ludo@gnu.org
State New
Headers
Series Replacing mcron jobs by Shepherd timers |

Commit Message

Ludovic Courtès March 22, 2025, 11:36 a.m. UTC
  * doc/guix.texi (Scheduled Job Execution): Add intro.  Add “Shepherd
Timers” subsection; move previous documentation to “Mcron” subsection.
Recommend use of Shepherd timers.
(Mcron Home Service): Recommend Shepherd timers.
(Shepherd Home Service): Document timers.

Change-Id: I9dba68a0d062f5aeeae29ff725e1161f2bd3b291
---
 doc/guix.texi | 168 +++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 159 insertions(+), 9 deletions(-)
  

Patch

diff --git a/doc/guix.texi b/doc/guix.texi
index 12eef9aa40..4592523f81 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -20849,14 +20849,123 @@  Scheduled Job Execution
 @subsection Scheduled Job Execution
 
 @cindex cron
-@cindex mcron
 @cindex scheduling jobs
-The @code{(gnu services mcron)} module provides an interface to
+It is often useful to have system tasks run periodically.  This can be
+achieved by defining Shepherd @dfn{timers} or by using the historical
+and somewhat less flexible mcron service.
+
+@subsubsection Shepherd Timers
+
+@cindex timers, Shepherd
+@cindex Shepherd timers
+The Shepherd supports running jobs periodically by defining
+@dfn{timers}, a special kind of service.  A Shepherd timer can be
+defined like another Shepherd service, but with specific @code{start}
+and @code{stop} methods (@pxref{Shepherd Services}):
+
+@lisp
+;; Defining a timer, verbosely.
+(shepherd-service
+ (provision '(updatedb))
+ (requirement '(user-processes))
+ (modules '((shepherd service timer)))
+ (start #~(make-timer-constructor
+           ;; Everyday at 3AM (using Vixie cron syntax).
+           (cron-string->calendar-event "0 3 * * *")
+           (command '(#$(file-append findutils "/bin/updatedb")))
+           #:wait-for-termination? #t))
+ (stop #~(make-timer-destructor))
+ (documentation "Periodically run 'updatedb'.")
+ (actions (list shepherd-trigger-action)))
+@end lisp
+
+This is quite some boilerplate so you can instead use this equivalent
+shorthand notation:
+
+@lisp
+;; Equivalent timer definition, but shorter.
+(shepherd-timer '(updatedb) "0 3 * * *"
+                #~(#$(file-append findutils "/bin/updatedb"))
+                #:requirement '(user-processes))
+@end lisp
+
+This procedure is defined as follows.
+
+@anchor{shepherd-timer-procedure}
+@deffn {Procedure} shepherd-timer @var{provision} @var{schedule} @
+         @var{command} [#:requirement '()] @
+         [#:documentation %default-timer-documentation]
+Return a Shepherd service with the given @var{provision} periodically
+running @var{command}, a list-valued gexp, according to @var{schedule},
+a string in Vixie cron syntax or a gexp providing a Shepherd calendar
+event.  @var{documentation} is the string that appears when running
+@code{herd doc @var{service}}.
+@end deffn
+
+The example below shows how to define a timer and to add it to your
+operating system configuration.
+
+@lisp
+(use-modules (gnu))
+(use-service-modules shepherd)
+(use-package-modules base)
+
+(define updatedb-timer
+  ;; Run 'updatedb' at 3AM everyday.
+  (shepherd-timer '(updatedb)
+                  "0 3 * * *"  ;Vixie cron syntax
+                  #~(#$(file-append findutils "/bin/updatedb")
+                     "--prunepaths=/tmp /var/tmp /gnu/store")
+                  #:requirement '(user-processes)))
+
+(define garbage-collection-timer
+  ;; Run 'guix gc' everyday at 5AM.
+  (shepherd-timer '(garbage-collection)
+                  #~(calendar-event #:hours '(5) #:minutes '(0))
+                  #~("/run/current-system/profile/bin/guix"
+                     "gc" "-F" "10G")
+                  #:requirement '(guix-daemon)))
+
+(operating-system
+  ;; @dots{}
+
+  ;; Extend the Shepherd service with additional timers
+  ;; using 'simple-service'.
+  (services (cons (simple-service 'my-timers
+                                   shepherd-root-service-type
+                                   (list garbage-collection-timer
+                                         updatedb-timer))
+                  %base-services)))
+@end lisp
+
+The resulting system contains these two services, which can be inspected
+with @command{herd status}.  They can also be triggered manually:
+
+@example
+herd trigger garbage-collection
+@end example
+
+@ref{Timers,,, shepherd, The GNU Shepherd Manual} for more information
+on Shepherd timers.
+
+@anchor{mcron-service}
+@subsubsection Mcron
+
+@cindex mcron
+Alternatively,
+the @code{(gnu services mcron)} module provides an interface to
 GNU@tie{}mcron, a daemon to run jobs at scheduled times (@pxref{Top,,,
 mcron, GNU@tie{}mcron}).  GNU@tie{}mcron is similar to the traditional
 Unix @command{cron} daemon; the main difference is that it is
-implemented in Guile Scheme, which provides a lot of flexibility when
-specifying the scheduling of jobs and their actions.
+implemented in Guile Scheme.  It is overall less convenient than
+Shepherd timers: individual jobs cannot depend on specific Shepherd
+services, logging is coarse-grain (one file for all the jobs), jobs may
+not be inspected, updated, or triggered manually.
+
+@quotation Note
+For the reasons given above, we recommend using Shepherd timers rather
+than mcron for your periodic tasks.
+@end quotation
 
 The example below defines an operating system that runs the
 @command{updatedb} (@pxref{Invoking updatedb,,, find, Finding Files})
@@ -48610,18 +48719,23 @@  Shells Home Services
 @node Mcron Home Service
 @subsection Scheduled User's Job Execution
 
-@cindex cron
-@cindex mcron
-@cindex scheduling jobs
-
+@cindex cron, per-user
+@cindex mcron, per-user
+@cindex scheduling jobs per-user
 The @code{(gnu home services mcron)} module provides an interface to
 GNU@tie{}mcron, a daemon to run jobs at scheduled times (@pxref{Top,,,
 mcron, GNU@tie{}mcron}).  The information about system's mcron is
-applicable here (@pxref{Scheduled Job Execution}), the only difference
+applicable here (@pxref{mcron-service, mcron reference}), the only difference
 for home services is that they have to be declared in a
 @code{home-environment} record instead of an @code{operating-system}
 record.
 
+@quotation Note
+We recommend defining periodic tasks as Shepherd timers, which provide
+more flexibility than mcron.  @xref{Shepherd Home Service}, for more
+info.
+@end quotation
+
 @defvar home-mcron-service-type
 This is the type of the @code{mcron} home service, whose value is a
 @code{home-mcron-configuration} object.  It allows to manage scheduled
@@ -48784,6 +48898,42 @@  Shepherd Home Service
 @end table
 @end deftp
 
+@cindex timers, per-user
+The Shepherd allows you to define @dfn{timers}, a special type of
+service that performs a given task periodically.  Just like you can
+define timers at the system level (@pxref{Scheduled Job Execution}), you
+can do so in your home environment.
+
+The example below defines a home environment where a Shepherd timer runs
+the @command{mkid} command twice per day (@pxref{mkid invocation,,,
+idutils, ID Database Utilities}).  It does so by extending
+@code{home-shepherd-service-type} with @code{simple-service}; the
+Shepherd timer itself is produced by the @code{shepherd-timer} procedure
+(@pxref{shepherd-timer-procedure, @code{shepherd-timer}}), which is
+given the service name, a gexp specifying its schedule, and a gexp
+specifying the command to run.
+
+@lisp
+(use-modules (gnu) (guix)
+             (gnu home services shepherd)
+             (gnu packages idutils))
+
+(define idutils-service
+  ;; Index my 'doc' directory everyday at 12:15PM and 7:15PM.
+  (simple-service
+   'update-idutils-database home-shepherd-service-type
+   (list (shepherd-timer '(update-idutils-database)
+                         #~(calendar-event #:hours '(12 19)
+                                           #:minutes '(15))
+                         #~(#$(file-append idutils "/bin/mkid")
+                            "doc")))))
+
+(home-environment
+  ;; @dots{}
+  (services (append (list idutils-service)
+                    %base-home-services)))
+@end lisp
+
 @cindex log rotation, for user services
 The Shepherd also comes with a @dfn{log rotation service}, which
 compresses and then deletes old log files produced by services and