Nginx主配置段不支持直接使用$ENV_VAR引用环境变量;env指令仅声明环境变量白名单供worker进程继承,不能用于配置项值替换;实际使用需通过shell预处理(如envsubst)或Lua/Perl模块动态读取。

Nginx 主配置段(即 nginx.conf 的顶层,非 server 或 location 块内)本身不支持直接用 $ENV_VAR 语法引用环境变量,也不能在 env 指令中使用变量展开。但你可以通过 env 指令**导出**环境变量供 Nginx 内部模块(如 ngx_http_perl_module、ngx_http_lua_module)或外部程序(如启动脚本、日志处理)使用;而要在配置中**实际使用**环境变量值(比如设置 root、proxy_pass),需借助运行时机制——最常用且可靠的方式是:在启动前用 shell 展开变量生成最终配置,或使用 Lua/Perl 模块动态读取。
env 指令的作用与限制
env 是 Nginx 主配置段的指令,用于显式声明哪些环境变量应被保留在 worker 进程中(默认只保留 TZ)。它不会赋值,也不做替换,仅起“白名单”作用:
- 写法示例:
env APP_ENV; env CONFIG_DIR=/etc/nginx/conf.d; - 未声明的环境变量在 worker 进程中不可见(即使系统有,Nginx 也读不到)
-
env VAR=VALUE形式可设默认值,但该值仍是静态字符串,不能含$引用其他变量 - 它对
server块内的配置项(如root $APP_ROOT;)完全无效——Nginx 配置解析阶段不支持这种变量展开
在配置中真正使用环境变量的可行方式
若你想根据环境切换路径、上游地址等,必须绕过纯静态配置解析。主流做法有两类:
-
预处理配置文件:用 shell 脚本(如
envsubst)在启动 Nginx 前替换模板中的${VAR}占位符。例如:envsubst '${BACKEND_HOST} ${STATIC_PATH}' < nginx.conf.template > /etc/nginx/nginx.conf && nginx -t && nginx -
用 Lua 模块动态读取(需编译
ngx_http_lua_module):
在http块中:set_by_lua_block $backend_host { return os.getenv("BACKEND_HOST") or "localhost:8080" },然后在location中用proxy_pass http://$backend_host; -
用 Perl 模块(较少用,需启用
ngx_http_perl_module):perl_set $log_level 'sub { return $ENV{"LOG_LEVEL"} || "warn"; }';,再用于error_log ... $log_level;
常见误区与验证方法
很多人误以为写 env MY_VAR; root /var/www/$MY_VAR; 就能生效——这会报错或静默失败(Nginx 把 $MY_VAR 当字面量)。正确验证步骤:
- 先确认环境变量已由启动环境传入:
systemctl show --property=Environment nginx(systemd)或检查启动脚本中是否export MY_VAR=xxx - 加
env MY_VAR;到nginx.conf顶层,并重载:nginx -s reload - 在 worker 进程中验证是否可见:
ps aux | grep nginx | head -1 | xargs -0 -I{} cat /proc/{}/environ | tr '\0' '\n' | grep MY_VAR - 若要用在配置逻辑中,必须配合 Lua/Perl 或预处理,不能依赖原生
$语法
不复杂但容易忽略:Nginx 的 env 指令只是“透传开关”,不是“变量注入器”。真要驱动配置行为,得靠外部脚本或扩展模块来桥接。










