Nginx变量仅分内置变量和自定义变量两类,内置变量只读不可赋值,自定义变量需显式声明且受作用域与执行阶段限制;map最安全但仅限http块内使用;变量均为运行时求值,不可用于配置解析期指令。

在 Nginx 中,nginx.conf 里能用的“变量”其实只有两类:内置变量(built-in variables)和通过 set、map、geo 等指令定义的自定义变量。它们不是任意位置都能用,也不是所有上下文都支持赋值或引用——变量的可用性严格受作用域(scope)和指令执行阶段(phase)限制。
内置变量只能读取,不能赋值
Nginx 内置变量如 $remote_addr、$uri、$args、$http_user_agent 等,由 Nginx 在请求处理过程中自动填充,只读不可写。尝试用 set $remote_addr "127.0.0.1"; 会报错:
这类变量在以下上下文中可安全引用:
-
server和location块中的大多数指令(如return、proxy_set_header、log_format) -
if条件判断中(但注意if本身有局限性,不推荐复杂逻辑) -
map指令的源值或目标值中(如map $arg_version $backend { ... })
自定义变量需显式声明,且作用域受限
用 set 定义的变量仅在当前配置块及其子块生效,且必须在使用前声明。例如:
location /api/ {
set $api_version "v1";
proxy_pass http://backend/$api_version;
}这段有效;但如果写成:
location /api/ {
proxy_pass http://backend/$api_version; # ❌ 未声明就引用
set $api_version "v1";
}则启动时会报错:nginx: [emerg] unknown "api_version" variable。另外注意:
-
set不支持嵌套块外继承,server块里set的变量,在location里不可直接用(除非 location 是其子块且未被覆盖) -
set不能出现在http块顶层(即不在server或location内),否则报错 - 变量值是字符串,不支持类型转换或算术运算(Nginx 本身无原生整数运算,需靠
map模拟)
map 是最安全的变量生成方式,但仅限于特定上下文
map 指令必须定义在 http 块内,用于根据源变量值映射出新变量,适合做条件路由、灰度分流等。例如:
http {
map $http_x_version $upstream_group {
default backend_v1;
"v2" backend_v2;
"~^v3\..*" backend_v3;
}
server {
location / {
proxy_pass http://$upstream_group;
}
}
}关键规则:
-
map块不能嵌套,不能出现在server或location中 - 源变量可以是任意已存在的变量(包括其他
map变量),但目标变量名不能与内置变量同名 -
map的匹配在 rewrite 阶段早期执行,比set更稳定,适合依赖请求头、参数的动态决策
变量不能用于影响配置解析阶段的行为
所有变量都是运行时求值的,因此不能用在需要编译期确定的场景中。典型限制包括:
- 不能作为
include的路径(include $conf_path;❌) - 不能用于
upstream名称(proxy_pass http://$upstream_name;❌,但可通过resolver+ 变量域名实现间接代理) - 不能用于
listen、server_name、root等指令的字面值(除非该指令明确支持变量,如root支持变量,server_name不支持) -
if块内定义的set变量,只在该if分支内有效,且if本身不保证执行顺序(尤其与rewrite混用时易出错)










