22

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.

0
43

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
9
  • When it comes to quoting quotes (e.g. by using CATALINA_OPTS in systemd environment for Apache tomcat 7.0.61) using EnvironmentFile really is the way to go. Thanks! – Karl Richter Apr 26 '15 at 17:11
  • What is the standard/ convention directory for keeping an EnvironmentFile on Ubuntu? On other systems I've seen /etc/sysconfig/ – Davos Aug 29 '17 at 1:20
  • 2
    @Davos a reasonable place would be /etc/default. Files there have been historically used for placing environment variables for corresponding init scripts. – muru Aug 29 '17 at 1:21
  • I have this file already on my system /etc/environment which contains a PATH variable, would appending to that be sensible? – Davos Aug 29 '17 at 1:22
  • 1
    @Davos that's systemwide. If there's no problem with the variable being set for practically every process, sure. Note that /etc/environment is not processed by a shell; aside from simple variable assignment, its syntax is very different from the systemd syntax noted above or general shell syntax. – muru Aug 29 '17 at 1:25
0

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

0

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.


EDIT

I found the documentation, 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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.