别一上来就 kill -9:先看信号、再看进程树,优雅停服务
别一上来就 kill -9:先看信号、再看进程树,优雅停服务
服务卡住了,很多人第一反应是 kill -9 进程号,确实立竿见影,但也最容易留后遗症:没写完的文件截断一半、数据库事务没提交、临时文件和锁没清理,下次启动反而报错。本文讲一个更稳的停服务顺序:先看清进程树,再按信号从轻到重试,最后才用 -9 兜底。
第一步:先看进程树,别杀错进程
动手前先确认到底是谁在跑。ps aux | grep 服务名 只能看到一行行散的进程,分不清父子关系;换成 ps -ef --forest 或者 pstree -p,一眼就能看出主进程和它拉起来的子进程。只杀子进程,主进程可能马上又拉起一个;只杀主进程,孤儿进程可能继续占着端口和内存。
再确认进程到底在干什么。ps -o pid,ppid,stat,cmd -p 进程号 看状态:R 是正在跑,S 是在等事件,D 是在等磁盘 I/O,Z 是僵尸进程。D 状态的进程即使发信号也不会立刻响应,因为它卡在内核的 I/O 路径上,这时反复 kill 没有意义,先查磁盘和 I/O 才是正路;Z 状态的进程已经死了,杀它也没用,得去找它的父进程回收。
第二步:信号从轻到重,别跳级
Linux 的终止信号是有梯度的。默认的 kill 进程号 发的是 SIGTERM(15),意思是“请你自己收拾好再退出”,服务收到后可以刷盘、关连接、删临时文件,这是最体面的停法。先发一次 SIGTERM,等几秒,再用 ps -p 进程号 看它还在不在。
如果服务对 SIGTERM 没反应,再试 SIGINT(2),相当于在终端按 Ctrl+C,有些服务只处理这个信号。命令是 kill -INT 进程号。还不行,再考虑 SIGQUIT(3),它会让进程退出并生成 core dump,适合需要留现场排查的情况,但平时不要滥用,core 文件可能很大。
只有前面都试过、服务确实僵死不动,才轮到 SIGKILL(9),也就是 kill -9。它是内核直接动手,进程连清理的机会都没有,所以只能当最后手段,不能当日常操作。记住顺序:TERM → INT → QUIT → KILL,每一步之间留几秒观察,别一口气全发出去。
第三步:端口和残留要复查
进程退出了不代表现场干净了。先查端口是不是真的放出来了:ss -tlnp | grep 端口号,如果还有进程占着,说明杀错了对象或者有子进程残留,顺着进程树再找一遍。再查服务自己的数据目录有没有 .lock、.pid 残留文件,有些服务启动时会先检查锁文件,旧的锁没清掉,新进程会以为“已经有一个实例在跑”而拒绝启动。
如果服务是用 systemd 管的,优先用 systemctl stop 服务名 而不是直接 kill。systemd 知道整个进程组,会按配置的停止方式和超时处理,停不掉时它自己会升级手段;直接 kill 绕过了 systemd,它可能按 Restart 策略又把服务拉起来,你会看到“杀了又活”的怪现象。查状态用 systemctl status 服务名,看最后几行日志确认它到底卡在哪一步。
收尾自查清单:先 pstree -p 确认父子关系,再按 TERM、INT、QUIT、KILL 的顺序发信号、每步等几秒,最后 ss 查端口、systemctl status 查服务状态。把 kill -9 留到最后,你的服务和数据都会少受很多罪。
- 点赞
- 收藏
- 关注作者
评论(0)