编程 nginx 1.31.8:working_directory 的相对路径不再跟着启动目录走

2026-11-07 21:02:27

nginx 1.31.8:working_directory 的相对路径不再跟着启动目录走

nginx 1.31.8(2026-10-21)的 CHANGES 里有一条行为变更和一条配套修复:

*) Change: now the path specified in the "working_directory" directive is relative to
   nginx prefix directory, but not to the current directory.

*) Bugfix: worker processes exited on start or during reconfiguration if an invalid
   directory was specified in the "working_directory" directive.

working_directory 是 core 模块的 main 上下文指令,语法 working_directory directory;,作用是给 worker 进程设置工作目录。它最常见的用途是配合 core dump:进程崩溃时,如果 kernel.core_pattern 是普通路径,内核会按崩溃进程的 cwd 写 core 文件,所以 worker 的 cwd 决定了 core 落在哪。这个目录必须存在且对 worker 用户可写。

相对路径的解析基准从当前目录变成 prefix

1.31.8 之前,working_directory 里的相对路径按进程启动时的当前目录解析。而 nginx 的启动方式决定了这个当前目录是什么:

  • systemd 拉起:取决于单元里的 WorkingDirectory,没写就是 /,部分发行版的打包会设成 /etc/nginx 或别的目录;
  • init 脚本或 supervisor:取决于脚本里有没有 cd;
  • 手工启动:cd /usr/local/nginx/sbin && ./nginx,当前目录就是 sbin。

于是同一行 working_directory logs/core;,在三台机器上可能分别落到 /logs/core、/etc/nginx/logs/core、/usr/local/nginx/sbin/logs/core。配置文件看起来完全一样,行为不一样,core 文件也就时有时无。

1.31.8 起统一按 nginx prefix 解析。prefix 由编译时的 --prefix 决定,nginx -V 的 configure arguments 里能看到,也可以用启动参数 -p / --prefix 覆盖。

配套的 bugfix 是同一条变更的另一面:working_directory 指向的目录无效时,worker 进程会在启动或 reconfiguration 阶段直接退出,而不是打条警告继续跑。所以升级后如果相对路径在新基准下指向一个不存在的目录,reload 会让 worker 起不来。退出时的具体日志文案这里没有实测;排查时可以直接看 worker 进程是否存活。

升级时查什么

  1. nginx -V,从 configure arguments 里找到 --prefix,确认配置里相对路径实际指向哪。
  2. 把 working_directory 改成绝对路径。跨机器、跨启动方式都不会飘。
  3. 验证 worker 实际的 cwd:ls -l /proc/$(pgrep -f 'nginx: worker')/cwd。
  4. nginx -t 只做配置语法与部分路径检查,不会创建目录,缺失目录要自己建。
  5. core 目录 chown 给 worker 运行用户;同时确认 kernel.core_pattern——如果配成 |/usr/lib/systemd/systemd-coredump 这类管道形式,core 由 coredump 服务接管,不会再落到 working_directory 里。

配置对照与 systemd 单元

改前,路径取决于启动方式:

# 1.31.8 之前:相对启动时的 cwd,systemd 下大概率是 /logs/core
working_directory logs/core;

改后,路径相对 prefix;假设 --prefix=/usr/local/nginx:

# 等价于 /usr/local/nginx/logs/core
working_directory logs/core;

# 更稳的写法,不依赖 prefix 也不依赖启动目录
working_directory /var/log/nginx/core;

systemd 单元示例:

[Unit]
Description=nginx
After=network.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
# 1.31.8 起不再影响 working_directory 的相对路径解析,但仍是 master 进程自身的 cwd
WorkingDirectory=/
ExecStartPre=/usr/local/nginx/sbin/nginx -t -q -p /usr/local/nginx
ExecStart=/usr/local/nginx/sbin/nginx -p /usr/local/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload -p /usr/local/nginx
ExecStop=/usr/local/nginx/sbin/nginx -s quit -p /usr/local/nginx

[Install]
WantedBy=multi-user.target

建目录并授权:

install -d -o nginx -g nginx -m 0750 /var/log/nginx/core
sysctl kernel.core_pattern
ls -l /proc/$(pgrep -f 'nginx: worker')/cwd

新基准比「跟着启动目录走」可预测得多,代价是以前靠 cwd 隐式生效的配置会暴露出来:升级时要么把路径写成绝对路径,要么确认 prefix 下那个目录真的存在、权限也对。

复制全文 生成海报 nginx 运维 systemd

推荐文章

程序员茄子在线接单