Score:2

Passing "flag" Arguments to Systemd Services

us flag

I have a Systemd service that calls a script. That script takes it's own arguments, some of which are named arguments. I currently have the following service:

[Unit]
Description=My Service
StartLimitIntervalSec=0

[Service]
Type=simple
Restart=no
User=corvus
Environment="ARGS=%I"
ExecStart=/path/to/script.sh $ARGS

[Install]
WantedBy=multi-user.target

And I am attempting to call the script with something like:

$ sudo systemctl start myservice@"--flag argument".service

However this doesn't seem to work and the -- part of the flag seems to get converted into //. The service looks like it is running, but doesn't seem to be and in the systemd status information I can see where it has substituted the -- with //.

I have attempted to escape the - by prefixing them with a \ however that also doesn't work and the service doesn't actually start with this approach.

Any pointers or things to try would be appreciated!

Score:4
us flag

The conversion of - to / is for allowing paths in the template argument and other parts of the unit name. This is covered in man systemd.unit, section "String Escaping for Inclusion in Unit Names":

Sometimes it is useful to convert arbitrary strings into unit names. To facilitate this, a method of string escaping is used, in order to map strings containing arbitrary byte values (except NUL) into valid unit names and their restricted character set. A common special case are unit names that reflect paths to objects in the file system hierarchy. Example: a device unit dev-sda.device refers to a device with the device node /dev/sda in the file system.

The escaping algorithm operates as follows: given a string, any "/" character is replaced by "-", and all other characters which are not ASCII alphanumerics, ":", "_" or "." are replaced by C-style "\x2d" escapes. In addition, "." is replaced with such a C-style escape when it would appear as the first character in the escaped string.

[...]

This escaping is fully reversible, as long as it is known whether the escaped string was a path (the unescaping results are different for paths and non-path strings). The systemd-escape(1) command may be used to apply and reverse escaping on arbitrary strings. Use systemd-escape --path to escape path strings, and systemd-escape without --path otherwise.

So:

% systemd-escape  -- "--flag argument"
\x2d\x2dflag\x20argument

You should use \x2d\x2dflag\x20argument as the template argument.

Ben Turner avatar
us flag
This has helped overcome the first hurdle, however I have now noticed that the string "--flag argument" gets passed to the script as a single argument. My script uses a `while [[ $# -gt 0 ]]; do` loop to loop over the arguments looking for flag-value pairs ($1 and $2 in the script respectively).As there is only a single argument provided from systemd, this functionality is broken. Is there a way of fixing this at the service level or do I need to modify my script to account for it?
muru avatar
us flag
You could try something like `ExecStart=/bin/sh -c 'set -f; /path/to/script.sh %I'` to have a shell do whitespace splitting for you (you might need to use `/bin/sh -c 'set -f; /path/to/script.sh $@' sh %I` - I don't remember how exactly quoting and templating mix in systemd units. However, if this is your script and you can modify it, I strongly recommend using environment variables (`FLAG_VAR=argument` and then use the template argument to set an `EnvironmentFile`) or maybe reading flags from a file instead of forcing command-line arguments directly into the template argument.
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.