Вопрос или проблема
Я определил некоторые переменные окружения, такие как APP_ENV
, в своем файле /etc/environment
на ArchLinux.
Если я ввожу printenv
, я вижу их.
Я создал этот простой тестовый файл с названием… test.php
<?php
var_dump(getenv('APP_ENV'));
var_dump(getenv());
Если я запускаю php test.php
, все в порядке, я вижу свои переменные среды.
Но когда я пытаюсь получить доступ к файлу через HTTP… ничего нет в моей среде!
Конечно, я изменил конфигурацию /etc/php/php-fpm.d/www.conf
, чтобы установить clear_env = no
Вот затронутые строки:
; Очистка окружения в рабочих процессах FPM
; Предотвращает случайное попадание переменных окружения в рабочие процессы FPM
; очищая окружение в рабочих процессах перед добавлением переменных окружения,
; указанных в конфигурации пула.
; Установив "no", вы сделаете все переменные окружения доступными для PHP
; через getenv(), $_ENV и $_SERVER.
; Значение по умолчанию: да
clear_env = no
И я перезапустил службы php-fpm
и nginx
, но… все равно ничего в моей среде. Скрипт возвращает bool(false)
.
Так что… Я что-то упускаю?
Это моя версия php-fpm:
php-fpm --version
PHP 7.2.6 (fpm-fcgi) (built: May 26 2018 07:45:18)
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
И моя версия Nginx
nginx -v
nginx version: nginx/1.14.0
Что я должен сделать, чтобы получить доступ к переменным окружения в контексте PHP-FPM?
Большое спасибо!
Вы можете установить переменную окружения в /etc/php/php-fpm.d/www.conf следующим образом:
env[APP_ENV] = development
Тогда вы сможете получить её с помощью getenv('APP_ENV')
, как и ожидалось.
Когда вы вводите printenv или php test.php, вы видите переменные окружения, потому что они существуют.
Когда вы “пытаетесь получить доступ к файлу через HTTP… в [вашей] среде ничего нет”. Именно, ваши переменные окружения не установлены.
Почему вы ожидаете другого поведения? Файлы, такие как /etc/environment, /etc/profile и /etc/bashrc, загружаются только при использовании оболочки, а не при запуске демона.
Возможное решение — создать PHP файл, например, такой:
<? $_SERVER['APP_ENV']='dev';
где-то на диске и подключить его через настройку auto_prepend_file
в php.ini.
Не очень чисто, но это может помочь избежать хранения секретов в конфигурации php-fpm…
Обоснование:
кажется, что документация PHP для конфигурации fpm не очень ясно объясняет, как должны работать clear_env
и env
в конфигурационном файле пула.
На моем опыте:
- переменные окружения, которые будут доступны рабочим процессам, когда
clear_env = no
, это те, которые определены для пользователя в пуле, который обычно не является пользователем root - определение переменных окружения для этого пользователя в таких местах, как .bashrc, не сработает, поскольку рабочие процессы не считывают те же скрипты конфигурации среды, что и оболочка
- кажется, что, в зависимости от того, как php-fpm фактически запускается (с помощью скрипта init.d / systemd / прямого вызова исполняемого файла, например, через пользовательскую Docker CMD), переменные окружения могут или не могут отображаться
К тому же, очень сложно заставить документированный синтаксис env[APP_ENV] = $APP_ENV
работать, так что единственный способ сделать значение видимым — это жестко закодировать его в конфигурации пула fpm. Но это может быть не лучшим решением для всех сценариев
Я разработал что-то в своей производственной среде, что должно сработать. Это расширение использования конфигурационных файлов php-fpm для добавления переменных окружения. Вы можете встроить переменные среды в этот конфигурационный файл, поэтому вместо непосредственного размещения секретов в конфигурационном файле php-fpm, он действует как фильтр.
[www]
env[HOSTNAME] = ${HOSTNAME}
env[MODE] = ${MODE}
php_admin_value[error_log] = /path/to/logs/PHP-${HOSTNAME}-error.log
.
Ответ или решение
Для получения переменных окружения в контексте PHP-FPM с Nginx на ArchLinux необходимо понимать, как функционирует обработка переменных окружения в различных сценариях. Из-за этого возникает различие между командной строкой и серверным окружением.
Теория
Переменные окружения на системах Unix обычно устанавливаются в файлах, таких как /etc/environment
, /etc/profile
, или других скриптах инициализации. Эти файлы инициализации выполняются при запуске интерактивного сеанса оболочки, но не применяются непосредственно к процессам демонов. PHP, запущенный через Nginx и PHP-FPM в веб-контексте, работает именно как такой демон. Следовательно, переменные окружения, определённые в /etc/environment
, не передаются автоматически PHP-FPM, когда он запускается через сервисные системы, такие как systemd.
Пример
Вы столкнулись с ситуацией, когда переменные окружения видны при выполнении php test.php
в командной строке, но отсутствуют при доступе к тому же скрипту через HTTP. Это связано с тем, что PHP-FPM, функционируя как фоновый сервис, не наследует переменные окружения из интерактивного сеанса оболочки.
Применение
1. Настройка файла конфигурации PHP-FPM
Чтобы сделать переменные окружения доступными для PHP, работающего под управлением PHP-FPM, необходимо внести изменения в конфигурацию пулов. Один из способов решения — использовать директиву env[]
в файле конфигурации пула PHP-FPM, например /etc/php/php-fpm.d/www.conf
. Это гарантирует, что PHP-FPM передаст специфичные переменные окружения процессам PHP.
[www]
env[APP_ENV] = development
После внесения изменений перезапустите сервисы PHP-FPM и Nginx, чтобы изменения вступили в силу:
sudo systemctl restart php-fpm
sudo systemctl restart nginx
2. Альтернативные решения
-
Использование systemd для передачи переменных окружения: Если PHP-FPM запускается через systemd, можно создать файл конфигурации, например,
/etc/systemd/system/php-fpm.service.d/override.conf
:[Service] Environment="APP_ENV=development"
После этого выполните:
sudo systemctl daemon-reload sudo systemctl restart php-fpm
-
Использование
auto_prepend_file
: Если необходимо избежать изменения конфигурации PHP-FPM, можно использовать директивуauto_prepend_file
, чтобы загрузить файл, устанавливающий переменные окружения в рантайме:Создайте файл
set_env.php
:<?php $_SERVER['APP_ENV'] = 'dev';
Измените файл конфигурации PHP, добавив путь к
set_env.php
:auto_prepend_file = /path/to/set_env.php
3. Развертывание в контейнерах Docker
В средах, таких как Docker, переменные окружения могут быть переданы через команды docker run
или через файлы .env
внутри контейнера. Это также может быть настроено в docker-compose.yml
.
services:
php:
image: php:fpm
environment:
APP_ENV: development
Заключение
Управление переменными окружения в контексте PHP-FPM требует четкого понимания, как устройства и процессы взаимодействуют с окружением операционной системы. Независимо от выбранного подхода, ключевым моментом является обеспечение корректной передачи переменных в соответствующее окружение PHP через должным образом настроенные конфигурационные файлы или механизмы контейнеризации.