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 live
systemctl list-timers # should now include yours
systemctl status test.timer # check the timers enabled systemctl status test.service # and the service isn't
sudo journalctl -u test.timer # check the timer ran at startup
sudo journalctl -u test.service # but the service didn't

https://man.archlinux.org/man/systemd.time.7 # time formats