服务器运维

Nginx 启动命令:启动、停止、重启与 reload 怎么选

Nginx 启动命令分两套:由 systemd 管理时用 systemctl start、stop、restart、reload nginx;直接控制进程时执行 nginx 启动,用 nginx -s stop、quit、reload 停止或重载。改了配置先 nginx -t 检查再 reload,不必 restart;只有升级了 Nginx 程序、改了 systemd 参数或进程状态异常时才需要 restart。

作者 顶联产品团队发布于 6 分钟阅读

Nginx 启动命令取决于它是怎么装上的。用 apt、dnf 从发行版软件源或 nginx.org 官方仓库安装的,由 systemd 管理,启动执行 systemctl start nginx;源码编译或解压即用的版本,直接执行 Nginx 程序本身,例如 /usr/local/nginx/sbin/nginx。停止、重启、重载也是两套写法:systemctl stop|restart|reload nginx,或者 nginx -s stop|quit|reload。日常改配置只需要 nginx -t 检查通过后 reload,正在访问的用户不会断开;restart 会让整个进程退出再启动,留给少数几种必须用它的情况。

所有写法一张表:启动、停止、重启、重载

操作 systemd 管理时 直接控制进程 对应信号 效果
启动 systemctl start nginx nginx — 启动 master 进程和若干 worker 进程
快速停止 systemctl stop nginx(具体信号由 unit 文件决定) nginx -s stop TERM 或 INT 立即退出,正在传输的请求被切断
优雅停止 — nginx -s quit QUIT 不再接受新连接,处理完手头的请求再退出
重载配置 systemctl reload nginx nginx -s reload HUP 用新配置启动新 worker,旧 worker 处理完再退出
重启 systemctl restart nginx nginx -s quit 之后再执行 nginx — 整个进程退出后重新启动,master 的 PID 改变
重新打开日志 — nginx -s reopen USR1 日志被轮转改名后,让 Nginx 写入新文件
检查配置 nginx -t nginx -t — 只检查语法和引用的文件,不影响正在运行的进程
查看状态 systemctl status nginx pgrep -a nginx — —

日常用到的命令:

# systemd 管理的 Nginx(发行版软件源或 nginx.org 官方仓库安装)
sudo systemctl start nginx
sudo systemctl stop nginx
sudo systemctl restart nginx
sudo nginx -t && sudo systemctl reload nginx    # 检查通过才重载
sudo systemctl enable --now nginx               # 设为开机自启并立即启动
systemctl status nginx --no-pager

# 直接控制进程(源码编译默认装在 /usr/local/nginx)
sudo /usr/local/nginx/sbin/nginx                # 启动
sudo /usr/local/nginx/sbin/nginx -s quit        # 优雅停止
sudo /usr/local/nginx/sbin/nginx -s stop        # 快速停止
sudo /usr/local/nginx/sbin/nginx -t && sudo /usr/local/nginx/sbin/nginx -s reload

几个容易踩的细节:

  • nginx -s 靠 pid 文件找 master 进程。 它先读配置里的 pid 指令,拿到 pid 文件里的进程号再发信号。启动时用 -c 指定了别的配置文件,发信号时也要带上同一个 -c,例如 nginx -c /opt/nginx/conf/nginx.conf -s reload,否则会报 open() ".../nginx.pid" failed 或 invalid PID number。
  • 提示 nginx: command not found。 源码编译的程序不在 PATH 里。执行 ps -ef | grep "nginx: master",master 进程的命令行会显示完整路径和配置文件,例如 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf;常用的话做一个软链接:ln -s /usr/local/nginx/sbin/nginx /usr/local/bin/nginx。宝塔面板装的 Nginx 在 /www/server/nginx/sbin/nginx,一般通过面板或它提供的服务脚本控制。
  • service 写法。 CentOS 6 这类老系统用 service nginx restart 或 /etc/init.d/nginx reload;在 systemd 系统上执行 service 命令,会被转交给 systemctl,效果相同。
  • 直接用 kill 发信号也可以。 kill -HUP $(cat /run/nginx.pid) 等价于 reload,kill -QUIT 等价于 quit。pid 文件的位置以 grep -E '^\s*pid' /etc/nginx/nginx.conf 查到的为准。

reload 和 restart 的区别:什么时候必须 restart

收到 reload 后,master 进程先检查新配置并打开新的端口和日志文件;检查通过,就用新配置启动一批新的 worker,再通知旧 worker 不再接收新连接、处理完手头的请求后退出。整个过程中监听端口一直开着,用户感知不到。新配置有错时,master 把错误写进 error.log,拒绝加载,继续用旧配置运行。restart 则是先停止、再启动:两步之间端口关闭,新连接会被拒绝;如果新配置有错,启动失败,网站就停在那里了。

对比项 reload restart
master 进程 不变,PID 不变 退出后重新启动,PID 改变
正在处理的请求 旧 worker 处理完再退出 取决于停止信号:TERM 立即切断,QUIT 等请求处理完(受超时限制)
监听端口 一直在监听,不会拒绝新连接 停止到启动之间端口关闭
新配置有错 拒绝加载,按旧配置继续运行 启动失败,网站中断
是否换成磁盘上的新程序 不会,仍运行原来的程序 会
适用场景 绝大多数配置修改:server、location、upstream、证书、日志格式、限流 升级 Nginx 程序、改 systemd 参数、进程状态异常

换证书也属于配置修改,reload 就能让新证书生效。真正需要 restart 的是下面三种情况:

  1. 升级了 Nginx 软件包。 apt upgrade 或 dnf update 替换的是磁盘上的程序文件,正在运行的 master 还是旧程序,reload 只换配置不换程序。nginx -v 显示的是磁盘上的新版本,不能说明运行中的是哪个版本。确认方法是看 master 进程对应的程序文件:ls -l /proc/$(cat /run/nginx.pid)/exe,末尾带 (deleted) 说明程序已被替换,需要 restart 才会用上新版本。部分发行版的软件包在升级时会自行处理,以这条命令的结果为准。
  2. 改了 systemd 的参数。 在 unit 文件或 systemctl edit nginx 里改的 LimitNOFILE、环境变量等,只在进程启动时生效,要先 systemctl daemon-reload,再 systemctl restart nginx。
  3. 进程状态异常。 例如 pid 文件被误删、master 被 kill 后残留 worker、reload 报 invalid PID number。先用 pgrep -a nginx 看清有哪些进程,必要时全部结束,再用 systemctl 重新启动。

确认 reload 是否成功,看进程启动时间:

ps -o pid,ppid,lstart,cmd -C nginx

reload 成功后,master 的 PID 和启动时间不变,worker 都是刚启动的新进程。如果还有标着 worker process is shutting down 的旧 worker 迟迟不退,通常是 WebSocket、大文件下载这类长连接还没结束。频繁 reload 时这些旧进程会越积越多、占用内存,可以在 nginx.conf 的最外层加 worker_shutdown_timeout 30s;,让旧 worker 最多等 30 秒就关闭剩余连接退出。

至于 restart 时正在处理的请求会不会被切断,要看 unit 文件怎么写。不同来源的 unit 写法不同:有的停止时发 QUIT 并等待几秒,超时再强制结束;有的直接发 TERM。执行 systemctl cat nginx,看 ExecStop、KillSignal、TimeoutStopSec 这几行就清楚了。

如果升级 Nginx 程序也不能接受断连,Nginx 官方文档提供了不停机替换程序的信号流程:给旧 master 发 USR2 启动新程序,再用 WINCH 让旧 worker 退出,确认新进程正常后对旧 master 发 QUIT。由 systemd 管理时,systemd 跟踪的是 pid 文件里记录的主进程,手工做这套流程前先确认 unit 文件的 PIDFile 设置;没把握的话,在业务低峰期 restart 更省事。

源码编译的 Nginx 怎么交给 systemd 管理

源码编译装的 Nginx 没有 unit 文件,systemctl start nginx 会提示 Unit nginx.service not found。可以自己写一个,保存为 /etc/systemd/system/nginx.service:

[Unit]
Description=nginx web server
After=network-online.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=mixed

[Install]
WantedBy=multi-user.target

要点有三个:PIDFile 必须和 nginx.conf 里 pid 指令的路径一致(源码编译默认是安装目录下的 logs/nginx.pid);ExecStartPre 先跑一遍 nginx -t,配置有错时直接拒绝启动;停止用 QUIT 信号优雅退出,5 秒内没退完再强制结束。不建议用 ExecStop=nginx -s quit 代替 KillSignal:这条命令发完信号立即返回,systemd 随即认为停止动作已经完成,按 KillMode 和 KillSignal 处理剩余进程,KillSignal 保持默认的 TERM 时,等于又发了一次快速停止,优雅退出就失去了意义。

写好后先把手动启动的进程停掉,再交给 systemd:

sudo /usr/local/nginx/sbin/nginx -s quit
sudo systemctl daemon-reload
sudo systemctl enable --now nginx
systemctl status nginx --no-pager

Windows 下怎么启动、停止、重启 Nginx

Windows 版 Nginx 是 nginx.org 下载的 zip 包,解压即用,不是系统服务。它把运行时所在的目录当作相对路径的起点,所以所有命令都要先进入 Nginx 目录再执行,否则会报找不到 conf\nginx.conf 或 logs\nginx.pid。在命令提示符(cmd)里:

cd /d C:\nginx
start nginx
nginx -t
nginx -s reload
nginx -s quit
nginx -s stop
tasklist /fi "imagename eq nginx.exe"
taskkill /f /im nginx.exe
  • 用 start nginx 启动,它会在后台另开进程;直接执行 nginx.exe 会占住当前窗口。默认配置下任务管理器里会看到两个 nginx.exe,一个 master、一个 worker,这是正常的。
  • Windows 上的重启就是 nginx -s quit 之后再 start nginx;只是改了配置,用 nginx -s reload。
  • 在 PowerShell 里要写成 .\nginx.exe -s reload、Start-Process .\nginx.exe,PowerShell 默认不从当前目录查找命令,直接写 nginx 会提示找不到。
  • taskkill /f 是强制结束,用于 -s 命令失效、进程残留的情况,平时不要用它代替 quit。

Windows 上几个特有的启动报错:

报错 原因 处理
bind() to 0.0.0.0:80 failed (10048: ...) 端口已被占用,常见是之前启动的 Nginx 没退出,或者 IIS 在用 80 端口 netstat -ano | findstr :80 查 PID,再用 tasklist /fi "pid eq 1234" 看是哪个程序;PID 为 4 表示被系统的 HTTP.sys(IIS 等)占用
bind() to 0.0.0.0:80 failed (10013: ...) 端口被系统保留,或者被其他程序以独占方式占用 执行 netsh interface ipv4 show excludedportrange protocol=tcp 查看保留的端口范围(开启 Hyper-V、WSL 后常见),换一个不在范围内的端口
CreateFile() ... failed (1113: ...) Nginx 所在路径或配置里的路径含中文 放到全英文路径下,例如 C:\nginx

Nginx 启动失败怎么排查

systemctl start nginx 失败时,屏幕上只有一句 Job for nginx.service failed because the control process exited with error code。按这个顺序找原因:

sudo nginx -t                               # 1. 配置有没有错,报错会给出文件和行号
systemctl status nginx --no-pager -l        # 2. 最近几行启动日志
journalctl -u nginx -n 30 --no-pager        # 3. 更完整的启动日志
sudo tail -n 30 /var/log/nginx/error.log    # 4. Nginx 自己的错误日志
sudo ss -lntp | grep -E ':(80|443)\b'       # 5. 80、443 端口被谁占着

常见报错与处理:

报错 原因 处理
bind() to 0.0.0.0:80 failed (98: Address already in use) 端口被占用:Apache(httpd)、面板自带的 Web 服务,或者一个手动启动、不归 systemd 管的 Nginx 用 ss -lntp 找到占用的进程;如果占用者就是 nginx,先 nginx -s quit 停掉它,再 systemctl start nginx
bind() to [::]:80 failed (97: Address family not supported by protocol) 系统关闭了 IPv6,配置里却有 listen [::]:80 删除或注释 IPv6 的 listen 行
bind() to 0.0.0.0:端口 failed (13: Permission denied) 用普通用户启动、监听 1024 以下的端口;或者 SELinux 不允许 Nginx 监听 8088 这类非标准端口 用 root 或 systemd 启动;SELinux 环境执行 semanage port -a -t http_port_t -p tcp 8088 放行该端口
unknown directive "proxy_passs" 指令拼错,或用了没编译进来的模块的指令 核对拼写;用 nginx -V 查看编译了哪些模块
directive "server_name" is not terminated by ";" 漏了分号 按报错给出的文件和行号修改,行号可能指向下一行
unexpected "}" 或 unexpected end of file, expecting "}" 花括号不配对 检查报错位置前面最近的几个块
cannot load certificate "...": BIO_new_file() failed 证书路径写错,或文件没有读权限 用 ls -l 核对路径和权限
报错中含 key values mismatch 证书和私钥不是一对 分别执行 openssl x509 -in 证书.pem -noout -pubkey | openssl sha256 和 openssl pkey -in 私钥.key -pubout | openssl sha256,两个结果相同才是一对
could not build server_names_hash, you should increase server_names_hash_bucket_size 域名太长或太多 在 http 块加 server_names_hash_bucket_size 128;

端口占用里最常见的一种是“两种启动方式混用”:有人直接执行过 nginx,进程在运行,systemctl status 却显示 inactive;这时再 systemctl start nginx 必然报 98 端口占用,而网站其实一直在跑。解决办法是停掉手动启动的那个,以后统一用 systemctl。

另外,systemctl status 里出现 Can't open PID file /run/nginx.pid (yet?) after start 一般只是 systemd 读取 pid 文件早了一点,服务状态显示 active (running) 就不用处理。启动显示成功、网页却打不开,先在服务器本机执行 curl -I http://127.0.0.1 区分问题出在 Nginx 还是出在防火墙和安全组。

SSH 连不上时怎么重启 Nginx

有两种情况会让你在 SSH 里处理不了 Nginx:改防火墙规则时连 22 端口一起封掉了,或者服务器负载过高、SSH 迟迟登录不上。这时只能从服务器的“屏幕”进去。在 Toplink DCIM 里,运维人员从 IPMI 远程管理打开基于 BMC 的 VNC 控制台,业务网络断了也能看到系统的登录提示符,用 root 登录后先 nginx -t,再按需要 reload 或 restart,防火墙规则也可以在这里改回来。如果机器已经租给客户,服务商开放相应权限后,客户在客户自助端也能打开同样的控制台自行处理;系统确实卡死、控制台没有响应时,才需要重启或进入救援模式。

常见问题

nginx -s reload 和 systemctl reload nginx 有区别吗?

效果一样,都是让 master 进程重新读取配置。区别在管理归属:由 systemd 启动的 Nginx 统一用 systemctl 操作,systemctl status 显示的状态才准确;手动执行 nginx 启动的进程不归 systemd 管,是“明明在运行、status 却显示 inactive”这类混乱的主要来源。

怎么设置 Nginx 开机自启?

Linux 上执行 systemctl enable nginx,想同时立即启动就用 systemctl enable --now nginx,再用 systemctl is-enabled nginx 确认结果为 enabled。Windows 版 Nginx 不是系统服务,开机自启要借助 WinSW、NSSM 这类把程序包装成服务的工具,或者放进计划任务。

reload 之后配置没生效怎么办?

先看 error.log 里 reload 那一刻有没有 emerg 报错,新配置有错时 Nginx 会继续按旧配置运行。没有报错,就用 nginx -T 打印实际加载的完整配置,确认改的文件确实被 include 进来,以及请求有没有被另一个 server_name 相同或带 default_server 的 server 块先匹配走。

Docker 里的 Nginx 怎么重启和重载?

重载执行 docker exec 容器名 nginx -s reload,改配置前同样可以先 docker exec 容器名 nginx -t 检查;重启用 docker restart 容器名。容器里的 Nginx 以 daemon off 方式在前台运行,是容器的主进程,在容器里执行 nginx -s stop 或 quit 会让整个容器退出。

想看看在你的机房里怎么用?

从一次产品演示开始,梳理你的业务链路。

查看价格
服务热线 400-112-2951

让我们聊聊你的 IDC 业务

扫码添加企业微信,预约产品演示或申请试用。

Toplink 企业微信二维码

长按保存或使用企业微信 / 微信扫描

也可致电
400-112-2951
Telegram
@TopLink88