About environment variables
Environment variables are named values that affect how the system works. For example they tell the system where to look for commands (the PATH
variable) or where to look for libraries (LD_LIBRARY_PATH
). Their names are often in all-uppercase. Sometimes people refer to an environment variable with a dollar sign $
in front, but that's the same thing: when people say "the $PATH environment variable" they mean "the PATH environment variable". This is because the dollar sign $
is a shell syntax for refering to an environment variable, as you will learn later.
Environment variables are set on a per-process basis, but they are inherited by child processes. This means that if you set environment variables in process A, another already running process B will not see these new environment variables. But if A spawns a child process C, then C will have all environment variables that A had. If you once again change the environment variables in A, then C will not see the changes.
The per-process nature of environment variables some implications. When you set environment variables in your bashrc
or other bash startup files…
- …only newly spawned bash shells see them.
- …the web server usually does not see them, because the web server tends to be started from init scripts, not from bash.
- …cron jobs do not see them, because cron jobs' environment variables are entirely dictated by their crontabs.
Table of contents
- Loading...
Working with environment variables
You can see all environment variables in your shell by running the following command:
$ env
You can set an environment variable with the syntax export <NAME>=<VALUE>
. For example, to set the APXS2
variable to the value /usr/sbin/apxs2
:
$ export APXS2=/usr/sbin/apxs2
Any process that you run from your shell from that point on will have said environment variable:
$ export APXS2=/usr/sbin/apxs2 $ ruby -e 'p ENV["APXS2"]' /usr/sbin/apxs2
The "export" keyword is important
You must set the export
keyword. If you omit the export
keyword then the environment variable will not be visible to other processes:
$ APXS2=/usr/sbin/apxs2 $ ruby -e 'p ENV["APXS2"]' nil
You can reference an environment variable in your shell by typing the $
sign followed by the environment variable's name. For example, to see the value of the PATH
variable:
$ echo $PATH
You can also use this trick to extend the value of an environment variable:
$ export PATH=/usr/bin # Prepends '/opt/local/bin', so that it becomes /opt/local/bin:/usr/bin $ export PATH=/opt/local/bin:$PATH # Appends '/usr/local/bin', so that it becomes /opt/local/bin:/usr/bin:/usr/local/bin $ export PATH=$PATH:/usr/local/bin
The PATH environment variable
The PATH
environment variable dictates where the system looks for command. It is a colon-separated list of directories. If you get a "command not found" error while you know that the command is installed, then setting PATH
will help. For example suppose that the command frobnicator
is in /opt/local/bin
:
user@localhost bash$ frobnicator bash: frobnicator: command not found
We verify that /opt/local/bin
is not in PATH
:
user@localhost bash$ echo $PATH /bin:/usr/bin:/usr/local/bin
We can run frobnicator
through it's full path…
user@localhost bash$ /opt/local/bin/frobnicator => success!
…or we can add /opt/local/bin
to PATH
.
user@localhost bash$ export PATH=$PATH:/opt/local/bin user@localhost bash$ frobnicator => success!
Adding Passenger's administration tools to PATH
If you get a "command not found" error when invoking one of the Passenger administration tools (e.g. passenger-status
or passenger-memory-stats
then that means the tools are not in PATH
, so you need to add them.
-
If you installed Passenger with RubyGems, then the tools are in your RubyGems executable path. You can view the gem path using the command
gem env
:$ gem env RubyGems Environment: - RUBYGEMS VERSION: 2.2.1 - RUBY VERSION: 1.9.3 (2014-05-14 patchlevel 547) [x86_64-darwin13.4.0] - INSTALLATION DIRECTORY: /Users/hongli/.rvm/gems/ruby-1.9.3-p547 - RUBY EXECUTABLE: /Users/hongli/.rvm/rubies/ruby-1.9.3-p547/bin/ruby - EXECUTABLE DIRECTORY: /Users/hongli/.rvm/gems/ruby-1.9.3-p547/bin !! - RUBYGEMS PLATFORMS: - ruby - x86-darwin-10 - GEM PATHS: - /opt/ruby-enterprise-1.8.7-2010.01/lib/ruby/gems/1.8 - /Users/hongli/.gem/ruby/1.8 - GEM CONFIGURATION: - :update_sources => true - :verbose => true - :benchmark => false - :backtrace => false - :bulk_threshold => 1000 - "gem" => "--no-ri --no-rdoc" - REMOTE SOURCES: - http://rubygems.org/
As you can see, the RubyGems executable path in the example happens to be
/opt/ruby-enterprise-1.8.7-2010.01/bin
. So that directory must be added toPATH
. - If you installed Passenger using the tarball, then the tools are in the
bin
subdirectory of the Passenger tarball directory that you extracted. For example, if you extractedpassenger-5.0.0.tar.gz
inside/opt
, then the tools are located in/opt/passenger-5.0.0/bin
. In that case, you need to add/opt/passenger-5.0.0/bin
to yourPATH
. - If you installed Passenger through APT or YUM, then some Passenger administration tools are in
/usr/bin
, while others are in/usr/sbin
. If you are not logged in as root, then/usr/sbin
may not be inPATH
, which would explain why you get a "command not found" when trying to invoke some of the tools. You should add/usr/sbin
toPATH
. -
If you are unsure where your Passenger directory is then you can use the
find
command to look them up. Go to the root directory and invokefind
withsudo
:$ cd / $ sudo find . -name passenger-status /usr/local/passenger/bin/passenger-status
In this example, the administration tools happen to be in
/usr/local/passenger/bin
, so you must add that toPATH
.
PATH
. Please read Environment variables and sudo to learn more.
Making environment variables permanent
When you exit your shell, the environment variable changes are lost. There is no standard method to set environment variables system-wide, so you have to set them in different configuration files for different services.
bash
To make environment variables permanent for future bash sessions for the current user, add them to your ~/.bashrc
:
$ echo 'export FOO=bar' >> ~/.bashrc $ echo 'export PATH=/usr/local/bin:$PATH' >> ~/.bashrc
To make them permanent for future bash sessions for all users, add them to /etc/bashrc
.
/etc/bash.bashrc
.
~/.bashrc
is actually included by your ~/.profile
, which might not be the case if you created the user with useradd
instead of adduser
for example
Apache
On Debian and Ubuntu, with an Apache installed through apt, Apache environment variables are defined in the file /etc/apache2/envvars
. This is a shell script so environment variables must be specified with the shell syntax.
On Red Hat, CentOS, Rocky, Alma, Fedora, and Scientific Linux, with an Apache installed through YUM, Apache environment variables are defined in /etc/sysconfig/httpd
.
On macOS they are defined in /usr/sbin/envvars
and /System/Library/LaunchDaemons/org.apache.httpd.plist
, as explained here on Stack Overflow. As of macOS 10.11 you must temporarily disable SIP to edit these files as explained here on Stack Overflow.
On other systems, or if you did not install Apache through the system's package manager, the configuration file for environment variables is specific to the vendor that supplied Apache. There may not even be such a configuration file. You should contact the vendor for support.
Nginx
If you installed Nginx through the Debian or Ubuntu packages, then you can define environment variables in /etc/default/nginx
. This is a shell script so you must use the export FOO=bar
syntax.
Otherwise, environment variables are best set through the script which starts Nginx. For example, if you installed Nginx from source and you used the Nginx init script described here then you should edit that script to define the environment variables. Those init scripts are regular shell scripts, so use the export FOO=bar
syntax. Just make sure your set your environment variables before the script starts Nginx.
cron
To make environment variables permanent for cron jobs, add those variables to the relevant crontab. But note that inside crontabs you cannot refer to existing environment variables with the $
syntax because crontabs are not shell scripts. You have to specify the entire value.
# Environment variable definitions
FOO=bar
APXS2=/usr/sbin/apxs2
# **WRONG!** You cannot refer to existing variables with the `$` syntax!
PATH=/usr/bin:$PATH
# **WRONG!** You cannot use the 'export' keyword!
export PATH=/usr/bin:/usr/local/bin
# Correct:
PATH=/usr/bin:/usr/local/bin
# Jobs:
# m h dom mon dow command
* * * * * frobnicator
Passenger-served apps
You can pass environment variables to Passenger-served apps through various methods:
- When using Passenger + Apache, use the
PassEnv
andSetEnv
options of mod_env. This is supported starting from Passenger 4.0. - When using Passenger + Nginx, use the passenger_env_var option.
- When using Passenger Standalone, use the
--envvar
/ "envvars" option. - Through your
bashrc
. Starting from version 4.0, Passenger 4.0 spawns applications through bash and inherit all bash environment variables. Passenger Standalone tends to be started from the shell and thus inherits all environment variables set by the shell. - Through Apache and Nginx, as described earlier in this chapter. Any environment variables that you set on Apache and Nginx itself are inherited by Passenger, and thus by Passenger-served apps as well.
-
Through the application itself. Most programming languages provide APIs for setting environment variables. For example in Ruby you can write:
ENV['FOO'] = 'bar'
In Python you can write:
import os os.environ['FOO'] = 'bar'
Environment variables and sudo
rvmsudo
command instead of sudo
. However all information in this section applies to rvmsudo
as well.
The sudo
command resets all environment variables before running the specified command. This is done for security reasons. This means that if you set environment variables before running sudo passenger-install-xxx-module
, sudo passenger-status
or any other commands, then the environment variables are not correctly passed to the command.
Here is an example which demonstrates the problem. As you can see, the sh
command which we run through sudo does not see the environment variable.
user@localhost bash$ export MY_VAR=my_value user@localhost bash$ sudo sh -c 'echo MY_VAR is: $MY_VAR' MY_VAR is:
You can solve this problem by running sudo with -E
. This tells sudo to preserve environment variables (except for PATH
; read on to learn more). Here are two example usages:
# Example 1 user@localhost bash$ export MY_VAR=my_value user@localhost bash$ sudo -E sh -c 'echo MY_VAR is: $MY_VAR' MY_VAR is: my_value # Example 2 user@localhost bash$ export APXS2=/usr/sbin/apxs2 user@localhost bash$ sudo -E passenger-install-apache2-module
Alternatively, you can obtain a root prompt with sudo first, and then set the environment variables, before running any further commands:
$ user@localhost bash$ sudo -s Password: ... root@localhost bash# export APXS2=/usr/sbin/apxs2 root@localhost bash# passenger-install-apache2-module
Note that for security reasons, sudo
always resets the PATH
environment variable, even if you pass -E
! You can get around this problem by obtaining a root prompt first, and then set the environment variables:
user@localhost bash$ sudo -s Password: ... root@localhost bash# export PATH=$PATH:/opt/myruby/bin root@localhost bash# passenger-install-apache2-module