Why does bash parameter expansion not work inside systemd service files?

26,583

systemd does its own minimalistic shell-style command line parsing of the contents of ExecStart= and other parameters. This minimalistic parsing supports basic environment variable substitution but apparently not things like ${PORT:+port is $PORT}.

You will want to prevent systemd from doing that and let the invoked shell handle it.

From the documentation:

To pass a literal dollar sign, use "$$".

So try this:

ExecStart=/usr/bin/bash -c "echo $${PORT:+port is $$PORT}"

Or better yet, try this:

ExecStart=/bin/sh -c "echo $${PORT:+port is $$PORT}"

because the type of variable expansion you are doing here is POSIX standard and is not a bash-ism. By using /bin/sh instead of bash you will remove an unnecessary dependancy on bash.

Share:
26,583

Related videos on Youtube

Lev Levitsky
Author by

Lev Levitsky

A graduate of Moscow Institute of Physics and Technology (B.S. and M.S. in applied physics and math). Now I focus on utilizing Python for the needs of proteomics. Most of our results are available as Python packages pyteomics and pyteomics.biolccc.

Updated on September 18, 2022

Comments

  • Lev Levitsky
    Lev Levitsky over 1 year

    I am trying to use systemd's EnvironmentFile and add an option to the command when it is set in the file. I have the following in the unit file:

    ExecStart=/usr/bin/bash -c "echo ${PORT:+port is $PORT}"
    

    which doesn't echo anything when I start the service.

    The following works as expected:

    ExecStart=/usr/bin/bash -c "echo port is $PORT"
    

    which means that the file is read correctly.

    Parameter substitution also works on command line:

    $ PORT=1234 bash -c 'echo ${PORT:+port is $PORT}'
    port is 1234
    

    What am I missing?