nginx变量严格遵循配置块层级作用域和请求生命周期约束,仅在定义块及其子块内可见,内置变量只读且阶段可用,自定义变量须显式声明、运行时求值,map/geo变量是唯一全配置生效的例外。

nginx.conf 中的变量不是“随处可用”的通用符号,而是严格受配置块层级和请求生命周期双重约束的上下文值。理解作用域的关键在于:变量只在它被定义的配置块及其子块中有效,且多数自定义变量仅在请求处理阶段才真正存在。
变量只能在定义它的配置块及子块中使用
这是最核心的可见性规则,不继承、不跨级、不越界:
-
http 块顶层定义的变量(如用
map或geo)可在所有server和location中引用 -
server 块内用 set 定义的变量,仅对该
server及其内部所有location、if等子块可见 -
location 块中 set 的变量,只在该
location内部生效,同级其他location或父级server都无法访问 - 不能在 http 块顶层直接用 set——语法错误,Nginx 会拒绝加载配置
内置变量与自定义变量的作用域逻辑不同
内置变量(如 $uri、$host、$args)由 Nginx 在请求各阶段自动填充,它们不依赖定义位置,只要在支持该变量的处理阶段(rewrite、access、log 等)就能用;而自定义变量必须显式声明,且声明位置决定其作用域边界:
-
只读性:内置变量不可赋值,
set $remote_addr "127.0.0.1"会直接报错 -
运行时求值:所有变量(包括
map生成的)都是请求到达时才计算,不是配置加载时固化 - 字符串唯一类型:所有变量值都是字符串,没有整数、布尔等类型,也不支持算术运算
proxy_pass、fastcgi_pass 等指令不支持运行时变量拼接
这类指令在配置解析阶段就需要确定目标地址,而 set 定义的变量是运行时才赋值,因此直接写 proxy_pass http://upstream/$version 会导致启动失败:
- 正确做法是用
rewrite提前重写 URI,或用map构建完整 upstream 名称 -
map是唯一能在http块定义、全配置生效的条件映射机制,适合做灰度路由、多环境分流 - 避免在
if块里大量用set,因为if本身执行顺序复杂,容易引发意外交互
安全复用变量的推荐方式
不要试图“共享变量”,而应通过结构化手段统一管理逻辑:
- 用
include抽取公共配置片段,比如把常用set、add_header放进common.conf,各server中引入 - 用
map替代分散的if + set,例如按域名映射根路径:map $host $app_root { siteA.com "/var/www/a"; } - 对需要跨 server 复用的逻辑,优先考虑
geo或map,它们声明即全局可用,且惰性求值、性能稳定











