PHP-FPM 配置 clear_env 参数对获取环境变量有什么影响?
核心结论:PHP-FPM 默认 clear_env = yes 会清空所有父进程环境变量,导致 getenv('DB_HOST') 返回 false 或空字符串,需在 www.conf 中设置 clear_env = no 才能读取 Docker 或 systemd 注入的环境变量。
原因分析
PHP-FPM 在启动过程中,为了防止任意系统的环境变量进入 FPM worker 进程,默认会清空系统环境变量。这是出于安全设计:防止敏感变量(比如 DB_PASSWORD、AWS_SECRET_ACCESS_KEY)意外泄露给任意 PHP 脚本。但副作用也很直接——你用 getenv('APP_ENV') 或$_ENV['APP_ENV'] 拿不到值,返回空或 false。
常见错误现象包括:var_dump($_ENV) 输出空数组;getenv('DB_HOST') 返回 false 或空字符串,哪怕 echo $DB_HOST 在 shell 中能正常显示;Docker 容器里 env | grep APP_ENV 显示变量存在,但 PHP 脚本里读不到。正常执行 PHP 文件(CLI 模式)可以取到环境变量,但是通过 nginx+php-fpm 调用脚本取不到环境变量。
解决方案一:修改 clear_env 配置
找到你的 www.conf(通常在/etc/php/{version}/fpm/pool.d/www.conf 或容器内/usr/local/etc/php-fpm.d/www.conf)。在 [www] 段落内添加或修改这一行:clear_env = no。重启 php-fpm:运行 kill -USR2 $(cat /var/run/php-fpm.pid) 或 service php-fpm reload(取决于启动方式)。验证是否生效:在 PHP 脚本中执行 var_dump(getenv('PATH'));,如果输出非空字符串,说明环境变量已可读。
解决方案二:显式注入环境变量
在 php-fpm 中还有另一种方式传递环境变量到 PHP-FPM 的进程中,可以选择性使用环境变量。在 www.conf 中添加:
env[HOSTNAME] = $HOSTNAME
env[PATH] = /usr/local/bin:/usr/bin:/bin
env[TMP] = /tmp
env[TMPDIR] = /tmp
此方法比 clear_env = no 更安全,只传递需要的变量。在 php-fpm.conf 或 www.conf 中显式设置,否则改.env 文件或 Docker environment:都没用。
注意事项
设为 no 后,所有父进程环境变量都会透传到每个 worker 进程,包括你可能没意识到的变量(比如 HOSTNAME、KUBERNETES_SERVICE_HOST)。这不是 bug,是预期行为。将 clear_env 设置为 no 会让 PHP-FPM 继承所有系统环境变量,但这可能引入不必要的变量,甚至潜在的安全风险。常见问题包括 variables_order 未包含'E'导致$_ENV 为空、Web 服务器或 PHP-FPM 配置错误 (如 clear_env=yes)、变量名大小写不匹配、CLI 与 Web 环境差异等。
生产环境中推荐结合.env 文件、容器化或云平台管理,并遵循最小权限与敏感信息不硬编码等安全原则。相比配置文件,环境变量更安全、利于隔离,但难以处理复杂结构。
参考来源
来源:技术知识库 - 为什么 PHP 无法读取环境变量_在 FPM 配置文件中开启 clear_env = no(2026 年 4 月 23 日)
来源:技术知识库 - 优化 Laravel 应用时区配置:系统环境变量与 PHP-FPM 的实践指南(2025 年 8 月 30 日)
来源:技术知识库 - php php-fpm 读取不到环境变量的问题(2023 年 2 月 1 日)
来源:技术知识库 - 如何使用 Docker 设置 PHP 环境变量 PHP 容器动态配置参数方法(2025 年 7 月 22 日)