How to make a systemd service that is triggered by an associated timer, also execute after system reboot?
I have a working systemd service associated with a timer through both sharing the same file name stem -- the service unit file name ends with .service
and the associated timer unit file name ends wit .timer
. The timer is legitimately designed to start the service some time (60 seconds) after the service last became inactive. This is indicated in the timer file:
[Timer]
OnUnitInactiveSec=60
[Install]
WantedBy=multi-user.target
The service is triggered as expected and everything works except one "little" problem -- the timer only specifies the service should be started 60 seconds after it last became inactive (presumably after completion), which does not imply any triggering on conditions like newly [re]started system.
I want also the service to run initially when the system is restarted, which may happen from time to time due to some administrative updates or what not our organization is doing, affecting continuous system uptime.
Is it possible to make the service run once on system boot? I am sure after the initial execution, the timer should work as expected since it will trigger execution again 60 seconds after that first execution, and so on.
My service unit file is as follows (I redacted the more sensitive values of Description
and Service
, replacing them with "placeholders"):
[Unit]
Description=Foobar service
[Service]
ExecStart=/path/to/foobar
What can I do to supplement the triggering of the service with the extra condition that I want -- to run once on boot, so that I don't have to attend to the system every time it is rebooted?
The service is by design timer-invoked -- hence no Install
sections etc. It's essentially a program processing a set of files that match a predicate. Not sure if not having an Install
section is a problem or not, but I guess not having one should go well with it being timer-triggered and the script being "single sweep", essentially.
Solution 1:
The service is by design timer-invoked -- hence no
Install
sections etc.
But now you want it to be timer-invoked and started on boot, so the original design no longer applies. Therefore, add an [Install]
section to the service and systemctl enable
it so that it runs through multi-user.target (in addition to still being timer-invoked).
(You can also directly add the dependency symlink to multi-user.target.wants/ without using this section or systemctl, but that makes it a bit easier for the links to accidentally get removed.)
Alternatively, extend the timer to have OnBootSec=1s
(or something similar) in addition to what it currently has. Multiple "On" settings are allowed in a single timer, and the service will be invoked whenever any of those timeouts elapses.
(There are three different "on startup"-like options; they should all work, thanks to service dependencies, but overall OnBootSec= is probably the most appropriate one.)
Alternatively, create a second, separate timer which triggers the same service via OnBootSec=. Timer units can be differently named, as long as they use Unit=
to specify what to invoke.
Any of the 3 options should work equally well. It doesn't matter to timers whether the unit is also installed as a dependency of some target or not.