Environment variable in /etc/environment with pound (hash) sign in the value
On Ubuntu 12.04, I have an environment variable defined in /etc/environment
like this:
FOO="value_before#value_after"
When I ssh into the server to check the value, I get this:
$ env | grep FOO
FOO=value_before
I'm guessing it is treating the #
as a comment and stripping it out, however, this works:
$ . /etc/environment
$ export FOO
$ env | grep FOO
FOO=value_before#value_after
I've tried escaping the #
like this:
FOO="value_before\#value_after"
But that doesn't work, instead I just get this:
FOO=value_before\
Any ideas on how to make the hash be treated like part of the value? Any help would be great.
Values I've tried in the /etc/environment
file:
FOO='value_before#value_after'
FOO="value_before#value_after"
FOO='"value_before#value_after"'
FOO="value_before\#value_after"
FOO='value_before\#value_after'
And other various combinations of the above. A lot of these will work when you just normally set them in the shell. But they don't seem to work in the /etc/environment
file.
This is read by the pam_env module. Given that the pam_env module expects them to be "simple" KEY=VALUE pairs (doesn't need quotes) and also supports comments identified by #, it assumes that a # and anything following it in a VALUE are a comment. Also, note that it does not support any concept of escaping.
This can be seen in the following snippet from the _parse_env_file function in pam_env.c.
/* now find the end of value */
mark = key;
while(mark[0] != '\n' && mark[0] != '#' && mark[0] != '\0')
mark++;
if (mark[0] != '\0')
mark[0] = '\0';
The above snippet walks each character of the VALUE portion until it finds a \n
, #
or \0
. It then overwrites that character with a \0
.
This effectively strips off the #
and everything following. Note: This is a feature not a bug. It is the comment feature.
So, at this point you cannot have values in /etc/environment
that include a #
or a \n
or \0
in the middle of the value. It also looks like from the code that the keys need to be alpha-numeric.
I was never able to find a way around this limitation in /etc/environment
, the documentation seems to state that /etc/environment
is a simple environment file:
This module can also parse a file with simple KEY=VAL pairs on separate
lines (/etc/environment by default).
Which might mean it won't let you escape values using quotes or the \
character, despite other places in the documentation maybe saying this is possible:
(Possibly non-existent) environment variables may be used in values using
the ${string} syntax and (possibly non-existent) PAM_ITEMs may be used in
values using the @{string} syntax. Both the $ and @ characters can be
backslash escaped to be used as literal values values can be delimited with ""
Or maybe not:
The file is made up of a list of rules, each rule is typically placed on a
single line, [...] Comments are preceded with `#´ marks and extend to the
next end of line.
Anyway, to get around this limitation, I moved my global environment variables into a file in /etc/profile.d
as discussed in this answer. I still consider this question unanswered, but I wanted to make sure there was a linked workaround for posterity.
There is no way in /etc/environment to escape the #(as it treated as a comment) as it is being parsed by he PAM module "pam_env" and it treats it as a simple list of KEY=VAL pairs and sets up the environment accordingly. It is not bash/shell, the parser has no language for doing variable expansion or characters escaping.