Когда php используется в качестве модуля apache , переменная среды, SetEnv директиву Apache SetEnv доступна для getenv() php, но, похоже, она недоступна для C расширений через getenv() stdlib. По крайней мере, это происходит с модулем pgsql .
Если переменная обновляется с помощью php-кода:
putenv("varname=".getenv("varname"));
то он становится доступным для кода расширения.
Вопрос: зачем нужна перестройка? Как отличная среда php отличается от «стандартной» ( stdlib ) среды?
Это происходит с: PHP Version 5.3.10-1ubuntu3.17 в Ubuntu 12.04, как модуль apache. При запуске из командной строки это обходное решение не требуется. Из этого другого вопроса: Использование .pgpass из Apache libphp5.so кажется, что это обходное решение также необходимо для php-5.4 под FreeBSD, поэтому это не просто Ubuntu или php-5.3.
Это не зависит от variables_order есть E Я пробовал как EGPCS , так и $_ENV , а $_ENV не заполняется, когда E не существует, как и ожидалось, но это не меняет результат getenv() , как задокументировано , или, по-видимому, результат getdv getenv() из stdlib внутренних расширений.
Демонстрация проблемы с модулем pgsql . Он построен поверх библиотеки libpq написанной на C , которая вызывает getenv() на нескольких необязательных переменных окружения PG* .
В файле конфигурации apache под <VirtualHost> я устанавливаю это, чтобы попытки подключения не выполнялись:
SetEnv PGHOST doesnotexist
и не указывая хост в вызове pg_connect , поэтому PGHOST следует принимать, когда он присутствует.
Первая попытка :
$v=getenv("PGHOST"); echo "PGHOST=$v\n"; $cnx=pg_connect("user=daniel"); if ($cnx) { echo "Connection is successful."; }
Результат:
PGHOST = doesnotexist Соединение выполнено успешно.
Поэтому PGHOST игнорируется, несмотря на то, что он находится в окружающей среде.
Вторая попытка , теперь снова PGHOST в среду, хотя она уже есть:
$v=getenv("PGHOST"); echo "PGHOST=$v\n"; putenv("PGHOST=".getenv("PGHOST")); $cnx=pg_connect("user=daniel"); if ($cnx) { echo "Connection is successful."; }
Результат (невозможность подключения к указанному хосту, как и ожидалось):
PGHOST = doesnotexist Предупреждение: pg_connect (): Не удается подключиться к серверу PostgreSQL: не удалось перевести имя хоста «donotexist» на адрес: Имя или услуга, неизвестные в /var/www/test/pgtest2.php в строке 8
Причина в том, что:
Значения среды, которые вы получаете от getenv()[PHP] (функция php), отличаются от среды, которую вы запрашиваете с помощью getenv()[C] (функция C lib). Что делает getenv()[PHP] , проверяет с зарегистрированным sapi на соответствие ( http://lxr.php.net/xref/PHP_5_6/ext/standard/basic_functions.c#3999 ).
Apache2 sapi делает это через свой собственный контекст среды ( http://lxr.php.net/xref/PHP_5_6/sapi/apache2handler/sapi_apache2.c#253 ), а не стандартную среду ОС из самого процесса apache.
ТОЛЬКО, когда нет совпадения, он будет проверять в среде фактического процесса. Вот почему getenv()[PHP] возвращает значение, но getenv()[C] этого не делает.
Теперь «хак» также прост: putenv()[PHP] , сохраняет заданный ключ / значение в среде запущенного процесса, поэтому его можно найти позже через getenv()[c] ,