23

I want to specify an Environment systemd directive containing =, e.g.

Environment=CATALINA_OPTS=-Dappserver.home=/var/lib/archiva/apache-tomcat-current -Dappserver.base=/var/lib/archiva/apache-tomcat-current

and get the error

[/lib/systemd/system/archiva.service:10] Invalid environment assignment, ignoring: CATALINA_OPTS=-Dappserver.home\=/var/lib/archiva/apache

in journalctl -xe. I tried to quote with " and ' and to escape = with \ without success. This seems undocumented.

muru
  • 207,228

3 Answers3

45

I think your problem is due the space in the environment variable's contents. Looking at the examples from the systemd docs, an assignment should be a single string:

Example:

Environment="ONE=one" 'TWO=two two'
ExecStart=/bin/echo $ONE $TWO ${TWO}

This will execute /bin/echo with four arguments: one, two, two, and two two.

Example:

Environment=ONE='one' "TWO='two two' too" THREE=
ExecStart=/bin/echo ${ONE} ${TWO} ${THREE}
ExecStart=/bin/echo $ONE $TWO $THREE

This results in echo being called twice, the first time with arguments 'one', 'two two' too, , and the second time with arguments one, two two, too.

I tested this with the following service (note the quotes around the entire assignment):

[Unit]
Description=My Daemon

[Service]
Environment='CATALINA_OPTS=-Dappserver.home=/var/lib/archiva/apache-tomcat-current -Dappserver.base=/var/lib/archiva/apache-tomcat-current'
ExecStart=/bin/echo ${CATALINA_OPTS}

[Install]
WantedBy=multi-user.target

And got the desired output in journalctl:

Apr 26 08:19:29 laptop echo[28439]: -Dappserver.home=/var/lib/archiva/apache-tomcat-current -Dappserver.base=/var/lib/archiva/apache-tomcat-current

Of course, it would be simpler to use EnvironmentFile instead. Replacing the Environment with the following gave the same desired result:

EnvironmentFile=/tmp/foo

Where /tmp/foo contained (note the lack of quotes):

CATALINA_OPTS=-Dappserver.home=/var/lib/archiva/apache-tomcat-current -Dappserver.base=/var/lib/archiva/apache-tomcat-current
muru
  • 207,228
2

In addition to what the accepted answer says, if you put your environment variables into a drop-in file, then you need to use the following syntax to make sure they are not all treated as one argument to your program:

env.conf drop-in file

[Service]
Environment='CATALINA_OPTS=-Dappserver.home=/var/lib/archiva/apache-tomcat-current -Dappserver.base=/var/lib/archiva/apache-tomcat-current'

unit.service

[Unit]
Description=My Daemon

[Service] ExecStart=/bin/echo $CATALINA_OPTS

[Install] WantedBy=multi-user.target

I don't know why using just $ENV_NAME worked for me, and ${ENV_NAME} didn't, and I couldn't find anything documenting this difference. All I can say is that $ENV_NAME syntax worked to treat each argument in the variable which is separated by space, as distinct arguments, whereas the ${ENV_NAME}, treated them all as one argument.

Maybe using echo is not the best way to tell this difference. I suggest anyone looking to test it to use something like /usr/bin/printf "%s\n" ${ENV_NAME} vs /usr/bin/printf "%s\n" $ENV_NAME, and see what they get.

Creating drop-in files

One can create a drop-in file by using the edit command for systemctl. For example in the case of this question, the command would be:

sudo systemctl edit archiva.service

You can also create one like I did above by adding a custom file to /lib/systemd/system/archiva.service.d/ folder


EDIT

I found the documentation on observed environmental variable behavior, thanks to another answer:

Basic environment variable substitution is supported. Use "${FOO}" as part of a word, or as a word of its own, on the command line, in which case it will be erased and replaced by the exact value of the environment variable (if any) including all whitespace it contains, always resulting in exactly a single argument. Use "$FOO" as a separate word on the command line, in which case it will be replaced by the value of the environment variable split at whitespace, resulting in zero or more arguments. For this type of expansion, quotes are respected when splitting into words, and afterwards removed.

smac89
  • 1,085
-1

Alternative solution

"C escapes supported in command lines and environment variables"

  • "\n" newline
  • "\r" carriage return
  • "\t" tab
  • "\v" vertical tab
  • "\" backslash
  • """ double quotation mark
  • "'" single quotation mark
  • "\s" space
  • "\xxx" character number xx in hexadecimal encoding
  • "\nnn" character number nnn in octal encoding

https://www.freedesktop.org/software/systemd/man/systemd.service.html

Gary
  • 99