I have the following executable python script:
#!/usr/bin/python
import os
print os.environ
when I execute it from the command line as root, I get the following:
{
'LANG': 'en_US.UTF-8',
'TERM': 'xterm-256color',
'SHELL': '/bin/bash',
'LESSCLOSE': '/usr/bin/lesspipe %s %s',
'LANGUAGE': 'en_US:en',
'SHLVL': '1',
'SSH_TTY': '/dev/pts/0',
'OLDPWD': '/var/www/bais-mordechai-laravel',
'COMP_WORDBREAKS': ' \t\n"\'><;|&(:',
'PWD': '/var/www/bais-mordechai-laravel/public',
'LESSOPEN': '| /usr/bin/lesspipe %s',
'SSH_CLIENT': '71.205.188.8 56489 22',
'LOGNAME': 'root',
'USER': 'root',
'PATH': '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games',
'MAIL': '/var/mail/root',
'LS_COLORS':'...',
'HOME': '/root',
'_': './pythontest',
'SSH_CONNECTION': '...'
}
But when I run this from a php script (running on nginx server) and echo back the result I get:
{
'HOME': '/var/www',
'PWD': '/var/www/bais-mordechai-laravel/public',
'USER': 'www-data'
}
Why are they different? Specifically, how can I get the web version to include the 'PATH' variable?
For apache, see mod_setenv.
This module allows for control of internal environment variables that are used by various Apache HTTP Server modules. These variables are also provided to CGI scripts as native system environment variables, and available for use in SSI pages. Environment variables may be passed from the shell which invoked the httpd process. Alternatively, environment variables may be set or unset within the configuration process.
If you are using Apache's FCGId, see FcgidInitialEnv.
Use FcgidInitialEnv to define environment variables to pass to the FastCGI application. This directive can be used multiple times.
This setting will apply to all applications spawned for this server or virtual host. Use FcgidCmdOptions to apply this setting to a single application.
For Nginx CGI, see the env setting.
By default, nginx removes all environment variables inherited from its parent process except the TZ variable. This directive allows preserving some of the inherited variables, changing their values, or creating new environment variables.
If you are using NgxWSGIModule, see the wsgi_var setting.
Directive assigns the variable, which will be added to the
environment dictionary passed to the WSGI application.
It is possible to use strings, nginx variables and their
combination as values. Directives not set are inherited from the
outer level.
If you are running your application under (gunicorn|tornado|twisted|etc)+supervisord, see the environment directive.
A list of key/value pairs in the form KEY="val",KEY2="val2" that will be placed in the supervisord process’ environment (and as a result in all of its child process’ environments). This option can include the value %(here)s, which expands to the directory in which the supervisord configuration file was found. Values containing non-alphanumeric characters should be quoted (e.g. KEY="val:123",KEY2="val,456"). Otherwise, quoting the values is optional but recommended. Note that subprocesses will inherit the environment variables of the shell used to start supervisord except for the ones overridden here and within the program’s environment option.
If you are using something else, let me know.
You can always inject environment variables using os.environ - do it at the start of your (c|fc|ws)gi.py script. Se also sys.path:
sys.path.append('/usr/local/django')
Related
I am using PHP as PHP-FPM on Centos. I am trying to follow the http://12factor.net/ guidelines of having the settings be stored in environment variables.
I have created a file in /etc/profile.d that sets the environment variables I want, and the environment variables appear when tested in the CLI via Bash i.e. running the bash script:
echo $SOME_SERVER_SETTING
shows the correct output.
I have set the clear_env setting to false and variables_order to EGPCS, however, the variable I have set does not show up in PHP either getenv('SOME_SERVER_SETTING') or doing var_dump($_ENV)
What other setting needs to be set to allow PHP-FPM to receive all of the server environment variables, and in particular those set through a shell script in /etc/profiles.d on Centos?
Tested on Centos 7 with Systemd service and PHP 5.6.4
OPEN
/etc/php.ini
FIND
variables_order = "GPCS"
REPLACE TO
variables_order = "EGPCS"
# http://php.net/manual/en/ini.core.php#ini.variables-order
OPEN
/etc/php-fpm.d/www.conf (maybe /etc/php5/fpm/pool.d/www.conf)
(do not confuse with /etc/php-fpm.conf)
FIND IF EXIST
clear_env = yes
REPLACE TO OR ADD
clear_env = no
# http://php.net/manual/en/install.fpm.configuration.php
OPEN
/etc/environment
ADD
#any variables you need, for example:
MY_VAR=1234
RUN IN SHELL FOR CHECK
source /etc/environment
echo $MY_VAR # 1234
RUN IN SHELL
ln -fs /etc/environment /etc/sysconfig/php-fpm
systemctl daemon-reload && service php-fpm restart
...TESTING
OPEN
index.php # in your project folder, running with php-fpm
ADD
var_dump(getenv('MY_VAR'), $_ENV['MY_VAR']);exit;
RUN IN BROWSER
http://mylink.to.project/index.php
string(4) "1234"
string(4) "1234"
ENJOY!
Security reasons :-)
See /etc/php5/fpm/pool.d/www.conf (debian location, may be different on CentOs)
; Clear environment in FPM workers
; Prevents arbitrary environment variables from reaching FPM worker processes
; by clearing the environment in workers before env vars specified in this
; pool configuration are added.
; Setting to "no" will make all environment variables available to PHP code
; via getenv(), $_ENV and $_SERVER.
; Default Value: yes
;clear_env = no
; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from
; the current environment.
; Default Value: clean env
;env[HOSTNAME] = $HOSTNAME
;env[PATH] = /usr/local/bin:/usr/bin:/bin
;env[TMP] = /tmp
;env[TMPDIR] = /tmp
;env[TEMP] = /tmp
Environment variables in a FastCGI setup are set as input by the client of the FPM process, for instance NginX. They are sent as headers to the FastCGI server, which interprets them and sets them accordingly for you to read out with getenv.
If you are in fact using NginX, look for the fastcgi_param directives. You can also set environment variables in your pool config of php5-fpm, depending on your use case.
You need to read the environment variables from the correct location. PHP creates a super global variable for this: $_ENV So you can access a single variable by accessing a certain element from that variable, which holds an array: echo $_ENV['SOME_SERVER_SETTING'];
I have no idea why your example above should work on CLI. The super global variable is the documented location and works.
What might be your issue here is that the variables are not set for the http server process. Typically scripts like those in /etc/profile.d are executed at login time. So when a user creates a session inside the system. But that will never happen for an http server started as a system server. No login is performed, no profile script is executed, no environment variables are set.
To solve this you can
set the environment variables inside the startup script of the service
set the variables inside the host configuration or .htaccess style files
auto-prepend a script setting the variables
When php is used as an apache module, an environment variable coming from an apache SetEnv directive is available to php's getenv(), but it does not appear to be available to C extensions through stdlib's getenv(). At least it happens with the pgsql module.
If the variable is reinstantiated with the php code:
putenv("varname=".getenv("varname"));
then it becomes available to the extension's code.
The question: why is that reinstantiation necessary? How is the core php environment distinct from the "standard" (stdlib) environment?
This occurs with: PHP Version 5.3.10-1ubuntu3.17 in Ubuntu 12.04, as an apache module. When run from the command line, the above workaround is not necessary.
From this other question: Using .pgpass from Apache libphp5.so it appears that this workaround is also necessary for php-5.4 under FreeBSD so it's not just Ubuntu or php-5.3.
It doesn't depend on variables_order having E in it. I've tried both EGPCS and GPCS, and $_ENV is not populated when E is not there, as expected, but that doesn't change the result of getenv(), as documented, or apparently the result of stdlib's getenv() from inside extensions.
Demo of the problem with the pgsql module. It's built on top of the libpq shared library written in C, which calls getenv() on a handful of optional PG* environment variables.
In apache configuration file, under a <VirtualHost>, I'm setting this to make connection attempts fail:
SetEnv PGHOST doesnotexist
and not specifying a host in the pg_connect call, so PGHOST must be taken when present.
First try:
$v=getenv("PGHOST");
echo "PGHOST=$v\n";
$cnx=pg_connect("user=daniel");
if ($cnx) {
echo "Connection is successful.";
}
Result:
PGHOST=doesnotexist
Connection is successful.
So PGHOST is getting ignored, despite being in the environment.
Second try, now putting again PGHOST into the environment even though it's already there:
$v=getenv("PGHOST");
echo "PGHOST=$v\n";
putenv("PGHOST=".getenv("PGHOST"));
$cnx=pg_connect("user=daniel");
if ($cnx) {
echo "Connection is successful.";
}
Result (failure to connect to the specified host, as expected):
PGHOST=doesnotexist
Warning: pg_connect(): Unable to connect to PostgreSQL server:
could not translate host name "doesnotexist" to address:
Name or service not known in /var/www/test/pgtest2.php on line 8
The reason is this:
The environment values you get from getenv()[PHP] (the php function) are different than the environment you query with getenv()[C] (the C lib function). What getenv()[PHP] does, is checking with the registered sapi for a match (http://lxr.php.net/xref/PHP_5_6/ext/standard/basic_functions.c#3999).
The apache2 sapi does this through its own environment context (http://lxr.php.net/xref/PHP_5_6/sapi/apache2handler/sapi_apache2.c#253), not the standard OS environment from the apache process itself.
ONLY when there is no match found, it will check at the environment of the actual process. So this is why getenv()[PHP] returns a value, but getenv()[C] does not.
Now, the "hack" is a simple one as well: putenv()[PHP], stores the given key/value in the environment of the running process, which is why it can be found later on by getenv()[c].
I'm running Apache/2.2.11 (Win32) PHP/5.3.0 and I did the following in my .htaccess file:
SetEnv FOO bar
If I print out the $_ENV variable in a PHP file, I get an empty array. Why doesn't my environment variable appear there? Why is it empty in the first place?
I did find my variable though, but it appears in the $_SERVER variable. And for some reason it appears twice, sort of. Why is this?
[REDIRECT_FOO] => bar
[FOO] => bar
It appears I can get it using getenv('FOO'), so maybe I should just use that instead. But I am still a bit curious to what causes this. Is this a Windows issue? Or what is going on?
Turns out there was two issues here:
1. $_ENV is only populated if php.ini allows it, which it doesn't seem to do by default, at least not in the default WAMP server installation.
; This directive determines which super global arrays are registered when PHP
; starts up. If the register_globals directive is enabled, it also determines
; what order variables are populated into the global space. G,P,C,E & S are
; abbreviations for the following respective super globals: GET, POST, COOKIE,
; ENV and SERVER. There is a performance penalty paid for the registration of
; these arrays and because ENV is not as commonly used as the others, ENV is
; is not recommended on productions servers. You can still get access to
; the environment variables through getenv() should you need to.
; Default Value: "EGPCS"
; Development Value: "GPCS"
; Production Value: "GPCS";
; http://php.net/variables-order
variables_order = "GPCS"
When I set the variables_order back to EGPCS, $_ENV is no longer empty.
2. When you use SetEnv in your .htaccess, it ends up in $_SERVER, not in $_ENV, which I gotta say is a tad confusing when it's named SetEnv...
# .htaccess
SetEnv ENV dev
SetEnv BASE /ssl/
# php
var_dump($_SERVER['ENV'], $_SERVER['BASE']);
// string 'dev' (length=3)
// string '/ssl/' (length=5)
3. The getenv function will always work and is not affected by the PHP setting for $_ENV Additionally it seems to do so insensitive to case, which might be useful.
var_dump(getenv('os'), getenv('env'));
// string 'Windows_NT' (length=10)
// string 'dev' (length=3)
$_ENV variables are imported from the environment under which PHP is running, and depending on your setup (the OS, your server, whether PHP runs as an Apache module or under FastCGI, etc.), this can vary greatly.
IIRC in a standard Apache+mod_php install on Windows, the only way to change variables in $_ENV is to change Windows' environment variables (see this). This can be significant when dealing with PHP extensions on Windows, because some of them (eg: php_ldap) are only configurable through environment vars on $_ENV.
REDIRECT_* variables appear if you are using RewriteRules. On my server they also appear just so. It might have something to do with running under FastCGI. And if combined with suexec, that's most likely to clean up the complete environment var pool. There might be additional configuration necessary to get them back, PassEnv particularily. As to why getenv() works for you, I have no clue. But all phenomena are specific to your server and php configuration. Ask on serverfault, they should know.
I'm running Apache/2.2.11 (Win32) PHP/5.3.0 and I did the following in my .htaccess file:
SetEnv FOO bar
If I print out the $_ENV variable in a PHP file, I get an empty array. Why doesn't my environment variable appear there? Why is it empty in the first place?
I did find my variable though, but it appears in the $_SERVER variable. And for some reason it appears twice, sort of. Why is this?
[REDIRECT_FOO] => bar
[FOO] => bar
It appears I can get it using getenv('FOO'), so maybe I should just use that instead. But I am still a bit curious to what causes this. Is this a Windows issue? Or what is going on?
Turns out there was two issues here:
1. $_ENV is only populated if php.ini allows it, which it doesn't seem to do by default, at least not in the default WAMP server installation.
; This directive determines which super global arrays are registered when PHP
; starts up. If the register_globals directive is enabled, it also determines
; what order variables are populated into the global space. G,P,C,E & S are
; abbreviations for the following respective super globals: GET, POST, COOKIE,
; ENV and SERVER. There is a performance penalty paid for the registration of
; these arrays and because ENV is not as commonly used as the others, ENV is
; is not recommended on productions servers. You can still get access to
; the environment variables through getenv() should you need to.
; Default Value: "EGPCS"
; Development Value: "GPCS"
; Production Value: "GPCS";
; http://php.net/variables-order
variables_order = "GPCS"
When I set the variables_order back to EGPCS, $_ENV is no longer empty.
2. When you use SetEnv in your .htaccess, it ends up in $_SERVER, not in $_ENV, which I gotta say is a tad confusing when it's named SetEnv...
# .htaccess
SetEnv ENV dev
SetEnv BASE /ssl/
# php
var_dump($_SERVER['ENV'], $_SERVER['BASE']);
// string 'dev' (length=3)
// string '/ssl/' (length=5)
3. The getenv function will always work and is not affected by the PHP setting for $_ENV Additionally it seems to do so insensitive to case, which might be useful.
var_dump(getenv('os'), getenv('env'));
// string 'Windows_NT' (length=10)
// string 'dev' (length=3)
$_ENV variables are imported from the environment under which PHP is running, and depending on your setup (the OS, your server, whether PHP runs as an Apache module or under FastCGI, etc.), this can vary greatly.
IIRC in a standard Apache+mod_php install on Windows, the only way to change variables in $_ENV is to change Windows' environment variables (see this). This can be significant when dealing with PHP extensions on Windows, because some of them (eg: php_ldap) are only configurable through environment vars on $_ENV.
REDIRECT_* variables appear if you are using RewriteRules. On my server they also appear just so. It might have something to do with running under FastCGI. And if combined with suexec, that's most likely to clean up the complete environment var pool. There might be additional configuration necessary to get them back, PassEnv particularily. As to why getenv() works for you, I have no clue. But all phenomena are specific to your server and php configuration. Ask on serverfault, they should know.
I'm running Apache/2.2.11 (Win32) PHP/5.3.0 and I did the following in my .htaccess file:
SetEnv FOO bar
If I print out the $_ENV variable in a PHP file, I get an empty array. Why doesn't my environment variable appear there? Why is it empty in the first place?
I did find my variable though, but it appears in the $_SERVER variable. And for some reason it appears twice, sort of. Why is this?
[REDIRECT_FOO] => bar
[FOO] => bar
It appears I can get it using getenv('FOO'), so maybe I should just use that instead. But I am still a bit curious to what causes this. Is this a Windows issue? Or what is going on?
Turns out there was two issues here:
1. $_ENV is only populated if php.ini allows it, which it doesn't seem to do by default, at least not in the default WAMP server installation.
; This directive determines which super global arrays are registered when PHP
; starts up. If the register_globals directive is enabled, it also determines
; what order variables are populated into the global space. G,P,C,E & S are
; abbreviations for the following respective super globals: GET, POST, COOKIE,
; ENV and SERVER. There is a performance penalty paid for the registration of
; these arrays and because ENV is not as commonly used as the others, ENV is
; is not recommended on productions servers. You can still get access to
; the environment variables through getenv() should you need to.
; Default Value: "EGPCS"
; Development Value: "GPCS"
; Production Value: "GPCS";
; http://php.net/variables-order
variables_order = "GPCS"
When I set the variables_order back to EGPCS, $_ENV is no longer empty.
2. When you use SetEnv in your .htaccess, it ends up in $_SERVER, not in $_ENV, which I gotta say is a tad confusing when it's named SetEnv...
# .htaccess
SetEnv ENV dev
SetEnv BASE /ssl/
# php
var_dump($_SERVER['ENV'], $_SERVER['BASE']);
// string 'dev' (length=3)
// string '/ssl/' (length=5)
3. The getenv function will always work and is not affected by the PHP setting for $_ENV Additionally it seems to do so insensitive to case, which might be useful.
var_dump(getenv('os'), getenv('env'));
// string 'Windows_NT' (length=10)
// string 'dev' (length=3)
$_ENV variables are imported from the environment under which PHP is running, and depending on your setup (the OS, your server, whether PHP runs as an Apache module or under FastCGI, etc.), this can vary greatly.
IIRC in a standard Apache+mod_php install on Windows, the only way to change variables in $_ENV is to change Windows' environment variables (see this). This can be significant when dealing with PHP extensions on Windows, because some of them (eg: php_ldap) are only configurable through environment vars on $_ENV.
REDIRECT_* variables appear if you are using RewriteRules. On my server they also appear just so. It might have something to do with running under FastCGI. And if combined with suexec, that's most likely to clean up the complete environment var pool. There might be additional configuration necessary to get them back, PassEnv particularily. As to why getenv() works for you, I have no clue. But all phenomena are specific to your server and php configuration. Ask on serverfault, they should know.