Apache, PHP, and environment variables

Environment variables in Apache/PHP can be tricky, especially when PHP code running in mod_php calls a command-line PHP script.

Apache has its own “environment variables”, which can be set via the httpd configuration directive SetEnv. But these are not environment variables in the standard Linux sense. They will not be passed to child processes invoked with backticks, system(), shell_exec(), etc.

To a PHP script, they can sometimes look interchangeable, because php’s getenv() function will first try to get a value from the SAPI (which gets the apache environment variable) before falling through to check the system’s environment variables.

So if you have SetEnv foo=1 in your apache config, calling getenv('foo') from PHP code running in mod_php will return 1 (it gets it from the apache “environment variables”).

And if you add foo=1 to /etc/environment, then calling getenv('foo') from a PHP script launched at the command line (or via cron) will return 1 (it gets it from the system environment variables). But note that the mod_php code does *not* have a “real” system environment variable set, despite the fact that it’s in /etc/environment (for security reasons, system environment variables are not available by default inside of apache). There are no system environment variables to pass down to child processes. Further, when a subprocess is called from mod_php, the variables in /etc/environment are not loaded in. The shell it runs in is very bare-bones. So if code in mod_php calls a command-line PHP script, a call to getenv('foo') in that script will return FALSE:

  • no system environment variables inherited (the mod_php code didn’t have any)
  • no apache “environment variables” available (the command-line script is a separate process with no access to the SAPI)
  • no system environment variables from /etc/environment (due to the bare-bones shell that is running)

Further confusing things is the $_ENV array, which is only populated if “E” appears in the variables_order directive in php.ini, which it typically does not on production servers.

To make an environment variable available to all PHP scripts, no matter whether they are running in mod_php, launched as CLI scripts from the command line or cron, or exec-ed as a standalone script from code running in mod_php, you should define the variable in two places:

  • /etc/environment, where standalone PHP scripts will get the environment variable
  • /etc/sysconfig/httpd (on RHEL/CentOS), where systemd will load environment variables when it starts apache, making them available to mod_php code as “real” environment variables

Leave a Reply

Your email address will not be published. Required fields are marked *