96

Is it possible to create service with the same script started with different input parameters?

Example:

[Unit]
Description=script description

[Service]
Type=simple
ExecStart=/script.py parameters1
ExecStart=/script.py parameters2
Restart=on-failure

[Install]
WantedBy=multi-user.target

Is it possible?

Will it be launched in serial-mode? Or in two different process?

Lii
  • 11,553
  • 8
  • 64
  • 88
Riccardo
  • 1,011
  • 1
  • 8
  • 7
  • 4
    Why in the world was this closed? The question obviously involves a specific problem and software tools used primarily by programmers. – aquirdturtle Dec 28 '22 at 22:31

2 Answers2

149

if Type=simple in your unit file, you can only specify one ExecStart, but you can add as many ExecStartPre, ExecStartPost, but none of this is suited for long running commands, because they are executed serially and everything one start is killed before starting the next one.

If Type=oneshot you can specify multiple ExecStart, they run serially not in parallel.

If what you want is to run multiple units in parallel, there a few things you can do:

If they differ on 1 param

You can use template units, so you create a /etc/systemd/system/foo@.service. NOTE: (the @ is important).

[Unit]
Description=script description %I

[Service]
Type=simple
ExecStart=/script.py %i
Restart=on-failure

[Install]
WantedBy=multi-user.target

And then you exec:

$ systemctl start foo@parameter1.service foo@parameter2.service

or...

Target dependencies

You can create multiple units that links to a single target:

#/etc/systemd/system/bar.target
[Unit]
Description=bar target
Requires=multi-user.target
After=multi-user.target
AllowIsolate=yes

And then you just modify you .service units to be WantedBy=bar.target like:

#/etc/systemd/system/foo@.service
[Unit]
Description=script description %I

[Service]
Type=simple
ExecStart=/script.py %i
Restart=on-failure

[Install]
WantedBy=bar.target

Then you just enable the foo services you want in parallel, and start the bar target like this:

$ systemctl daemon-reload
$ systemctl enable foo@param1.service
$ systemctl enable foo@param2.service
$ systemctl start bar.target

NOTE: that this works with any type of units not only template units.

quantum
  • 3,672
  • 29
  • 51
aleivag
  • 2,306
  • 1
  • 13
  • 13
  • 2
    Very nice solution! But note that `systemctl stop bar.target` doesn't stop any of these linked services :'( – jirislav Oct 26 '18 at 23:09
  • @aleivag what about if I want stop all the running services? should I execute `systemctl stop foo@param_number.service` for each service? and if I have 100 services registered to the same target? – Spartaok Nov 20 '18 at 11:45
  • 1
    @Spartaok you do `systemctl stop foo@*` – aleivag Dec 06 '18 at 21:15
  • 6
    Also you may add `PartOf=bar.target` into `[Unit]` section of `foo@.service`. This allows to stop services when target is being stopped. – Johny Dec 24 '18 at 15:49
  • 4
    Pay attention that if you want `bar.target` started during system boot you need to add `[Install]` section with `WantedBy=multi-user.target` line into `bar.target` and enable this target with the next command: `systemctl enable bar.target` – Johny Dec 24 '18 at 15:51
  • @aleivag if I do `systemctl start foo@` not works, only stop, is there a way to start also all the instances? thanks.. – sfarzoso Mar 10 '19 at 16:11
  • @sfarzoso not really, because `foo@` can be anithing ... you can add stuff like `foo@34578968372469028` and that is valid... , stop on the other hanmd, can stop all active units... – aleivag Mar 13 '19 at 19:23
  • You could also use a "systemd multi service application" http://alesnosek.com/blog/2016/12/04/controlling-a-multi-service-application-with-systemd/ – rogerdpack May 16 '19 at 23:10
32

You can use ExecStartPre or ExecStartPost for one of scripts

[Unit]
Description=script description

[Service]
Type=simple
ExecStartPre=/script.py parameters1
ExecStart=/script.py parameters2
Restart=on-failure

[Install]
WantedBy=multi-user.target
amin khozaei
  • 431
  • 3
  • 7
  • 3
    But in the control I read " Additional commands that are executed before or after the command in ExecStart=, respectively. Syntax is the same as for ExecStart=, except that multiple command lines are allowed and the commands are executed one after the other, serially " In your case, i should wait that the first script on success before the system start second script or not? Thank you – Riccardo Jan 11 '18 at 09:05
  • Yes, in this solution you should wait for success of first script. Another solution is about creating bash script that get `parameters1` and `parameters2` and then pass them to python scripts. – amin khozaei Jan 12 '18 at 20:43