nginx 的 set 指令用于在 server 块中定义请求级局部变量,仅当前请求有效,需显式初始化,多次赋值以最后一次为准;适用于动态路径管理、多租户部署等场景,但条件逻辑优先用 map 替代 if + set 以提升性能与可靠性。

在 Nginx 的 server 块中用 set 指令定义局部变量,核心作用是把重复计算、路径拼接或条件判断结果提前固化为变量,让后续指令(如 root、alias、proxy_pass)引用更清晰、更少出错。它不是全局变量,也不跨请求,只对当前请求生命周期有效。
变量必须显式初始化,且只能在使用前定义
未通过 set、map 或内置变量(如 $host)赋值的变量,值为空字符串,可能导致路径错误或 404。同一请求中多次 set 同名变量,以最后一次为准。
- 正确写法:
set $app_root "/var/www/app";,之后再在root $app_root;中使用 - 错误写法:直接写
root $app_root;而没先set,Nginx 会当成字面量$app_root处理,不是变量替换 - 注意:不能在
if块外直接依赖if内部的set,因为if是惰性执行,且存在作用域限制
用 set 统一管理动态路径和前缀
当多个 location 需要共用基于域名、版本号或环境的路径时,用 set 提前提取,避免硬编码和重复逻辑。
- 例如按子域名区分静态资源根目录:
set $static_root "/var/www/static"; if ($host ~ "^cdn\.(.+)$") { set $static_root "/var/www/cdn"; } - 再配合
location /assets/ { alias $static_root/assets/; },逻辑集中、易维护 - 适合场景:多租户部署、灰度发布路径切换、CDN 回源路径动态调整
优先用 map 替代 if + set 实现条件映射
map 在配置加载阶段就完成编译,性能更好,无 if 的执行顺序陷阱,也更安全可靠。
- 推荐写法:
map $host $backend { example.com "http://10.0.1.10:8080"; www.example.com "http://10.0.1.11:8080"; default "http://10.0.1.12:8080"; } - 然后在
proxy_pass $backend;中直接使用,比嵌套if更稳定 - 适用于:根据
$host、$arg_v、$http_user_agent等做简单路由映射
变量可用于 rewrite、proxy_pass 和日志等标准指令
set 定义的变量支持在大多数需要字符串值的指令中展开,但要注意使用上下文是否允许。
- 可用:
rewrite ^/v(\d+)/(.*)$ /$2?version=$1 break;中可嵌入set变量参与拼接 - 可用:
proxy_pass http://$upstream_host$request_uri;,其中$upstream_host可由set或map设置 - 不可用:
log_format中不能直接引用运行时set变量(需用map或内置变量替代)











