Systemd with multiple execStart [closed]
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
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
Why in the world was this closed? The question obviously involves a specific problem and software tools used primarily by programmers.
2 Answers 2
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
$ systemctl start foo@parameter1.service foo@parameter2.service
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.
How to use a parameter in ExecStart command line?
I try to convert a SysVinit script used on Debian (and derivative distros such as Linux Mint and Ubuntu & Co.) to a systemd service to be used on Fedora or Arch Linux (and derivative distros such as Bridge or Manjaro), but even if the systemd start system is more performant and versatile than the previous, I don’t understand how to make simple stuff such as using an «optional» argument on a command line like ExecStart= or ExecRestart= ! Here is what I do with SysVinit:
#!/bin/sh ### BEGIN INIT INFO # Provides: myprog # Required-Start: $remote_fs $syslog # Required-Stop: $remote_fs $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: myprog init script # Descripton: this script manages myprog ### END INIT INFO # exit if myprog isn't installed [ -x "/opt/mystuff/myrpog" ] || exit 0 case "$1" in start) cd /opt/mystuff ./myprog -r echo ;; stop) cd /opt/mystuff ./myprog -x ;; restart) cd /opt/mystuff ./myprog -x && ./myprog -r ;; version) cd /opt/mystuff ./myprog -v ;; try) cd /opt/mystuff ./myprog ;; *) echo "Usage: sudo service myprog " >&2 exit 3 ;; esac :
So the script above allows to use different arguments including an empty one that will display the message «Usage: . » when using the following command lines:
sudo service myprog start # Start myprog with the -r argument sudo service myprog stop # Stop myprog with the -x argument sudo service myprog version # Display the release of myprog in the console sudo service myprog try # Start myprog without any argument sudo service myprog restart # Stop then start myprog with the -r argument sudo service myprog # Display the "Usage. " message in the console
[Unit] Description=This script manages myprog ConditionFileExecutable=/opt/mystuff/myprog [Service] Type=oneshot RemainAfterExit=yes ExecStart=/opt/mystuf/myprog -r ExecStop=/opt/mystuff/myprog -x ExecRestart=/opt/mystuff/myprog -x : /opt/mystuff/myprog -r [Install] After=NetworkManager.service
Here starts my problems (and my lack of systemd knowledge): Obviously, systemd doesn’t provide a command such as ExecCustom01= , ExecCustom02 , etc. that would allow me to create commands for «version» and «try» (and other if needed). So, I may use ExecRestart in a different manner if I could use an argument to start both the «version» or the «try» command (being said that the «real» restart may be done by starting successively the stop and the start commands). These «customized» ExecRestart= command could then look like this:
sudo systemctl restart myprog # Without argument for the "try" command
sudo systemctl restart myprog -v # For the "version" command
[Unit] Description=This script manages myprog ConditionFileExecutable=/opt/mystuff/myprog [Service] Type=oneshot RemainAfterExit=yes ExecStart=/opt/mystuf/myprog -r ExecStop=/opt/mystuff/myprog -x ExecRestart=/opt/mystuff/myprog . // This is where I need to use an argument [Install] After=NetworkManager.service
But I don’t know if it’s possible, and if yes, what is the syntax to use? Any help would be truly appreciated since even after spending a bunch of hours in the multiple systemd man pages, I couldn’t find any explicit sample about how to do that. Thanks in advance for your time and advice.
systemd — Giving my service multiple arguments
Is it possible to give my systemd service more than one argument? I’d like to execute a program with multiple arguments which have to be decided by the final user. E.g: ./program arg1 arg2 To start it a single argument app I’d need something like systemctl start arg1@program , where in the service definition I have ExecStart = /usr/bin/program ℅i . Thanks!
4 Answers 4
Yes you can! Define them in a file somewhere and add them to EnvironmentFile in your systemd Service. For example, say the contents of /etc/.progconf are:
EnvironmentFile=/etc/.progconf ExecStart=/usr/bin/prog $ $
You can write to that file if you need to change them on the go. A service shouldn’t change its options very often, maybe consider autostarting or cron if you need to achieve that.
Heh, quite handy, didn’t think of that. I have to agree though: Service parameters don’t change on a regular basis, and neither do their config files.
if the service file uses environment variables, can you say VAR1=. VAR2=. systemctl start foobar.service to pass the variables?
@JohannesSchaub-litb, no, you can’t. There is a PassEnvironment directive, but it takes variables from the systemd process (normally PID 1), not from systemctl . Environment variables from the systemctl process don’t get propagated to the service being started.
But upstart can run multiple instances of the same service, with different parameters. For example a mail server on eth0 and another instance of said mailserver on eth1, passing the parameter to upstart and managing them as separate services. Can systemd do this?
I wanted to do the same thing, but without a separate file for each combination of arguments. I found that I could pass one long argument with spaces and then use systemd’s environment variable space-splitting feature to separate the arguments.
I made a service with filename argtest@.service (note the trailing ‘at sign’ which is required when a service takes arguments).
[Unit] Description=Test passing multiple arguments [Service] Environment="SCRIPT_ARGS=%I" ExecStart=/tmp/test.py $SCRIPT_ARGS
I run this with sudo systemctl start argtest@»arg1 arg2 arg3″.service and it passes arg1 , arg2 and arg3 as separate command-line arguments to test.py.