Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

systemd: multiple units of the same

Tags:

linux

systemd

I try to start multiple processes with systemd - restart if it terminated included. The only difference is the argument of the processes.

Is there a way to avoid a unit-file per process?? I am looking for a unit-file for all processes together.

Normally I would use a start-skript but - as I said - restart in case of termination should be also included. And I do not see a way to do it with pure systemd and no handmade skriptlets.

Thanks!

like image 351
chris01 Avatar asked Sep 16 '25 18:09

chris01


1 Answers

Perhaps using a template unit fits your needs. From systemd.unit(5)

Optionally, units may be instantiated from a template file at runtime. This allows creation of multiple units from a single configuration file. If systemd looks for a unit configuration file, it will first search for the literal unit name in the file system. If that yields no success and the unit name contains an "@" character, systemd will look for a unit template that shares the same name but with the instance string (i.e. the part between the "@" character and the suffix) removed. Example: if a service [email protected] is requested and no file by that name is found, systemd will look for [email protected] and instantiate a service from that configuration file if it is found.

To refer to the instance string from within the configuration file you may use the special "%i" specifier in many of the configuration options. See below for details.

So you might create a file [email protected] that reads something like

[Unit]
Description=MyService component %i
PartOf=myservice.target

[Service]
Type=simple
ExecStart=/usr/local/bin/myservice %i
Restart=on-failure

and the master unit myservice.target as

[Unit]
Description=Myservice
[email protected] [email protected] [email protected]

The PartOf= specification in [email protected] ensures that when the target is stopped or restarted each component is as well. With Requires= in myservice.target each component must be started for myservice to have successfully started. I think it should be the case that if any individual component fails any that didn't fail should be terminated; i.e. its all or nothing. If that's not what you want you might use Want= instead of Requires=.

It's a little awkward, but if you need to supply multiple arguments you can introduce an indirection through environment variables. For the template unit add Environment=args=%i and replace %i in the ExecStart with $args. I think it'd be better to find an alternative to that, but without knowing more about your use-case I'm not sure what that solution would be.

like image 127
Geoff Reedy Avatar answered Sep 18 '25 09:09

Geoff Reedy