Description
Use case: You want to use Process
to launch a subprocess. The sub-process requires an extra environment variable (eg CHILDVAR=somevalue
), but any other environment variables (such as PATH
, TMPDIR
, SSH_AUTH_SOCK
, ad nauseum) should be passed-through without modification. In the contract for Process::__construct()
, the only way to pass a new variable is to append it to $_ENV
, e.g.
$p = new Process($command, $cwd, $_ENV + array("CHILDVAR"=>"somevalue"));
That is intuitive, but it does not work in Debian-based distros because it relies on $_ENV
. In Debian's PHP packages, the php.ini
sets variables_order=GPCS
which kills $_ENV
. (By contrast, upstream php.net
defaults to variables_order=EGPCS
which supports $_ENV
.). To see this in action, run this on any PHP CLI:
php -d variables_order=EGPCS -r 'print_r($_ENV);'
php -d variables_order=GPCS -r 'print_r($_ENV);'
A few ideas for resolving this problem -- none of which seem pretty:
- Downstream code should guard all references to
$_ENV
and generate warnings aboutvariables_order
. (Problem: That sucks for a large portion of the user community which runs on Debian/Ubuntu.) - Complain to debian.org, ubuntu.com, etal, and haggle with them about fixing the defaults. I suspect that they've confused
variables_order
with the inter-related optionrequest_order
. (Problem: Even if they agree to change it, there's a large install base on old/past releases.) - Complain to
php.net
and ask for an API that reliably provides all environment variables. (Problem: Install-base.) - Change the contract of
Process
to allow adding new variables. (Problem: Compatibility break?) - Distribute a new helper function/class to approximate
$_ENV
. E.g.
namespace Symfony\Process;
class Environment
{
/**
* Get a list of all environment variables.
*
* This is loosely equivalent to $_ENV; however, $_ENV does not work
* in some common configurations.
*
* @return array
* Example: $result['PATH'] === '/usr/local/bin:/usr/bin:/bin'
*/
public static function get()
{
// Wishful thinking: return $_ENV;
// Some systems -- such as Debian and Ubuntu -- disable $_ENV by
// default (by setting `variables_order=GPCS`), which makes it harder
// to write well-behaved CLI scripts which propagate the environment
// content.
// This is silly policy and most likely an accident of history --
// e.g. `variables_order` was introduced in PHP 5.0; the better
// alternative `request_order` didn't appear until PHP 5.3.
// Regardless, the information is still available -- getenv($key) can
// return values for specific variables, and `$_SERVER` contains an
// amalgamation of 'environment' and 'server' variables. To make an
// accurate(ish) list, we need to filter $_SERVER using getenv().
// See also: http://php.net/manual/en/ini.core.php#ini.variables-order
$env = array();
foreach (array_keys($_SERVER) as $key) {
$value = getenv($key);
if ($value !== null && $value !== false) {
$env[$key] = $value;
}
}
return $env;
}
}
print_r(Environment::get());