=head1 NAME
slicd-sched - Scheduler, aka the cron daemon
=head1 SYNOPSIS
B<slicd-sched> [B<-R> I<FD>] I<FILE>
=head1 OPTIONS
=over
=item B<-h, --help>
Show help screen and exit.
=item B<-R, --ready-fd> I<FD>
Announce readiness by printing a LF (\n) on I<FD> when ready. This can be used
to signal to your service manager when the daemon is actually ready.
=item B<-V, --version>
Show version information and exit.
=back
=head1 DESCRIPTION
B<slicd-sched>(1) is the actual cron daemon. It must be started with the path to
a file of "compiled" crontabs, previously generated via B<slicd-parser>(1)
It will load the compiled crontabs in memory, calculate the next runtime for
every job, process them as needed and wait until the next time a job needs to
run.
Processing a job simply means that it will print on its stdout a line in the
format I<USERNAME:COMMAND LINE> corresponding to the job to run. Its stdout is
obviously meant to be redirected into B<slicd-exec>(1)'s stdin, which will take
care of forking and executing the command line.
Unlike most cron daemons, B<slicd-sched>(1) doesn't wake up every minute to
check if a job definition matches & must be run; Instead, it calculate the next
runtime for each job, and waits until the closest one.
It does so via a timer set on the real-time system clock, which means any time
changes (manual, NTP, etc) is handled properly.
Specifically, if the time jumps backward, nothing happens (jobs are not re-run),
as B<slicd-sched>(1) still waits for the time previously calculated. If after
setting the time backward you want jobs to be processed, you'll need to have
B<slicd-sched>(1) re-process jobs at the (new) current minute, which can be done
simply by sending it a signal USR1.
If the time jumps forward and the timer has expired, it will process every job
that should run in the current minute, and again set a new timer for the closest
next run. (There's no attempt to run "missed" jobs.)
=head2 Daylight Saving Time
Time changes due to DST are also handled properly, though differently since they
are another beast.
Specifically, when time jumps backward then jobs that run during the "repeated"
interval will indeed run again. For example, if a job runs every hour at minute
30, and the clock jumps from 02:59 (DST activated) to 02:00 (DST deactivated),
then the job will run at 02:30 (DST on), then an hour later at 02:30 (DST off).
When time jumps forward then jobs that would have run during the "missed"
interval will simply not run, since that time didn't happen; there's no attempt
to run "missed" jobs either. For example our job set to run every hour at minute
30, when the clock goes from 01:59 (DST off) to 03:00 (DST on), would simply run
at 01:30 (DST off) then an hour later at 03:30 (DST on).
=head2 Special DST mode
A special DST handling mode can be activated on a per-job basis (see
B<slicd-parser>(1)), in which case time changes due to DST are handled
differently than described above. It can be enabled only on deactivation (time
jumps backward), only on activation (time jumps forward), or both.
When time jumps backward, jobs will only run during the "first pass" - or when
DST was activated. When the time "repeats" but with DST deactivated, they will
not run. So using the same example, our job would run at 02:30 (DST on), and
then only two hours later, at 03:30 (DST off).
When time jumps forward, jobs that would have run at least once during the
"missed" interval will run at the first minute of DST. Again, with our usual
example it would have the job run at 01:30 (DST off), then at 03:00 (DST on) -
because of a "missed run" at the non-existing time of 02:30 - and back as usual
at 03:30 (DST off).
=head1 SIGNALS
The following signals can be used :
=over
=item B<SIGHUP>
Reload compiled crontabs. To avoid re-running jobs, the next jobs to run will
only be calculated started at the next minute.
=item B<SIGUSR1>
Re-process jobs starting at the current minute.
=item B<SIGINT>
=item B<SIGTERM>
Exit.
=back
=head1 NOTES
Since it only prints to its stdout when a job needs to run, B<slicd-sched>(1)
can run as any user, it doesn't require root privileges. Only B<slicd-exec>(1)
does, so the forked children can drop privileges as needed.
=head1 RETURN VALUE
The following return values are possible:
=over
=item B<0> : success
=item B<1> : usage error (unknown option, etc)
=item B<2> : I/O error (permission denied, etc)
=item B<3> : memory error
=item B<4> : no crontabs specified
=item B<5> : other errors (failed to get current time, set timer, etc)
=back
=head1 SEE ALSO
B<slicd-dump>(1), B<slicd-parser>(1), B<slicd-exec>(1)