分享一个遇到的 Nginx 命令引发的故障 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
Yangsh853
V2EX    程序员

分享一个遇到的 Nginx 命令引发的故障

  •  3
     
  •   Yangsh853 85 天前 3161 次点击
    这是一个创建于 85 天前的主题,其中的信息可能已经有所发展或是发生改变。

    提到 nginx -t 命令,绝大多数人的第一反应是 “测试 Nginx 配置文件语法是否正确” 毕竟执行后看到 “syntax is ok” 和 “test is successful”,就默认它只是个 “语法检查工具”。

    图片

    但最近一次线上故障,让我彻底刷新了对这条命令的认知:它居然会悄悄修改服务器目录权限,甚至直接导致业务卡顿崩溃!

    一、突发故障:页面频繁卡顿,日志报满 “权限拒绝”

    某天突然收到业务反馈:某页面多次加载卡顿、频繁报 “502 Bad Gateway”,用户无法正常操作。

    图片

    第一时间查看 Nginx 错误日志,发现大量类似报错,核心信息全是 “权限拒绝”:

    [crit] 421611#421611: *429 open() "/var/lib/nginx/tmp/proxy/664/02/0000000027" failed (13: Permission denied) while reading upstream, client: 
    16:48:57 [crit] 421611#421611: *399 open() "/var/lib/nginx/tmp/proxy/666/02/0000000026" failed (13: Permission denied) while reading upstream, client: , server: _, request: "GET /hp-prod/js/dist/block-editor.min.js?ver=b3b0b55b35e04df52f7c HTTP/1.1", upstream: "http://:9080/hp-prod/js/dist/block-editor.min.js?ver=b3b0b55b35e04df52f7c", host: "8.153.203.10", referrer: "http://hppd-admin/post.php" 

    日志指向很明确:Nginx 要读取 / 写入代理临时文件(/var/lib/nginx/tmp/proxy/)时,没有权限 这些临时文件是 Nginx 转发上游服务(如 WordPress 、后端 API )时,用来缓存大响应的关键文件,没权限操作就会导致请求中断。

    二、紧急修复:麻溜恢复业务

    既然是权限问题,先定位 Nginx 的运行用户:

    ps aux | grep nginx 

    输出显示,Nginx worker 进程的运行用户是 app-u(这是我们之前为了安全,专门创建的低权限账号)。

    再检查临时目录权限:

    ls -ld /var/lib/nginx/tmp/proxy/ 

    结果出乎意料:proxy 目录及所有子文件的属主 / 属组,居然变成了 nobody( Linux 默认的匿名用户)app-u 对这些文件没有读写权限,自然会报错。

    紧急执行权限修复命令:

    # 递归将临时目录的属主/属组改为 app-u chown -R app-u:app-u /var/lib/nginx/tmp/ # 确保目录有读写执行权限 chmod -R 755 /var/lib/nginx/tmp/ 

    修复后通知用户重试,页面加载恢复正常,故障暂时解决。

    三、溯源:是谁 “偷偷” 改了权限?

    业务恢复后,核心问题来了:/var/lib/nginx/tmp/ 原本是 app-u 权限,为什么会变成 nobody

    我们翻了故障前 1 小时的服务器操作日志(通过操作记录日志文件),发现一个关键操作:**故障前 2 分钟,有同事用 root 账号执行了 nginx -t -c /path/to/nginx.conf**。

    “不就是测试个配置吗?怎么会改权限?” 带着疑问,去看了当时执行的 nginx.conf,发现配置文件里有一行:

    user nobody; # 指定 Nginx 运行用户为 nobody 

    但这里有个矛盾:我们实际启动 Nginx 时,用的是 app-u 账号,且启动命令里没指定配置文件(默认加载 /etc/nginx/nginx.conf,其中 user app-u;) 那同事手动指定的这个配置文件,为什么会影响目录权限?

    四、测试验证:nginx -t 居然真的会改权限!

    为了验证猜想,我在测试环境复现了整个过程:

    1. 初始状态:用 app-u 启动 Nginx ,/var/lib/nginx/tmp/ 属主是 app-u,权限正常;
    2. 执行命令:切换到 root 账号,执行 nginx -t -c /path/to/test.conf(这个 test.conf 里配置了 user nobody;);
    3. 检查结果:执行后立即查看 tmp 目录权限 proxyclient_body 等子目录的属主,果然从 app-u 变成了 nobody

    至此真相大白: nginx -t 不仅会检查配置语法,还会根据配置文件中的 user 指令,自动创建 / 修复 Nginx 所需的临时目录(如 tmp/proxytmp/client_body),并将这些目录的属主改为 user 指令指定的用户

    之前同事用 root 执行 nginx -t -c 错误配置文件 时,配置里的 user nobody; 触发了 Nginx 的 “目录权限修复” 逻辑 直接把原本 app-u 权限的临时目录,改成了 nobody 权限,最终导致业务故障。

    五、后续整改

    这次故障完全是 “认知盲区” 导致的,后续我们做了 3 项整改,彻底杜绝同类问题:

    1. 规范配置文件:user 指令与运行用户强一致

    所有 Nginx 配置文件的 user 指令,必须与实际启动 Nginx 的账号保持一致 比如用 app-u 启动,就统一写 user app-u;,禁止出现 nobodyroot 等不匹配的用户。

    同时将核心配置文件(如 /etc/nginx/nginx.conf)设为只读,避免误修改:

    chmod 444 /etc/nginx/nginx.conf 

    2. 平时变更类相关操作禁止使用 root 账号

    3. 日志监控告警:提前发现权限问题

    通过写脚本监控错误日志中的错误关键字,错误次数,一旦触发阈值就告警

    最后:

    以前总觉得 nginx -t 是 “安全无害” 的命令,这次故障才意识到:任何看似简单的命令,都可能藏着你不知道的细节

    尤其是 Nginx 这类高频使用的工具,建议多翻官方文档(比如 nginx -t 的官方说明里其实提到了 “会验证配置相关的目录权限”),避免因 “想当然” 踩坑

    图片

    图片

    16 条回复    2025-09-04 09:31:44 +08:00
    mimiphp
        1
    mimiphp  
       85 天前   3
    wget -c https://nginx.org/download/nginx-1.27.5.tar.gz
    tar zxvf nginx-1.27.5.tar.gz
    cd nginx-1.27.5 && ls
    make clean
    ./configure \
    --prefix=/usr/local/nginx \
    --user=www \
    --group=www \
    --sbin-path=/usr/local/nginx/sbin/nginx \
    --conf-path=/usr/local/nginx/nginx.conf \
    --error-log-path=/usr/local/nginx/error.log \
    --http-log-path=/usr/local/nginx/access.log \
    --pid-path=/usr/local/nginx/nginx.pid \
    --lock-path=/usr/local/nginx/nginx.lock \
    --http-client-body-temp-path=/usr/local/nginx/client_temp \
    --http-proxy-temp-path=/usr/local/nginx/proxy_temp \
    --http-fastcgi-tem-path=/usr/local/nginx/fastcgi_temp \
    --http-uwsgi-temp-path=/usr/local/nginx/uwsgi_temp \
    --http-scgi-temp-path=/usr/local/nginx/scgi_temp \
    --with-file-aio \
    --with-threads \
    --with-http_addition_module \
    --with-http_auth_request_module \
    --with-http_dav_module \
    --with-http_flv_module \
    --with-http_gunzip_module \
    --with-http_gzip_static_module \
    --with-http_mp4_module \
    --with-http_random_index_module \
    --with-http_realip_module \
    --with-http_secure_link_module \
    --with-http_slice_module \
    --with-http_ssl_module \
    --with-http_stub_status_module \
    --with-http_sub_module \
    --with-http_v2_module \
    --with-mail \
    --with-mail_ssl_module \
    --with-stream \
    --with-stream_realip_module \
    --with-stream_ssl_module \
    --with-stream_ssl_preread_module

    make -j $(nproc)
    make install
    cat <<EOF > /etc/systemd/system/nginx.service
    [Unit]
    Description=nginx
    After=network.target

    [Service]
    Type=forking
    ExecStart=/usr/local/nginx/sbin/nginx
    ExecReload=/usr/local/nginx/sbin/nginx -s reload
    ExecStop=/usr/local/nginx/sbin/nginx -s quit
    PrivateTmp=false

    [Install]
    WantedBy=multi-user.target
    EOF

    mkdir -p /usr/local/nginx/rewrite
    mkdir -p /usr/local/nginx/ssl
    mkdir -p /usr/local/nginx/ssl/default
    mkdir -p /usr/local/nginx/vhost


    这是我编写的编译安装 nginx 的代码片段。。。。我恰恰相反。web 服务器核心组件安装,比如就是 nginx 这个软件安装,必须用 root 权限来安装。执行权限交给 www ,并且是 nologin 账户。。。。普通用户就不应该可以操作修改重启核心组件。

    这里我特别强调就是多用户维护服务器,最好是开放 SSH ,或者 nginx 配置 webdav ,不要再用 FTP 这种明文传输的协议。
    yuedingwangji
        2
    yuedingwangji  
       84 天前   2
    既然你专门配置了 app-u 的账号运行 ng 了, 你都不改 ng 配置里面的账号么
    gearfox
        3
    gearfox  
       84 天前
    学到了
    Yangsh853
        4
    Yangsh853  
    OP
       84 天前 via Android
    @yuedingwangji 这个服务很早就在跑了,平时也确实没有注意到这个配置,后面全系统的 ng 都已经检查过了
    shinonome
        5
    shinonome  
       84 天前
    学习了
    i4t
        6
    i4t  
       84 天前
    这是很基础的故障了
    bai4246464
        7
    bai4246464  
       84 天前
    这个之前确实没注意,但是你既然用 app-u 用户启动了,就应该用 app-u 这个用户去 nginx -t
    guanzhangzhang
        8
    guanzhangzhang  
       84 天前
    可以看看 docker nginx-unprivileged 的容器做了哪些配置和设置参考下,以及制作 rpm 安装包的。
    都是非 root 用户加家目录,temp_path 要么单独家目录内,要么/tmp 目录下
    ivyliner
        9
    ivyliner  
       84 天前
    赞, 学习了
    githmb
        10
    githmb  
       84 天前
    你-t 了别的配置,又运行默认的配置,怪谁?
    nskjbtm123
        11
    nskjbtm123  
       83 天前
    这种故障真是可遇不可求,配置都不改成那个权限用户,那之前可能是怎么绕过那个配置文件的用户,使用低权限用户运行成功的?还是说之前不是用这个配置文件启动的
    Wyearn
        12
    Wyearn  
       83 天前
    学习到了
    victorc
        13
    victorc  
       83 天前   1
    没事不要去人为改变 nginx 的默认用户,会产生一系列维护成本,这属于没苦硬吃
    guo4224
        14
    guo4224  
       83 天前
    很难见到像 nginx 这么省心的东西……
    ioioj5
        15
    ioioj5  
       82 天前
    还真是没遇到过
    ruanimal
        16
    ruanimal  
       82 天前
    典型自作自受
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1040 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 18:30 PVG 02:30 LAX 10:30 JFK 13:30
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86