Have systemd timer *not* run on boot, only on schedule
I'm having an issue where I have a bunch of systemd timers set to run on a schedule to do various backup related tasks. They run successfully at the appointed time. However they also run when the system boots up, which I want to avoid. For example I have a remote rsync that takes a couple of hours to complete, and it needs to only run once at night, not upon reboot.
Here's an example timer:
[Unit]
Description=Run Remote rsync
Requires=remote-backup.service
[Timer]
OnCalendar=*-*-* 4:00:00
RandomizedDelaySec=1h
Persistent=false
[Install]
WantedBy=timers.target
And here's the service it runs:
[Unit]
Description=Remote backup
After=zfs.target network-online.target
OnFailure=status-email-root@%n.service
[Service]
Type=oneshot
ExecStartPre=/path/to/pre-backup script
ExecStart=/path/to/backup-script
ExecStartPost=/path/to/post-backup script
(the pre and post backup scripts ping a health check URL So that I get reports of success/failure/etc.)
The issue is that it's supposed to run only at 4am but if I reboot it will try to run on startup. I've tried changing Persistent
to false with no effect. I'd like to keep it as true, because if the backup truly failed or didn't run, I'd like to rerun it, but not run it every damn time!
I also tried removing the WantedBy
but that just made the thing never run, and I also tried changing the Type
on the service without success.
If anyone has any insight I'd really appreciate it. Thanks!
Solution 1:
In case anyone else has the same issue, /u/stormcloud-9 on reddit was able to help me with this. Turns out I need to remove the "Requires" line in the timer unit. What I hadn't realized was that systemd timers automatically bind to a server with the same filename (like XXX.timer automatically calls XXX.service) unless overridden with a Unit= directive.
Every time the system booted and the timer started, it would uneccessarily start the service because of the Requires= line.
Solution 2:
After chasing my tail with the same problem for half a day I found a simple approach that I detailed in this thread. There are lots of partial solutions offered which may work but didn't for me.
Quick version. Create two simple files in /etc/systemd/system/ with the same base name, here test, but suffixes .service and .timer. Don't add extra requireds and wanted bys.
These are test.service and test.timer.
[Unit]
Description=This is test.service
[Service]
Type=oneshot
ExecStart=/bin/echo "**** I ran at this now ****"
[Unit]
Description=This is test.timer
[Timer]
OnCalendar=*-*-* 10:45:00
[Install]
WantedBy=timers.target
Create the files then run sudo systemctl enable test.timer
and sudo systemctl start test.timer
. Then restart your system.
The status and journalctl commands below can be run for both .timer and .service to confirm that they acted as you expected.
Other useful commands:
systemctl list-unit-files --state=enabled
# whats livesystemctl list-timers
# should now include yourssystemctl status test.timer
# check the timers enabled
systemctl status test.service
# and the service isn'tsudo journalctl -u test.timer
# check the timer ran at startupsudo journalctl -u test.service
# but the service didn't
https://man.archlinux.org/man/systemd.time.7 # time formats