Nginx变量严格按配置块作用域生效,仅在定义块及其子块内可见,不存在跨server的全局变量;真正全局可用的只有内置变量、map定义变量和geo模块变量。

因为 Nginx 变量不是全局命名空间里的“通用变量”,而是严格绑定在配置块层级和请求生命周期中的上下文值。所谓“全局块中无法引用”,本质是混淆了“http 块顶层”和“真正跨 server 的全局作用域”——Nginx 并不存在后者。
变量只在定义它的配置块及其子块内可见
这是最核心的规则。变量不具备跨同级块的穿透能力:
-
http 块中定义的变量(如
set $base_path "/opt/app")可在其内部所有server和嵌套的location中使用 -
server 块中定义的变量只能被该
server内的location继承,对其他server完全不可见 -
location 块中定义的变量仅限本
location及其内部的if或命名 location(如@named),且if中修改不影响外部
常见“无法引用”的典型错误场景
这些错误在 reload 配置时会直接报 unknown variable:
- 在
http块顶层(即不在任何server或location内)写set $x "val"→ 语法错误,set不允许出现在http顶层 - 在某个
server里定义set $env "prod",却在另一个同级server的root $env中引用 → 变量未定义,两个server是平行关系,不继承 - 在
location /api中set $api_ver "v2",然后在proxy_pass http://upstream/$api_ver中引用 → 启动失败,因为proxy_pass在解析阶段求值,而set是运行时指令,此处变量尚未初始化
能真正“全局可用”的只有三类变量
它们不依赖 set,由 Nginx 自动提供或预声明,作用域覆盖整个请求处理链:
-
内置变量:如
$uri、$host、$args,在对应处理阶段(rewrite/access/log 等)始终可用 -
map 定义的变量:必须在
http块顶层声明(如map $http_user_agent $is_mobile { ... }),声明后全配置可见,惰性求值,安全高效 -
geo / geoip 模块变量:同样需在
http块定义,生成的变量可被任意server或location引用
如何安全地实现跨 server 的逻辑复用
不要试图“共享变量”,而应通过结构化方式统一管理:
- 用
include抽取公共配置片段,例如把常用set和add_header写进common.conf,在每个server中include common.conf - 用
map替代多处if + set,比如按域名映射根路径:map $host $app_root { siteA.com "/var/www/a"; siteB.com "/var/www/b"; },然后各server直接用root $app_root - 避免在
proxy_pass、fastcgi_pass等指令中动态拼接变量路径,改用rewrite提前重写 URI,或用map构建完整 upstream 地址


















