Когда 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]
,