12

I want to know the exact syntax for /etc/environment. I know it's not an ordinary shell script, but how exactly are single and double quotes processed?

Can environment variables defined earlier in the file be used to define later variables?

How does escaping work? What happens if there are spaces in the value?

Also - when is the file processed? Conflicting information online says it's processed at system startup, at each user login, or both.

I've been unable to find these details online; can anyone point me at authoritative documentation?

If it matters, I'm specifically interested in Ubuntu (Debian).

nerdfever.com
  • 303
  • 1
  • 3
  • 7

3 Answers3

25

It's curious enough that I've tested it before. The behaviour is somewhat... weird.

These settings in /etc/environment:

FOO1=bar
FOO2="bar"
FOO3="bar
FOO4=bar"
FOO5='bar'
FOO6='bar"
export FOO7=bar
FOO8=bar bar bar
#FOO9=bar
FOO10=$PATH
FOO11="foo#bar"

give these envvars:

FOO1=bar
FOO2=bar
FOO3=bar
FOO4=bar"
FOO5=bar
FOO6=bar
FOO7=bar
FOO8=bar bar bar
FOO10=$PATH
FOO11=foo

In other words:

  • it skips a leading export (7)
  • if the value starts with a single or double quote, it removes it and any trailing single or double quote. (2, 5)
  • ... but it doesn't mind if the quotes don't match, or if the final quote is missing (3, 6)
  • it doesn't treat whitespace specially, even in the absence of quotes (8)
  • ... not even trailing whitespace, which is hard to show here, but which I did also test (8)
  • it ignores lines that start with a # (9)
  • ... and cuts the lines at a #, even if it's in between quotes (11)
  • it doesn't support variable expansion (10)

It's read by pam_env.so, so you'd expect it documented in the pam_env manpage, or the environment man page, but they mention nothing of the treatment of quotes. Apart from testing, you'd have to parse the behaviour from the code larsks's answer linked to.

I suppose it tries to be accepting of assignments you'd put in your shell's startup files, so that something like export FOO="bar bar" does the same in both (provided you don't have any trailing spaces there). It's just that the syntax for /etc/environment is far simpler (to the point of stupidity, IMO).

/etc/environment also doesn't support variable expansions or such. As above, $PATH in the file ends up as literal $PATH in the value, not a list of directories.

The man pages linked above also describe pam_env.conf, which has a richer syntax and allows variable expansion. It's still not the shell syntax, though.

Related:

ilkkachu
  • 138,973
17

The /etc/environment file is read by pam_env.Unfortunately, the official documentation isn't terribly explicit about the format; it says:

The syntax are simple KEY=VAL pairs on separate lines. The export instruction can be specified for bash compatibility, but will be ignored. This can be useful when different services need different environments.

If you're really curious, the actual parsing logic can be found in the _parse_env_file function in the PAM sources. Specifically:

  /* now we try to be smart about quotes around the value,
     but not too smart, we can't get all fancy with escaped
     values like bash */
    if (key[i] == '=' && (key[++i] == '\"' || key[i] == '\'')) {
        for ( t = i+1 ; key[t] != '\0' ; t++)
            if (key[t] != '\"' && key[t] != '\'')
                key[i++] = key[t];
            else if (key[t+1] != '\0')
                key[i++] = key[t];
        key[i] = '\0';
    }
ilkkachu
  • 138,973
larsks
  • 34,737
-1

I'll try to answer your second, fourth, and fifth questions.

The documentation for this file is in the man page (man 5 pam_env.conf).

/etc/environment is read after pam_env.conf, and the man 5 pam_env.conf says this file is read at user login.

Basically, only key=value lines in the /etc/environment file. The man page states that you can use the file /etc/security/pam_env.conf to set environment variables by using other, possibly non-existent variables.

From the man page, regarding /etc/security/pam_env.conf:

Each line starts with the variable name, there are then two possible options for each variable DEFAULT and OVERRIDE. DEFAULT allows an administrator to set the value of the variable to some default value, if none is supplied then the empty string is assumed. The OVERRIDE option tells pam_env that it should enter in its value (overriding the default value) if there is one to use. When OVERRIDE is not used, "" is assumed and no override will be done.

VARIABLE [DEFAULT=[value]] [OVERRIDE=[value]]

(Possibly non-existent) environment variables may be used in values using the ${string} syntax and (possibly non-existent) PAM_ITEMs as well as HOME and SHELL 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 "", escaped " not supported. Note that many environment variables that you would like to use may not be set by the time the module is called. For example, ${HOME} is used below several times, but many PAM applications don't make it available by the time you need it. The special variables @{HOME} and @{SHELL} are expanded to the values for the user from his passwd entry.

The /etc/environment file specifies the environment variables to be set. The file must consist of simple NAME=VALUE pairs on separate lines. The pam_env(8) module will read the file after the pam_env.conf file.

You can also use your shell's (bash or zsh for example) configuration file or to set environment variables like that.