Keep learning, keep living...

0%

执行nginx -t修改临时目录属主

nginxroot启动时,如果配置文件中没有指定user指令,那么默认会设定usernobody, 数字为65534。而如果使用非root用户启动,那么nginx则不处理用户,直接以当前用户启动worker进程。

nginx的启动过程中的函数ngx_init_cycle会调用函数ngx_create_paths创建临时文件目录。在创建目录后,也会对目录的属主进行处理。如果属主不同于user指令配置的用户,那么就会调用chown更改属主为user配置的用户。

在执行nginx -t时,nginx也会调用函数ngx_init_cycle, 也就是在执行nginx -t时也有可能更改临时目录的属主,从而导致在运行的nginx worker进程没有权限读取临时目录导致业务异常。

比如,以nginx用户启动nginx, 此时临时目录属主为nginx

1
2
nginx     273095  0.0  0.0  26788   384 ?        Ss   10:11   0:00 nginx: master process ./sbin/nginx
nginx 273096 0.0 0.0 27156 1948 ? S 10:11 0:00 nginx: worker process
1
2
3
4
5
6
7
8
9
10
11
[nginx@dev02 nginx]$ ls -l
total 4
drwx------. 2 nginx nginx 6 Dec 18 10:10 client_body_temp
drwxr-xr-x. 2 nginx root 4096 Dec 18 10:11 conf
drwx------. 2 nginx nginx 6 Dec 18 10:10 fastcgi_temp
drwxr-xr-x. 2 nginx root 40 Oct 24 17:22 html
drwxr-xr-x. 2 nginx root 58 Dec 18 10:11 logs
drwx------. 2 nginx nginx 6 Dec 18 10:10 proxy_temp
drwxr-xr-x. 2 nginx root 48 Dec 18 10:07 sbin
drwx------. 2 nginx nginx 6 Dec 18 10:10 scgi_temp
drwx------. 2 nginx nginx 6 Dec 18 10:10 uwsgi_temp

当再次以root帐号运行nginx -t时,临时目录属主被修改为nobody。此时,worker进程不再有权限读取临时目录,从而会导致业务异常。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[root@dev02 nginx]# ls -l
total 4
drwx------. 2 nginx nginx 24 Dec 18 10:31 client_body_temp
drwxr-xr-x. 2 nginx root 4096 Dec 18 10:33 conf
drwx------. 2 nginx nginx 6 Dec 18 10:10 fastcgi_temp
drwxr-xr-x. 2 nginx root 40 Oct 24 17:22 html
drwxr-xr-x. 2 nginx root 58 Dec 18 10:32 logs
drwx------. 2 nginx nginx 6 Dec 18 10:10 proxy_temp
drwxr-xr-x. 2 nginx root 48 Dec 18 10:07 sbin
drwx------. 2 nginx nginx 6 Dec 18 10:10 scgi_temp
drwx------. 2 nginx nginx 6 Dec 18 10:10 uwsgi_temp
[root@dev02 nginx]# ./sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@dev02 nginx]# ls -l
total 4
drwx------. 2 nobody nginx 24 Dec 18 10:31 client_body_temp
drwxr-xr-x. 2 nginx root 4096 Dec 18 10:33 conf
drwx------. 2 nobody nginx 6 Dec 18 10:10 fastcgi_temp
drwxr-xr-x. 2 nginx root 40 Oct 24 17:22 html
drwxr-xr-x. 2 nginx root 58 Dec 18 10:32 logs
drwx------. 2 nobody nginx 6 Dec 18 10:10 proxy_temp
drwxr-xr-x. 2 nginx root 48 Dec 18 10:07 sbin
drwx------. 2 nobody nginx 6 Dec 18 10:10 scgi_temp
drwx------. 2 nobody nginx 6 Dec 18 10:10 uwsgi_temp

从上面的示例可以看到临时目录属主都被修改为nobody

这时请求访问到临时目录,会报错:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
[root@dev02 nginx]# curl --data-binary @1m.bin http://127.0.0.1:8080/upload -v
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0)
> POST /upload HTTP/1.1
> Host: 127.0.0.1:8080
> User-Agent: curl/7.61.1
> Accept: */*
> Content-Length: 1048576
> Content-Type: application/x-www-form-urlencoded
> Expect: 100-continue
>
< HTTP/1.1 100 Continue
< HTTP/1.1 500 Internal Server Error
< Server: nginx/1.29.4
< Date: Thu, 18 Dec 2025 02:42:40 GMT
< Content-Type: text/html
< Content-Length: 177
< Connection: close
<
<html>
<head><title>500 Internal Server Error</title></head>
<body>
<center><h1>500 Internal Server Error</h1></center>
<hr><center>nginx/1.29.4</center>
</body>
</html>
* we are done reading and this is set to close, stop send
* Closing connection 0

查看nginxerror.log可以看到worker进程没有权限读取临时目录:

1
2025/12/18 10:42:40 [crit] 273290#0: *13 open() "/usr/local/nginx/client_body_temp/0000000002" failed (13: Permission denied), client: 127.0.0.1, server: localhost, request: "POST /upload HTTP/1.1", host: "127.0.0.1:8080"

已给官方提交Pull Request, 在nginx -t时不修改临时目录权限,但官方认为修改属主是配置检测的必要步骤,拒绝该Pull Request

因而这种场景下,需要我们自行切换到nginx worker进程的用户,再执行nginx -t