ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Nginx进程管理:启动、停止、重启与开机自启配置详解

Nginx进程管理:启动、停止、重启与开机自启配置详解 1. 先把nginx的进程模型和信号机制搞明白很多新手折腾nginx上来就搜“nginx重启命令”复制粘贴一条nginx -s reload就跑。这种用法没错但一旦遇到“reload不生效”“kill进程后nginx起不来了”“开机自启配置了但就是没反应”这种问题时就完全不知道从哪里下手。归根结底是没有理解nginx到底是个什么样的程序它又是怎么被“控制”的。先把基础知识补上。nginx是一个master-worker多进程架构的Web服务器。你启动nginx后系统里会有两类进程一类是master主进程负责读取配置、接收信号、管理工作进程另一类是worker工作进程通常会有多个真正去处理HTTP请求的就是它们。worker进程之间是平级的每个都能独立处理连接master进程挂了或者主动退出worker进程也会跟着退出这套设计保证了服务的管理是集中式的。关键点来了master进程收到外部命令也就是信号后会做出对应的动作。比如你执行nginx -s stop其实是通过nginx二进制程序向master进程发送了一个QUIT信号让master进程优雅退出执行nginx -s reload就是发送HUP信号让master进程重新加载配置文件并启动新的worker进程。这就是信号机制理解了这一层之后所有操作都会变得非常顺手。还有个文件叫pid文件默认路径是/usr/local/nginx/logs/nginx.pid或者/var/run/nginx.pid里面记录了master进程的PID。nginx的命令行工具、systemd服务管理器都是靠这个文件找到master进程、再给它发信号的。如果pid文件丢失或者路径不对就会出现“明明nginx在运行但nginx -s stop却报错了”的情况后面我会专门讲这个问题怎么排查。除了信号机制还要知道nginx二进制文件本身提供了一套简洁的命令行参数nginx什么参数都不加就是直接启动服务nginx -s stop快速停止相当于发送TERM信号nginx -s quit优雅停止相当于发送QUIT信号等当前请求处理完再退出nginx -s reload平滑重载配置相当于发送HUP信号nginx -s reopen重新打开日志文件日志切割时会用到nginx -t测试配置文件语法是否正确nginx -T测试配置并输出完整的配置内容调试时很实用这几个命令就是日常nginx管理的核心。但要注意不同安装方式下nginx二进制文件的位置不一样后面的内容我会分别说明。2. 启动、停止与重启的具体操作2.1 启动nginx不同安装方式的不同位置启动nginx首先得知道你的nginx是从哪里来的。不同发行版、不同安装方式启动命令会有些区别。如果你是用包管理器装的比如CentOS上执行过yum install nginxUbuntu上执行过apt install nginx那么nginx二进制文件一般在/usr/sbin/nginx配置文件在/etc/nginx/nginx.conf。这种情况下启动方式有三种# 方式一直接用nginx命令启动 sudo /usr/sbin/nginx # 方式二使用systemd服务管理 sudo systemctl start nginx # 方式三如果你是老的SysV init系统比如CentOS 6 sudo service nginx start如果你是用源码编译安装的那么二进制文件的位置取决于编译时指定的prefix路径。我见过很多人在/usr/local/nginx/下面找不到nginx命令原因是nginx默认安装在/usr/local/nginx/目录但可执行文件在/usr/local/nginx/sbin/nginx没有把sbin目录加到环境变量里。这种情况下# 直接指定完整路径启动 sudo /usr/local/nginx/sbin/nginx # 或者把sbin目录加进PATH之后操作会更方便 export PATH/usr/local/nginx/sbin:$PATH还有一个细节如果启动时提示“address already in use”或者“bind() to 0.0.0.0:80 failed”说明80端口已经被占用了。这种情况要么是nginx已经在运行要么是其他程序比如Apache、Tomcat、或者其他Web服务占用了端口。可以使用netstat -tlnp | grep :80或者ss -tlnp | grep :80查看占用情况。补充一句启动成功后验证nginx是否正常运行最简单的方式是执行ps -ef | grep nginx你会看到一条master进程和几条worker进程。或者直接用curl访问本机curl -I http://127.0.0.1看到HTTP/1.1 200 OK就说明服务已经通了。2.2 停止nginx快速停止和优雅停止的区别停止nginx的命令是nginx -s stop和nginx -s quit两者都能让nginx退出但“退出姿势”完全不同。stop是立即终止相当于给master进程发送TERM信号。master进程收到后会立刻关闭所有worker进程不管当前有没有请求还在处理中。对于正在传输的大文件、正在执行的长连接请求就会直接被切断。这种方式的优势是“快”劣势是“粗暴”。一般只在需要马上释放端口、或者系统要重启时用。quit是优雅退出相当于发送QUIT信号。master进程收到后会先停止接受新连接然后等待当前正在处理的请求全部处理完毕再关闭worker进程。这个方式的代价是“慢”比如有一个长时间下载的任务还在跑worker进程就会一直不退直到下载完成。但好处是用户体验无感不会出现“操作进行到一半突然断掉”的情况。实际使用中生产环境我基本只用quit哪怕是日常维护也优先用quit除非特别紧急才用stop。如果主进程在收到QUIT信号后一直没有退出可以用nginx -s quit多次触发或者查看ps -ef | grep nginx检查是不是有worker进程还停留在工作中。停止命令的具体写法# 优雅停止 sudo nginx -s quit # 或者 sudo /usr/local/nginx/sbin/nginx -s quit # 快速停止 sudo nginx -s stop # 或者 sudo /usr/local/nginx/sbin/nginx -s stop这里有个坑要提醒如果你是通过systemd部署的nginx不要混用“nginx -s quit”和“systemctl stop nginx”。因为systemd有自己的一套进程管理和状态跟踪如果你绕过systemd直接向nginx发信号systemd可能还认为服务在运行但实际进程已经退了两者的状态会不一致之后“开机自启动”“失败自动拉起”这些功能就可能不生效。2.3 重启nginx最常见、也最容易出错的操作重启的本质是先停掉旧进程再启动新进程。用systemd的话一条systemctl restart nginx搞定。用命令行的话就是两步操作# 先停 sudo nginx -s quit # 再启动 sudo nginx但说实话日常运维中我们绝大多数时候不需要“重启”只需要“重载配置”。如果你修改了nginx.conf或者conf.d目录下的子配置文件想让配置生效最优解是执行nginx -s reload而不是重启nginx。为什么因为reload是平滑的整个过程不中断服务。master进程收到HUP信号后会做这几件事重新读取配置文件如果发现语法错误保持旧配置继续运行如果新配置没问题启动新的worker进程发送消息让旧的worker进程不再接受新连接处理完当前请求后退出这个过程对客户端来说几乎是无感的。而restart是先把master、worker全部停掉再重新拉起即使速度很快中间也存在一个空窗期高并发场景下这个空窗期可能就会导致部分请求失败。但是restart也不是没有使用场景。如果你改了监听端口、改了工作进程数这类无法在reload中生效的配置那必须restart。还有一种情况是nginx异常了内存异常、worker进程崩溃循环这时候reload可能无法解决问题只能重启。总结一下修改了静态配置、增加server块、调整proxy_pass等用nginx -s reload修改了listen端口、调整worker_processes等核心运行参数用restartnginx进程异常、资源泄漏、行为诡异时用restart实在判断不准的稳妥做法是先nginx -t测试配置然后restart。3. reload与restart这个坑必须单独拿出来说写到这里我觉得有必要单独用一章来讲reload和restart的区别因为这是我看到踩坑最多的地方也是面试里问烂了的知识点。很多新手把“改完配置重启一下就行”挂在嘴边但实际生产环境里“重启一下”可能就会引发线上事故。先说怎么判断你的修改到底需不需要restart。最直观的方式是看配置项属于哪一类能被reload生效的是那些在nginx进程运行期间可以动态调整的内容包括但不仅限于HTTP模块里的server块、location块、upstream后端列表、各种超时参数、gzip开关、缓存配置等。这些配置每次请求时都会从内存中的配置结构读取reload时新配置会替换旧配置新的worker进程直接用新配置老worker处理完当前连接后退出。不能被reload生效的是整个master进程架构级别的参数最典型的就是listen指令设置的监听端口。你改了端口或者新增了一个监听端口reload后新worker并不会去监听新端口因为套接字是在master进程启动时就创建好的。类似地调整worker_processes数量、修改worker_rlimit_nofile这类资源限制也需要restart。有个特别容易踩的坑改完端口执行nginx -s reload命令不报错但端口就是没生效。具体原因就是上面说的reload不会重新创建监听套接字只有restart才会。所以我个人的操作习惯是但凡改了listen相关的配置直接restart不做reload尝试节省时间也避免误判。再说一个实战经验生产环境修改upstream后端列表时优先用reload不要用restart。原因很简单reload时旧的worker进程会继续持有旧的上游连接池正在进行的请求不会被切断而restart会直接断开所有连接如果后端是数据库或者即时消息服务这种中断影响是很大的。还有一个很容易被忽略的场景如果你的nginx前面挂了负载均衡器比如云上的SLB或者自建的HAProxyreload和restart对负载均衡器的健康检查影响也不一样。reload的过程中端口一直是通的健康检查不会被中断restart时如果stop和start之间有一定时间间隔端口会短暂关闭健康检查就会判定实例异常流量会被切走等nginx恢复后再切回来。对于某些场景这甚至是有意的操作但如果你没有预期到这个行为就会误判为故障。另外说一句“nginx -s reload”本身也可能失败。如果配置文件里有语法错误reload会失败并且nginx会打印错误信息此时nginx会继续用旧配置运行服务不受影响。所以要养成一个习惯任何修改配置之后先执行nginx -t做语法测试测试通过再执行reload或者restart。这个习惯能帮你挡掉90%的配置错误。# 建议的操作顺序 sudo nginx -t # 如果输出 syntax is ok 和 test is successful sudo nginx -s reload4. 设置开机自启动systemd、SysV init和源码安装三种情况4.1 systemd时代的配置方法现在大多数Linux发行版都使用systemd作为初始化系统init system。CentOS 7、Ubuntu 16.04、Debian 8这些都是。systemd下服务是由unit文件来定义的nginx的unit文件一般位于/usr/lib/systemd/system/nginx.serviceCentOS系或/lib/systemd/system/nginx.serviceUbuntu/Debian系实际上两者往往是软链接关系。用systemd管理nginx自启动设置非常简单# 设置开机自启动 sudo systemctl enable nginx # 取消开机自启动 sudo systemctl disable nginx # 查看当前是否已设置自启动 sudo systemctl is-enabled nginxsystemctl enable做的事情是在/etc/systemd/system/multi-user.target.wants/目录下创建一个软链接指向nginx.service文件。这样系统进入multi-user.target也就是多用户命令行模式时就会自动启动nginx。下面两件事容易被人忽略。第一件enable只是设置了开机自启动它不会立刻启动服务。如果你希望“现在启动以后开机也自动启动”需要同时执行systemctl start nginx。第二件修改了系统的默认运行级别现在叫target、或者修改了nginx.service文件本体之后需要执行systemctl daemon-reload来让systemd重新加载unit文件否则修改可能不生效。有时你会看到这种输出The unit files have no installation config. This means they are not meant to be enabled using systemctl.说明这个service文件里缺少[Install]段systemd不知道通过哪个target的哪个依赖来启动这个服务。这种情况在自编译的、手动编写的service文件里很常见到时候要手动补上[Install]段。4.2 源码编译安装nginx时自己写一个systemd服务文件源码编译安装nginx的读者经常遇到的问题是nginx二进制在/usr/local/nginx/sbin/下没法用systemctl start nginx启动因为系统里根本没有nginx.service文件。网上很多教程会告诉你直接写一个启动脚本放到/etc/init.d/里用SysV方式管理。这在旧系统上没问题但现在的新系统我建议还是自己写一个systemd unit文件管理起来更规范还能用上systemd的守护、失败重启、依赖管理能力。假设你的nginx安装目录是/usr/local/nginx先创建service文件sudo vim /etc/systemd/system/nginx.service内容如下[Unit] Descriptionnginx - high performance web server Documentationhttp://nginx.org/en/docs/ Afternetwork-online.target remote-fs.target nss-lookup.target Wantsnetwork-online.target [Service] Typeforking PIDFile/usr/local/nginx/logs/nginx.pid ExecStartPre/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf ExecStart/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf ExecReload/usr/local/nginx/sbin/nginx -s reload ExecStop/usr/local/nginx/sbin/nginx -s quit PrivateTmptrue [Install] WantedBymulti-user.target逐行解释一下关键字段这样以后你自己调整的时候也有谱Afternetwork-online.target确保网络已经就绪后才启动nginx。如果没有这一行有些系统在开机时网络还没就绪就开始启动nginx此时nginx解析域名、监听端口都可能出问题。network-online.target并不是默认就启用的在部分系统上需要确保NetworkManager-wait-online.service之类的服务开启否则这个配置可能形同虚设。Typeforking告诉systemd这个服务的启动方式是“父进程fork出子进程后父进程退出”。nginx的master进程启动时就是这个行为所以这里必须写forking。如果你写成Typesimplesystemd会认为主进程一直在前台运行状态跟踪会混乱。PIDFile指向nginx的pid文件systemd靠它来判断服务是否启动成功。如果你的nginx pid文件路径不是在logs/nginx.pid这里要相应修改。ExecStartPre启动前先测试配置。如果配置有语法错误服务启动就会失败同时你能在systemd日志里看到具体错误。ExecReload定义了reload动作。之后执行systemctl reload nginx实际上就是执行这条nginx -s reload。ExecStop定义了停止动作。用优雅退出方式保证当前请求处理完才关闭。PrivateTmptrue服务使用独立的临时目录更安全。写完文件之后执行sudo systemctl daemon-reload sudo systemctl enable nginx sudo systemctl start nginx sudo systemctl status nginx如果status显示active (running)说明服务正常。以后再管理nginx就统一用systemctl start|stop|restart|reload|status nginx了。4.3 老系统的SysV init方式如果你的系统是CentOS 6这种老版本或者你所在的团队还在维护老环境那SysV init方式也得会。通过yum或者apt安装的nginx一般会自动安装对应的init脚本比如/etc/init.d/nginx。操作命令# 启动、停止、重启 sudo service nginx start sudo service nginx stop sudo service nginx restart # 设置开机自启动 sudo chkconfig nginx on # 查看自启动状态 sudo chkconfig --list nginx如果是源码编译安装的就需要手动把nginx的启动脚本放到/etc/init.d/并添加执行权限。网上可以找到官方或社区维护的init脚本复制到/etc/init.d/nginx后执行sudo chmod x /etc/init.d/nginx sudo chkconfig --add nginx sudo chkconfig nginx on这里有个小细节chkconfig --add想把脚本加入系统服务脚本里必须包含chkconfig的注释格式。比如#!/bin/sh # chkconfig: 2345 85 15 # description: nginx init script其中2345表示在运行级别2、3、4、5下启动85是启动优先级15是停止优先级。这个注释是chkconfig识别服务的依据缺了它chkconfig --add nginx会失败。4.4 自启动的常见问题为什么配置了却没生效我在帮朋友排查过很多次“关机重启后nginx没有自动启动”的问题每次的原因几乎都集中在几个点上这里整理出来供你对照排查。第一个是enable和start的混淆。有人只在机器上手动执行了systemctl start nginx就以为设置好了没有执行enable。重启后系统当然不会启动nginx。先在终端里执行systemctl is-enabled nginx如果输出是enabled那说明自启动配置是有的。第二个是nginx.service文件的PIDFile路径和实际路径不一致。如果你的nginx是编译安装的pid文件默认在/usr/local/nginx/logs/nginx.pid但service文件里写的是/run/nginx.pidsystemd启动服务后会发现pid文件不存在或者格式不对判定服务启动失败后续的自启动自然也不会正常。解决办法是打开nginx.conf看第一行pid /usr/local/nginx/logs/nginx.pid然后把service文件里的PIDFile改成一致。第三个是ExecStartPre里的路径写错了。比如你用的是nginx -t而不是/usr/local/nginx/sbin/nginx -t而nginx二进制又不在systemd的PATH环境变量里。systemd执行命令时的PATH和你在shell里是不一样的shell里可能配置了/usr/local/nginx/sbin在PATH中systemd可不会管你的.bashrc。所以service文件里所有涉及nginx二进制的路径要尽量写绝对路径避免踩这种隐晦的雷。第四个是防火墙的影响。如果nginx已经启动了但你从外部访问不到先别急着怀疑自启动大概率是firewalld或者iptables没有放行80端口或者其他监听端口。CentOS 7上可以执行sudo firewall-cmd --permanent --add-servicehttp sudo firewall-cmd --reloadUbuntu上一般用ufwsudo ufw allow Nginx Full5. 常见问题与排查技巧实录5.1 pid文件丢失或路径不匹配导致的异常我在2.1里提到过pid文件这里详细说说。pid文件是nginx用来保存master进程PID的。每次nginx启动都会把PID写入这个文件每次正常退出会删除这个文件。但如果nginx被kill -9强杀或者系统异常断电pid文件就可能残留或者丢失。残留的情况你执行nginx -s stop时报错nginx: [error] open() /usr/local/nginx/logs/nginx.pid failed (2: No such file or directory)说明pid文件不存在但nginx进程可能还在运行因为异常退出时pid文件被删了。这时候直接通过nginx命令行工具没法向master进程发信号了因为找不到PID。处理办法是手动找到master进程的PIDps -ef | grep nginx第一行就是master进程记下PID然后手动发送信号# 优雅停止 sudo kill -QUIT PID # 快速停止 sudo kill -TERM PID如果根本没有任何nginx进程在运行那就直接删除可能残留的pid文件然后正常启动即可sudo rm -f /usr/local/nginx/logs/nginx.pid sudo /usr/local/nginx/sbin/nginx这里给一个建议源码安装nginx时最好统一在nginx.conf里显式指定pid文件的路径比如pid /var/run/nginx.pid;这样pid文件就固定在一个规范位置既方便日志收集也方便systemd和监控脚本去读取。修改之后记得先关闭nginx再改配置然后重新启动这样新的pid路径才会生效。5.2 端口被占用Address already in use启动nginx报错bind() to 0.0.0.0:80 failed (98: Address already in use)核心意思是80端口被占用了。这种情况最常见的几种原因nginx已经在运行你重复启动了。这时候ps -ef | grep nginx能看到有nginx进程。其他Web服务占用了80端口比如Apache、Tomcat、Caddy等。系统里有一些隐性占用比如Docker的端口映射、虚拟机的端口转发。排查命令三板斧# 查看80端口被谁占用 ss -tlnp | grep :80 # 或者 netstat -tlnp | grep :80 # 查看占用端口的进程详情 lsof -i :80明确占用者后要么停掉旧服务要么修改nginx监听端口比如改为8080。这里要特别提醒一下如果是云服务器改了端口后云安全组规则也要同步调整否则外部依然访问不了。5.3 reload不生效的几个常见坑有时候你改了配置文件执行了nginx -s reload没有报错但访问到的内容还是旧的。这种“静默不生效”比报错更让人抓狂。第一个可能你改的不是nginx真正读取的配置文件。比如nginx是用/etc/nginx/nginx.conf作为主配置启动的但你改的是/usr/local/nginx/conf/nginx.conf那当然不生效。怎么确认先看nginx进程启动时用的配置路径ps -ef | grep nginxmaster进程的启动参数里通常会带-c参数指向具体的配置文件路径。然后用nginx -T也能够输出当前生效的完整配置。最彻底的办法是执行sudo nginx -T | head -n 30看输出里include了哪些文件再确认你修改的文件是否在这些include列表中。第二个可能配置里有语法错误但你没有先执行nginx -t。前面说过reload遇到配置错误时会静默失败或者打印一段错误后继续用旧配置。所以如果你觉得“明明reload了怎么没反应”第一步就是执行nginx -t看test是否通过。如果不通过根据错误提示定位到具体行号修改。这一步最简单但很多人就是会跳过。第三个可能是浏览器缓存或者CDN缓存。nginx配置本身已经生效了但浏览器端缓存了旧响应。这种情况在调试静态资源时特别常见。处理方式是强制刷新CtrlF5或者用curl直接请求服务器看响应头curl -I http://127.0.0.1/your-path如果服务器返回的响应头、内容已经是新的那问题就在浏览器或者中间层缓存和nginx无关。5.4 systemctl相关命令报错的排查思路使用systemd管理nginx时常见的报错有几种我直接列出排查思路你照着走一遍基本能定位。systemctl start nginx后长时间卡住或者报Job for nginx.service failed because the control process exited with error code大概率是ExecStartPre里的nginx -t没有通过或者nginx二进制路径有问题。查看详细日志sudo journalctl -u nginx.service -n 50 --no-pagersystemctl enable nginx报Failed to create symlink通常是/etc/systemd/system/multi-user.target.wants/目录权限异常或者nginx.service文件本身不存在。确认service文件位置是否正确然后重新执行enable。systemctl reload nginx报Job type reload is not applicable for unit nginx.service说明你的nginx.service文件里没有定义ExecReload指令。解决办法是编辑service文件添加ExecReload/usr/bin/nginx -s reload之类的行然后daemon-reload。nginx被systemd反复拉起但每次都是启动失败优先查看日志nginx的错误日志默认在/usr/local/nginx/logs/error.log或者/var/log/nginx/error.log和systemd的journal日志都会给出线索。5.5 日志文件不更新的问题这个问题和重启/自启动关系不大但我在实际项目里经常遇到顺手写一下。如果你发现nginx的access.log一直不更新一种可能是nginx没有收到任何请求但更常见的是日志文件被切割或者转移后nginx还是往旧的已删除文件句柄里写。日志切割场景下执行nginx -s reopen让nginx重新打开日志文件句柄。如果你配置了logrotate那在日志轮转后一般会自动执行reopen操作。如果你手动处理日志迁移记得执行reopen否则磁盘空间会被已删除文件占着不释放。这个用lsof | grep deleted可以看到。6. 实操场景反向代理、多站点部署时的重启注意事项前面讲的都是基础的启停和自启动操作但实际项目中nginx很少只做一个简单的静态Web服务器。下面结合常见的反向代理、多站点部署场景说说哪些操作习惯更稳妥。6.1 修改反向代理配置后的正确操作假设你用nginx做反向代理后端是Java应用或者Node服务配置大致是server { listen 80; server_name app.example.com; location / { proxy_pass http://backend_upstream; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } upstream backend_upstream { server 192.168.1.10:8080 weight5; server 192.168.1.11:8080 weight3; }这种情况下修改proxy_pass、upstream里的后端地址、超时时间等用nginx -s reload即可。但如果修改了listen端口、或者修改了server_name建议restart。为什么server_name修改也要restart严格来说server_name不涉及端口和socketreload是可以生效的但如果你同时修改了listen那肯定要重启。另外有时候新增一个server块时如果新server监听的端口是之前没有监听过的也必须restart因为nginx不会在reload时创建新的监听socket。有一个需要注意的点upstream后端列表的变更尽量在业务低峰期操作。即使reload是无损的新的后端连接池要重新建立如果后端服务刚好在高负载状态下可能会出现短暂的延迟波动。6.2 部署多个Web项目时的自启动取舍nginx部署多个Web项目本质上就是配置多个server块。其中一个项目挂了不应该影响其他项目的访问nginx在这方面做得很好各个server之间天然隔离。但如果你在同一个server里用多个location来代理不同项目只要其中一个location对应的后端挂了其他location的请求还是正常的这也是nginx的优势。在这种多项目部署模式下自启动设置其实没有额外的复杂点。你只需要保证nginx本身开机自启动所有server块的配置都会随之生效。但有一个实践建议多个项目共用一套nginx时把配置拆成单独文件管理比如/etc/nginx/conf.d/project-a.conf、/etc/nginx/conf.d/project-b.conf主配置文件里通过include /etc/nginx/conf.d/*.conf;引入。这样后面对单个项目做修改只需reload不用动主配置。6.3 nginx配合Docker容器场景下的启停现在很多人的服务都用Docker跑nginx既有直接用宿主机装的也有容器化部署的。如果你用Docker启动nginx对应的启停、自启动方式又不一样# 启动容器 docker run -d --name nginx-app -p 80:80 -v /some/nginx.conf:/etc/nginx/nginx.conf:ro nginx # 重启容器 docker restart nginx-app # 停止/启动容器 docker stop nginx-app docker start nginx-appDocker容器是否开机自启动取决于创建容器时有没有加--restart参数# 开机自启动且如果容器异常退出会自动拉起 docker run -d --restartalways --name nginx-app -p 80:80 nginx这里的关键点是如果容器内的服务异常退出--restartalways会尝试无限次重启容器但如果你手动docker stop了容器Docker不会自动把它拉起来。另外一个细节是容器里的nginx配置文件和宿主机是隔离的修改配置后一般要重新加载或者重建容器。具体操作上不重建容器的话可以进入容器内部执行nginx reloaddocker exec nginx-app nginx -s reload但如果你的nginx.conf是通过挂载卷挂进去的改挂载目录里的文件再执行reload就可以了。7. 从“能用”到“好用”我给新手的几个操作习惯建议文章写到这基础的启停、重载、自启动的操作都已经覆盖了。最后分享几个我这几年的实操习惯算是一些心得。第一所有配置文件修改之前先备份。不要只在本地副本备份在线上的服务器上也要有备份。我惯用的做法sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak.$(date %F_%H%M%S)这样改坏了能快速回滚心里不慌。第二修改配置之后养成三步检查的习惯先nginx -t验证语法、再systemctl reload nginx或nginx -s reload加载新配置、最后用curl或者页面访问验证服务是否正常。这套流程走下来线上出问题的概率会下降一个量级。第三管理nginx时能用systemd就用systemd尽量避免直接操作进程信号。理由很简单systemd的状态跟踪、日志收集、开机自启、失败重启都是自动化的你手动向master进程发信号等于绕过了这一层出了问题连日志都不好查。第四新建的systemd service文件注意设置Afternetwork-online.target并且确认systemctl status nginx里显示的running状态是稳定的。有些环境里因为网络初始化慢了一步nginx在没有网络时就尝试启动结果域名解析失败导致启动报错。这个坑不算常见但遇到了会很头疼。第五对于源码编译安装的nginx管理上要习惯写绝对路径。不仅systemd service里要用绝对路径日常手敲命令时也尽量用绝对路径或者把nginx的sbin目录加到/etc/profile.d/nginx.sh中echo export PATH/usr/local/nginx/sbin:$PATH | sudo tee /etc/profile.d/nginx.sh然后在新的shell里执行source /etc/profile.d/nginx.sh之后直接敲nginx命令就能被识别。这篇文章从nginx的进程模型和信号机制讲起覆盖了启动、停止、重启、reload等日常操作也详细说明了systemd下自启动配置的写法与坑点最后补充了几个常见问题的排查思路。只要你照着操作一遍再遇到nginx管理类的问题基本都能自己解决。
返回列表