Systemd: a linux service management system. It manages all the process from the start of the system.
There are standard methods to call systemd:
enable
: service will automatically be started by its starting logic specified
disable
: reverse of enable
start
: start the service regardless
stop
: stop the service regardless
restart
: stop and start (if not running, just start)
reload
: faster version of restart
but unstable
status
: check status
To config .service
file, you can modify user-wide /usr/lib/systemd
or systemwide /etc/systemd/system/*.service
, or permissioned-systemd /etc/systemd/user
. Or you can make it default with /lib/systemd/system/*.service
Usually we put in /etc/systemd/system/*.service
, for more info, visit stackoverflow
Below is a template that can help you write *.system
file.
[Unit]
Description=Description
Requires=dependency1.service dependency2.service
Wants=dependency-that-may-fail-and-still-ok.service
After=only-execute-after.service
[Service]
Type=simple/oneshot
RemainAfterExit=yes/no (only specified when oneshot)
User=www-data
Group=www-data
WorkingDirectory=/absolute/directory
ExecStart=/path/to/zsh ./start-gunicorn-http.sh
ExecStart=/bin/bash -c "echo you can have none or multiple ExecStart is you use oneshot, otherwise only one"
ExecStop=/bin/bash -c "echo something && echo other things"
[Install]
WantedBy=if-this-service-launch-I-will-launch-but-it-is-okay-for-me-to-fail.target
RequiredBy=if-this-service-launch-I-will-launch-but-it-is-bad-for-me-to-fail.target
Common Mistakes
You can't use any &&
and <
commands directly in ExecStart
because the commands is not executed in any shell
You can't directly execute program like tmux
or zsh
because environment variable is not loaded
You should make sure the permission of User
and Group
is correct (not with super power root
but with sufficient and reasonable power)
You should make sure the command you try to execute has resources defined by After
and by Requires
.
This section is (non-exact) copy of original article here
simple-test.service
[Unit]
Description=Simple service test
[Service]
Type=simple
ExecStart=/bin/bash -c "echo Simple service - start && sleep 60 && echo Simple service - end"
dep-simple-test.service
[Unit]
Description=Dependent service
After=simple-test.service
Requires=simple-test.service
[Service]
ExecStart=/bin/bash -c "echo Dependent service - running"
Starting dep-simple-test.service
will start simple-test.service
first (because of the After/Requires directives), and the logging shows:
Jun 19 20:28:16 thstring20200619162314 systemd[1]: Started Simple service test.
Jun 19 20:28:16 thstring20200619162314 systemd[1]: Started Dependent service.
Jun 19 20:28:16 thstring20200619162314 bash[1238]: Simple service - start
Jun 19 20:28:16 thstring20200619162314 bash[1239]: Dependent service - running
Jun 19 20:28:16 thstring20200619162314 systemd[1]: dep-simple-test.service: Succeeded.
Jun 19 20:29:16 thstring20200619162314 bash[1238]: Simple service - end
Jun 19 20:29:16 thstring20200619162314 systemd[1]: simple-test.service: Succeeded.
You can see the dependency runs first but the depended program will start immediately around the same time without waiting for the dependency to finish execute.
oneshot-test.service
[Unit]
Description=Oneshot service test
[Service]
Type=oneshot
ExecStart=/bin/bash -c "echo Oneshot service - start && sleep 60 && echo Oneshot service - end"
dep-oneshot-test.service
[Unit]
Description=Dependent service
After=oneshot-test.service
Requires=oneshot-test.service
[Service]
ExecStart=/bin/bash -c "echo Dependent service - running"
Jun 19 20:31:46 thstring20200619162314 systemd[1]: Starting Oneshot service test...
Jun 19 20:31:46 thstring20200619162314 bash[1420]: Oneshot service - start
Jun 19 20:32:46 thstring20200619162314 bash[1420]: Oneshot service - end
Jun 19 20:32:46 thstring20200619162314 systemd[1]: oneshot-test.service: Succeeded.
Jun 19 20:32:46 thstring20200619162314 systemd[1]: Started Oneshot service test.
Jun 19 20:32:46 thstring20200619162314 systemd[1]: Started Dependent service.
Jun 19 20:32:46 thstring20200619162314 bash[1440]: Dependent service - running
Jun 19 20:32:46 thstring20200619162314 systemd[1]: dep-oneshot-test.service: Succeeded.
You can see the program wait for the dependency to finish execution.
Type | Before | During | After |
---|---|---|---|
Simple | inactive (dead) | active (running) | inactive (dead) |
Oneshot | inactive (dead) | activating (start) | inactive (dead) |
Oneshot (RemainAfterExit) | inactive (dead) | activating (start) | active (exited) |
oneshot-execstop-remainafterexit.service
[Unit]
Description=Oneshot service test with ExecStop and RemainAfterExit
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/bash -c "echo Oneshot service - start && sleep 60 && echo Oneshot service - end"
ExecStop=/bin/bash -c "echo Oneshot service - stop"
Running systemctl status
on this service at it has run, we can see the difference:
● oneshot-execstop-remainafterexit.service - Oneshot service test with ExecStop and RemainAfterExit
Loaded: loaded (/etc/systemd/system/oneshot-execstop-remainafterexit.service; static; vendor preset: enabled)
Active: active (exited) since Fri 2020-06-19 21:07:54 UTC; 8s ago
Process: 1708 ExecStart=/bin/bash -c echo Oneshot service - start && sleep 60 && echo Oneshot service - end (code=exited, status=0/SUCCESS)
Main PID: 1708 (code=exited, status=0/SUCCESS)
Jun 19 21:06:54 thstring20200619162314 systemd[1]: Starting Oneshot service test with ExecStop and RemainAfterExit...
Jun 19 21:06:54 thstring20200619162314 bash[1708]: Oneshot service - start
Jun 19 21:07:54 thstring20200619162314 bash[1708]: Oneshot service - end
Jun 19 21:07:54 thstring20200619162314 systemd[1]: Started Oneshot service test with ExecStop and RemainAfterExit.
You can see with
RemainAfterExit=yes
,oneshot
program will showactive
even after program finish execution.
If we run systemctl stop oneshot-execstop-remainafterexit.service
, then it will execute ExecStop=/bin/bash -c "echo Oneshot service - stop"
:
Jun 19 21:07:54 thstring20200619162314 systemd[1]: Started Oneshot service test with ExecStop and RemainAfterExit.
Jun 19 21:08:58 thstring20200619162314 systemd[1]: Stopping Oneshot service test with ExecStop and RemainAfterExit...
Jun 19 21:08:58 thstring20200619162314 bash[1900]: Oneshot service - stop
Jun 19 21:08:58 thstring20200619162314 systemd[1]: oneshot-execstop-remainafterexit.service: Succeeded.
Jun 19 21:08:58 thstring20200619162314 systemd[1]: Stopped Oneshot service test with ExecStop and RemainAfterExit.
This is in contrast to
RemainAfterExit=no
(default behavior) as shown below:
oneshot-execstop.service
[Unit]
Description=Oneshot service test with ExecStop
[Service]
Type=oneshot
RemainAfterExit=no
ExecStart=/bin/bash -c "echo Oneshot service - start && sleep 60 && echo Oneshot service - end"
ExecStop=/bin/bash -c "echo Oneshot service - stop"
● oneshot-execstop.service - Oneshot service test with ExecStop
Loaded: loaded (/etc/systemd/system/oneshot-execstop.service; static; vendor preset: enabled)
Active: inactive (dead)
Jun 19 21:04:10 thstring20200619162314 systemd[1]: Starting Oneshot service test with ExecStop...
Jun 19 21:04:10 thstring20200619162314 bash[1480]: Oneshot service - start
Jun 19 21:05:10 thstring20200619162314 bash[1480]: Oneshot service - end
Jun 19 21:05:10 thstring20200619162314 bash[1604]: Oneshot service - stop
Jun 19 21:05:10 thstring20200619162314 systemd[1]: oneshot-execstop.service: Succeeded.
Jun 19 21:05:10 thstring20200619162314 systemd[1]: Started Oneshot service test with ExecStop.
We can see that the
ExecStop
ran immediately when theExecStart
was done.
oneshot
service has special power:
It does not have to have ExecStart
(but then you must have ExecStop
and RemainAfterExit=yes
)
It can have multiple ExecStart
When multiple ExecStart
are defined, the service fail if one of the ExecStart
fails:
oneshot-multiple-execstart-failure.service
[Unit]
Description=Oneshot service test with multiple ExecStart and failure
[Service]
Type=oneshot
ExecStart=/bin/bash -c "echo First"
ExecStart=/bin/bash -c "false && echo Second"
ExecStart=/bin/bash -c "echo Third"
$ sudo systemctl start oneshot-multiple-execstart-failure.service
Job for oneshot-multiple-execstart-failure.service failed because the control process exited with error code.
See "systemctl status oneshot-multiple-execstart-failure.service" and "journalctl -xe" for details.
$ sudo journalctl -u oneshot-multiple-execstart-failure.service
-- Logs begin at Mon 2020-06-22 13:24:01 UTC, end at Mon 2020-06-22 13:37:16 UTC. --
Jun 22 13:36:53 thstring20200622092223 systemd[1]: Starting Oneshot service test with multiple ExecStart and failure...
Jun 22 13:36:53 thstring20200622092223 bash[1441]: First
Jun 22 13:36:53 thstring20200622092223 systemd[1]: oneshot-multiple-execstart-failure.service: Main process exited, code=exited, status=1/FAILURE
Jun 22 13:36:53 thstring20200622092223 systemd[1]: oneshot-multiple-execstart-failure.service: Failed with result 'exit-code'.
Jun 22 13:36:53 thstring20200622092223 systemd[1]: Failed to start Oneshot service test with multiple ExecStart and failure.
However, if you want to prevent this behavior, you can add -
character in front of the executable.
oneshot-multiple-execstart-failure-success.service
[Unit]
Description=Oneshot service test with multiple ExecStart and failure
[Service]
Type=oneshot
ExecStart=/bin/bash -c "echo First"
ExecStart=-/bin/bash -c "false && echo Second"
ExecStart=/bin/bash -c "echo Third"
-- Logs begin at Mon 2020-06-22 13:24:01 UTC, end at Mon 2020-06-22 13:39:04 UTC. --
Jun 22 13:38:59 thstring20200622092223 systemd[1]: Starting Oneshot service test with multiple ExecStart and failure...
Jun 22 13:38:59 thstring20200622092223 bash[1553]: First
Jun 22 13:38:59 thstring20200622092223 bash[1555]: Third
Jun 22 13:38:59 thstring20200622092223 systemd[1]: oneshot-multiple-execstart-failure-success.service: Succeeded.
Jun 22 13:38:59 thstring20200622092223 systemd[1]: Started Oneshot service test with multiple ExecStart and failure.
When you are deciding which service type to choose between simple and oneshot, here is some guidance:
Does your service need to complete before any follow-up services run? Use oneshot.
Do your follow-up services need to be running while this service does? Use simple.
Is this a long-running service? Probably use simple.
Do you need to run this service only at shutdown? Use oneshot.
Do you need to have multiple separate commands to run? Use oneshot.
Table of Content