Получение переменных среды в PHP-FPM с Nginx

Вопрос или проблема

Я определил некоторые переменные окружения, такие как 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 через должным образом настроенные конфигурационные файлы или механизмы контейнеризации.

Оцените материал
Добавить комментарий

Капча загружается...