How do I skip immediate first run of service with systemd timer?

Trying to schedule a oneshot event with systemd timer. But the result is actually twoshot. Starting the timer runs the service, and then elapsing the timer runs the service again.

How would I adjust the following to prevent the initial run, and only fire off the service exactly once, after the timer has elapsed?

~/.config/systemd/user/relax.service

[Unit]
Description=Reminder to relax

[Service]
Type=oneshot
ExecStart=echo Relax

~/.config/systemd/user/relax.timer

[Unit]
Description=Future reminder to relax
Requires=relax.service

[Timer]
Unit=relax.service
OnActiveSec=10s
# Accuracy for fast and predictable debugging
#   First run will be perceptually immediate,
#   and second-run appears to be exactly 10s later.
AccuracySec=1us
RemainAfterElapse=false

[Install]
WantedBy=timers.target

Trial run.

$ journalctl -f | grep Relax &
[1] 66814
$ systemctl --user start relax.timer
Apr 06 13:35:02 device-name echo[66814]: Relax # <-- How to prevent this event?
Apr 06 13:35:12 device-name echo[66817]: Relax

This option means the timer is started with the systemctl start command, 10 seconds later it is started again. So the first run is need to start the 10 seconds for OnActiveSec.

https://www.freedesktop.org/software/systemd/man/systemd.timer.html

Aren’t you just repeating what I already said using different words?



I’m pretty sure I understand the basic behavior of the code I wrote above.

My question is how to convert that code into to a timer that starts a service if-and-only-if the the timer has elapsed?"

I wouldn’t expect it to run until after the timer has elapsed, seems like a bug to me but I’m no expert. :man_shrugging:

This works, you’ll see 2 started messages but only one echo.

systemd-run --user --on-active=10 --timer-property=AccuracySec=1us echo Relax

Thanks for the suggestion. But this is no longer contained inside a unit. Kind of defeats the purpose in choosing systemd for the timer, don’t you think?

Also, from my brief research, stopping/cancelling/removing a transient timer looks to require hacky solutions.

I don’t really know, since I don’t know what your use case is, it works for the test case you’ve shown. I was just pointing it out in the unlikely case it was enough, or maybe helped with troubleshooting.