Re: Q: systemd-timer vs cron
On Sat, 12 Mar 2022 at 14:40:32 -0500, Michael Stone wrote:
> On Sat, Mar 12, 2022 at 03:19:52PM +0800, Paul Wise wrote:
> > Do what apt does; make the cron job exit successfully without doing
> > anything when run on systemd, move most of what is being run into a
> > script or program in /usr, then call that from the timer and cron job.
> > Alternatively, make the cron job exit successfully without doing
> > anything when run on systemd, then have the timer call the cron job
> > with a --run-on-systemd argument that makes it run under systemd.
> These are still somewhat annoying in practice because of the log entries for
> CRON running something pointlessly.
systemd-cron gets round this by assuming that /etc/cron.d/foobar
is redundant with a native systemd timer foobar.timer, so if
foobar.timer exists (or is explicitly masked), systemd-cron will not run
/etc/cron.d/foobar. I don't think this naming convention is formally
guaranteed by Policy, but it seems to work well enough in practice.
systemd-cron is a third-party implementation of the cron-daemon interface
as a systemd generator, which outputs pairs of systemd .timer and
.service units corresponding to cron jobs. It is not part of systemd,
and is an alternative to running a more traditional cron-daemon (Vixie
cron or equivalent) as a long-running systemd service.
This mechanism currently only works for cron.d, and not for the grouped
hourly/daily/weekly/monthly sets of cron jobs, which always get run
by run-parts (unless the corresponding directory is completely empty,
in which case the appropriate hourly/daily/weekly/monthly timer is
automatically disabled by a ConditionDirectoryNotEmpty rule).
If there was a way to flag system cron jobs with metadata that says
"this is redundant when running under systemd", then that would remove
this redundancy for the more traditional cron-daemon setup too. That
would be a feature request for traditional cron implementations (and
systemd-cron) rather than a feature request for systemd.
Some backwards-compatible ways that I can think of to represent that
flag in crontab(5) syntax are:
- reserving an environment variable like SKIP_CRON_JOB_UNDER_SYSTEMD=1
to act as a request to skip parsing this cron job on systemd systems
(it would also be set like any other environment variable when the cron
job is executed on a non-systemd system, but that should generally be
harmless, because programs are generally expected to ignore unknown
- a magic comment, analogous to LSB "### BEGIN INIT INFO" comments
(the major disadvantage of this approach is that it requires parsing
comments, which always seems like a "code smell" to me)
- having a single conventional way to spell not-systemd guard, parsing
the shell command to see whether it includes the guard, and skipping
commands that do
(I don't like this aesthetically, because I feel as though the shell
command should be treated as opaque, and more practically I suspect
there are lots of variations of how to spell the guard: && vs. if/fi,
[ -d ] vs. test -d, and so on)
I personally think I've written those in preference order (best one first),
but it's up to the cron implementors' tastes rather than mine.