Persistently set the value of an environment variable for all users
|Debian (Etch, Lenny, Squeeze)|
|Ubuntu (Hardy, Intrepid, Jaunty, Karmic, Lucid, Maverick, Natty, Oneiric, Precise)|
To persistently set the value of an environment variable for all users
Environment variables are name-value pairs that can be used to communicate information from a process to its descendants. They are typically used to provide programs with information about the environment in which they are executing (hence the name). Notable ones include:
||the local or remote X Window display that should be used by default|
||the list of paths to search when looking for an executable|
||the current working directory|
||the terminal type|
||the default timezone|
Environment variables are inherited from parent to child when new processes are created. Processes can freely alter their own environment variables but not those of other processes. In particular, changes made by a child process do not propagate back to its parent.
Suppose that you want users on the local machine to direct HTTP requests via a proxy server listening on port 8080 of
proxy.example.com. This can be achieved for many (but not all) HTTP client programs by setting the environment variables
(The lower case variant
http_proxy is the more widely accepted form, and some HTTP clients accept either, but for maximum coverage it is better to set both.)
On most Linux-based systems, the first instance of the shell created following a user login will look for a file called
/etc/profile, and if it exists and is readable then it will execute the content of that file as shell script. Importantly it does this without spawning a child process, making
/etc/profile a suitable location for setting environment variables. Here is a typical example, with the required variable assignments placed at the end:
# /etc/profile: system-wide .profile file for the Bourne shell (sh(1)) # and Bourne compatible shells (bash(1), ksh(1), ash(1), ...). if [ "`id -u`" -eq 0 ]; then PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" else PATH="/usr/local/bin:/usr/bin:/bin:/usr/games" fi if [ "$PS1" ]; then if [ "$BASH" ]; then PS1='\u@\h:\w\$ ' else if [ "`id -u`" -eq 0 ]; then PS1='# ' else PS1='$ ' fi fi fi export PATH umask 022 export http_proxy='http://proxy.example.com:8080/' export HTTP_PROXY="$http_proxy"
Note that because of the manner in which this file is executed by the shell there is no need for it to begin with a shebang line (for example,
The value of
HTTP_PROXY has been defined in terms of
http_proxy so that changes can be made by editing one line rather than two. The use of single quotation marks in the first assignment causes interpolation to be suppressed, with the result that only single quotation marks within the URL need be escaped. The double quotation marks in the second assignment allow interpolation (which is wanted) but suppress tokenisation (which is not). In this particular example the quotation marks could be omitted because there are no special characters, but it is good practice to quote to protect against future changes.
The content of
/etc/profile is executed only when a login shell is created. One situation where this does not occur is when OpenSSH is used to execute a command non-interactively, for example:
ssh email@example.com 'env'
It is possible to work around this by explicitly creating a login shell as part of the remote command:
ssh firstname.lastname@example.org 'sh -l -c env'
Similar considerations apply when executing commands using
sudo, even if you start an interactive shell using the
-s option. To obtain a login shell you can use the
-i option instead.
Command run from a crontab do not execute within a login shell. As with
ssh you can work around this by explicitly creating a login shell:
* * * * * sh -l -c /home/user/myscript.pl
Some versions of LTSP (the Linux Terminal Server Project) create sessions without creating a login shell, therefore
/etc/profile is not executed. The suggested workaround is to use
/etc/bash.bashrc, which is not entirely satisfactory for the reasons discussed below.
This is not an exhausive list of ways in which
/etc/profile can be bypassed, and it would be unwise to rely on the method described here without first testing it under the particular set of circumstances in which it will be used.
You can check that the environment variable has been exported with the intended value by inspecting it from within a new login shell. The login shell can be created using the
-l option of the
sh command. The value can be inspected using the
printenv command if it is available:
sh -l -c 'printenv http_proxy'
printf command if not:
sh -l -c 'printf "%s\n" "$http_proxy"'
On systems that use the
pam_env PAM module (which most general-purpose Linux-based systems do), the file
/etc/environment can be used to set environment variables during login. It should contain a list of name-value pairs, one per line with an equals sign between each name and value. It is not interpreted as a shell script. To set the
HTTP_PROXY variables as described above, suitable content would be:
/etc/profile there are some circumstances where this file is not used, but there are differences as to what those circumstances are. For example:
- commands run non-interactively using OpenSSH will see variables from
/etc/environmentbut not from
- interactive OpenSSH sessions run through a server with the
UsePAMoption set to
nowill typically see variables from
/etc/profilebut not from
/etc/environment is not required by the LSB (as of version 4.1), but support is widespread and not restricted to Linux-based systems. Generally it is a reasonable alternative to
/etc/profile on systems that support it.
/etc/bash.bashrc is executed at startup by most interactive instances of the Bash shell that are not login shells.
This makes it potentially useful for filling gaps in the coverage of
/etc/profile. Points to bear in mind:
- This configuration file is specific to Bash and will not work if the user has chosen to use a different shell.
- Rather than merely providing a default value for an environment variable at the start of a session,
/etc/bash.bashrchas the potential to override assignments made by the user during a session.
Some non-POSIX compatible shells lack support for the combined assignment and export command used above and instead require that these two operations be performed separately, for example:
http_proxy="http://proxy.example.com:8080/" ; export http_proxy
Scripts that use the combined form are acceptably portable for most purposes, it being reasonable to assume that the default shell is POSIX-compatible, but if you want to support the widest possible range of execution environments then there is some benefit in using separate commands.