Coordinate Scripts With systemd
Use systemd to execute scripts, controlling the order of execution.
- Assuming we have:
a single preparation unit -
multiple "task" units -
a single cleanup script -
We want to run the prep unit once, then run all our task units and finally the done unit once.
Defining dependencies between tasks is relatively simple when each task
is represented by a systemd unit 1.
Dependencies are defined using
and order of execution is defined with
The only thing left is to make sure that the "preparation" and "finish" steps are executed only once, even if multiple tasks are run (and not once for each task).
To achieve this a
.target is created
and all tasks are associated to that target.
.servicefiles for the commands that must be executed before
.servicefor commands that should be executed after
Create as single
.targetfor all tasks
.servicefor each task, make it
The target file goes into
/etc/systemd/system and looks like this:
The target can be started manually with:
The task units are associated with the target using
This means, if we enable one or more task units with
... starting the
tasks.target will start all of the associated
This allows us to start all tasks with a single invocation which in turn means that we execute any number of tasks and the prep and done units only once.
Each task unit specifies the
prep.service as a
It also specifies the
Before= to have it run after the tasks.
# task.service --------------------------------------- [Unit] Description = A task unit Requires = prep.service After = prep.service Wants = done.service Before = done.service [Service] User = someuser Group = somegroup Type = oneshot ExecStart = /usr/local/bin/script.sh [Install] WantedBy = tasks.target
Requires=prep.service directive means that the task is not started
Wants=prep.service would try to start the prep unit first
but continue with the tasks regardless of whether preparation was
successful or not.
Group= properties can be used to run the command
under a different user than root.
Not all tasks have to specify the same dependencies. It is also possible that tasks depend on each other.
Prep and Done Units
prep.service and the
done.service are plain units
and do not define any dependencies.
the prep unit should be configured with
to have it complete before the first task can be started.
After= only control the order in which
services are started.
To make sure that the prep unit completes before the tasks are started,
Type=oneshot in the
Behavior of oneshot is similar to simple; however, it is expected that the process has to exit before systemd starts follow-up units.
The same goes for the task units if the done unit should only be executed after the tasks are complete.
- Custom unit files go into:
/etc/systemd/systemfor system-wide scope
~/.config/systemd/userfor user-specific scope