提到 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
居然真的会改权限!为了验证猜想,我在测试环境复现了整个过程:
app-u
启动 Nginx ,/var/lib/nginx/tmp/
属主是 app-u
,权限正常;nginx -t -c /path/to/test.conf
(这个 test.conf
里配置了 user nobody;
);tmp
目录权限 ——proxy
、client_body
等子目录的属主,果然从 app-u
变成了 nobody
!至此真相大白:
nginx -t
不仅会检查配置语法,还会根据配置文件中的 user
指令,自动创建 / 修复 Nginx 所需的临时目录(如 tmp/proxy
、tmp/client_body
),并将这些目录的属主改为 user
指令指定的用户。
之前同事用 root 执行 nginx -t -c 错误配置文件
时,配置里的 user nobody;
触发了 Nginx 的 “目录权限修复” 逻辑 —— 直接把原本 app-u
权限的临时目录,改成了 nobody
权限,最终导致业务故障。
这次故障完全是 “认知盲区” 导致的,后续我们做了 3 项整改,彻底杜绝同类问题:
user
指令与运行用户强一致所有 Nginx 配置文件的 user
指令,必须与实际启动 Nginx 的账号保持一致 —— 比如用 app-u
启动,就统一写 user app-u;
,禁止出现 nobody
、root
等不匹配的用户。
同时将核心配置文件(如 /etc/nginx/nginx.conf
)设为只读,避免误修改:
chmod 444 /etc/nginx/nginx.conf
通过写脚本监控错误日志中的错误关键字,错误次数,一旦触发阈值就告警
以前总觉得 nginx -t
是 “安全无害” 的命令,这次故障才意识到:任何看似简单的命令,都可能藏着你不知道的细节。
尤其是 Nginx 这类高频使用的工具,建议多翻官方文档(比如 nginx -t
的官方说明里其实提到了 “会验证配置相关的目录权限”),避免因 “想当然” 踩坑
1
mimiphp 6 小时 55 分钟前
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-temp-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 这种明文传输的协议。 |
2
yuedingwangji 3 小时 31 分钟前
既然你专门配置了 app-u 的账号运行 ng 了, 你都不改 ng 配置里面的账号么
|