How do you make a systemd service as the last service on boot?
Solution 1:
In systemd it is advised to use Before=
and After=
to order your services nicely around the other ones.
But since you asked for a way without using Before
and After
, you can use:
Type=idle
which as man systemd.service
explains:
Behavior of
idle
is very similar tosimple
; however, actual execution of the service program is delayed until all active jobs are dispatched. This may be used to avoid interleaving of output of shell services with the status output on the console. Note that this type is useful only to improve console output, it is not useful as a general unit ordering tool, and the effect of this service type is subject to a 5s timeout, after which the service program is invoked anyway.
Solution 2:
It really depends on your definition of "booted". I assume you want it to run immediately after the getty starts. To do this, you need to add your service to /etc/systemd/system/getty.target.wants/
directory. You should also ensure your file is using similar code to the other services in this directory. To run a custom service on bootup and shutdown (just beeps my motherboard buzzer) I use the following script in /etc/systemd/system/getty.target.wants/service_name.service
[Unit]
After=systemd-user-sessions.service plymouth-quit-wait.service
After=rc-local.service
Before=getty.target
IgnoreOnIsolate=yes
[Service]
ExecStart=/usr/bin/myinitscript.sh start
ExecStop=/usr/bin/myinitscript.sh stop
Type=oneshot
RemainAfterExit=true
[Install]
WantedBy=basic.target
/usr/bin/myinitscript.sh
is executable and has a shebang at the start.
Note that not everything will be started at this point in the boot, but this is the point at which the logon prompt appears to the user
Although this does use Before=
and After=
, it was for me much more understandable and actually works; I didn't find the above answer informative enough. This is also allows you to use both ExecStart=
and ExecStop=
, rather than being limited to a Type=simple
-like service.
Solution 3:
The best way to make sure our service will execute after all other enabled services is to create your own target and make it run after multi-user.target
.
Typically:
- Create a target unit
/etc/systemd/system/custom.target
file withAllowIsolate=yes
[Unit]
Description=My Custom Target
Requires=multi-user.target
After=multi-user.target
AllowIsolate=yes
- Create you service unit file
/etc/systemd/system/last_command.service
withAfter=multi-user.target
andWantedBy=custom.target
[Unit]
Description=My custom command
After=multi-user.target
[Service]
Type=simple
ExecStart=/usr/local/bin/my_last_command.sh
[Install]
WantedBy=custom.target
- Create the
/etc/systemd/system/custom.target.wants
directory - Link your
last_command;service
into/etc/systemd/system/custom.target.wants
ln -s /etc/systemd/system/last_command.service \
/etc/systemd/system/custom.target.wants/last_command.service
- Reload systemd with
systemctl daemon-reload
- Set the system default target as
custom.target
systemctl set-default custom.target
- Optionally, you may want apply immediately the
custom.target
systemctl isolate custom.target
This way, for each reboot, your last command will be executed after the multi-user.target
is reached.