93

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!

Thor
  • 4,043
peperunas
  • 1,321

4 Answers4

74

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:

ARG1=-o
ARG2=--verbose

And your .service file:

EnvironmentFile=/etc/.progconf
ExecStart=/usr/bin/prog ${ARG1} ${ARG2}

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.

For more examples check: https://wiki.archlinux.org/index.php/Systemd/Services

alexm
  • 1,131
49

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.

nonagon
  • 593
8

Easiest I have found is:

ExecStart=/bin/bash -c "\"/path/with spaces/to/app\" arg1 arg2 arg3 \"arg with space\""

Keeps it all self contained.

Having said that, I have found that at least on Ubuntu 18.04 LTS, I don't even need to do that, I can do this and it works fine:

ExecStart="/path/with spaces/to/app" arg1 arg2 arg3 "arg with space"

$vars work as arguments with this pattern as well.

jjxtra
  • 183
3

Tell your users to override the service by creating a drop-in snippet through the use of the edit option in systemctl.

Firstly, start with some sane defaults. Let's assume the ExecStart part of your service declares the following:

[Service]
ExecStart=./program arg1

Now any user of this service can decide that they want to use a different set of arguments for running the program. They can do that by creating a drop-in snippet with:

systemctl edit myservice.service

In the new file, they simply write the following to override the ExecStart:

[Service]
ExecStart=
ExecStart=./program arg1 arg2

The benefit of doing it this way is that the end result does not involve modifying the system-installed service which may conflict with some package managers.

And that's it!

Now just reload systemd (systemctl daemon-reload) and restart the service (systemctl restart myservice.service).

When the service restarts, it will always also load the user's modifications.

I hope that helps


Sources:

smac89
  • 474