Calendar Events (systemd.time)
I recently set up some cron jobs on a server with the original intention of using systemd timers. But I gave up and used cron when I realized the tool was fighting against me.
I wanted to trigger 3 different jobs all on the same schedule, but systemd timers can’t natively trigger more than one service.
You also can’t have a timer inside of a service; they have to be separate files. So for my 8 total jobs, I’d need 16 separate files instead of just one crontab.
Just seems like some simple changes could make timers really nice.
Use the timer to trigger a target unit, and attach whatever services you want batched together to that target.
Systemd has an extremely explicit model of one config file per config entity in the data model. Even without using a target to consolidate your setup to one timer, it’s not actually hard. Copy a bare-bones timer and service file 8 times, and edit each service to change the ExecStart line. The unit association between timer and service is implicit if they have the same name, no need to change anything there.
The tool isn’t fighting against you. That’s such a mundane, minor inconvenience to complain about with such a bold condemnation. Especially when comparing with cron, a tool providing almost none of the convenience, observability, and debuggability of systemd units.
for unit in b c d e f g h; do
cp a.timer $unit.timer
cp a.service $unit.service
The tool is fighting him. The explicit timers is not a strong point of systemd, and is, IMO, a pain in the ass.
just have your systemd service launch a script that contains your 8 commands? i don’t see why you’d need to make 8 different service files for what was a single cronjob. should take no more than 2 files.
If they are 8 logically separate jobs, they should run as 8 separate units. For one thing, systemd logs output in the journal by service name, so you can look at the logs for just one job in isolation; or look at the full system log and see which log line came from which logical job.
Same goes for checking job status. If they were all one script, it would be harder to see what parts failed. Separate them, and systemctl status will show you exactly which ones failed.
I wouldn’t go as far as saying it’s fighting against user, but I definitely find it tedious. Usually I just copy some other service, but it’s still more work then single line in Crontab. Yet I still think it’s worthy.
I feel like this is treading very close to implementation-specific behavior. Other cron systems, written in other programming languages, may not implement this exact behavior.
Yes – I wouldn’t be surprised if this was unintended/accidental behaviour that just got documented at some point.
Some cron implementations (not Debian) support 0 0 * * MON#1, which looks much more reasonable.
0 0 * * MON#1
This is exactly what it says in the last paragraph.
Ah man, for me this is right on the line of too much self-promotion and marketing. Still, nice writeup.
Really? We upvote basically everything Fly.io puts out. This seems fine to me.
Different issue (and I wouldn’t mind less free press for Fly, but they do make decent content). In Fly’s case, it’s existing members dragging in Fly articles in addition to their other stuff; in this case, it’s posting own stuff and basically nothing else.
The thing is that OP also posts comments on stories which they’re not the author. So they are involved in the community IMHO, it looks like they’re not here to just post their blog posts and just answer comments about their blog posts.
So I’d give it a pass personally. Is this better? (itamarst = pythonspeed.com) the ratio of self-promotion is lower, but the quantity of self-promotion is much higher, by a lot.
Oh I certainly don’t like that either, don’t get me wrong. To your point, that they are commenting on other things is what makes it a borderline case for me. :)
Dunno, seems fair. I like the writeup but also their product, helps me with monitoring my home setup in such an easy way.
Too magic for me. You can add a date/time/day screen on the shell script behind a cron job in less than ten lines of shell. I’m not happy that you have to look both at the script and the crontab to figure it out but I’m happier with that. Best would probably be something like:
0 0 1-7 * * : 'My First Monday only cronjob' && [ $(date '+%a') -eq 'Mon' ] && run-mycronjob.sh
Assuming I have the fields right.
This solution is locale-dependent, as date '+%a' returns the locale’s abbreviated date.
Then use ‘+%w’ which returns the weekday as a number.
Absolutely true. Also still arguably better than the original solution. The original solution is probably native to the cron package that the author uses. It’s not guaranteed to work anywhere else. Further, like a lot of tools in Unix, cron is terse as a result of its heritage from systems that would today be considered puny. Put a different way, me in 1985 would be astounded at how much computing power I can buy in 2022 in the form of a Raspberry Pi Zero. You should not embrace that terseness. The Systemd/Timer solutions are much better than the cron solutions presented. And I would say that if you are on a box without systemd, you’d still be better off to implement the “only on the first Monday of the month check” in shell rather than through clever manipulation of the cron parameters.
In retrospect, I should have emphasized in the post that the described trick is primarily a trick, a hack, an interesting curiosity.
PS. It’s really hard to buy a Raspberry Pi Zero in 2022, unfortunately. I wanted one for a hobby hardware project, I ended up getting a Radxa Zero. But point stands, the price/performance/size of computers in 2022 is awesome.
Solution is to run muslc which doesn’t do locales
I wanted this trick for my Github CI job that opens a PR every month to update dependencies.