第 6 章 · 04 信号与终止:`kill`、`killall`、`pkill`


文档摘要

第 6 章 · 04 信号与终止: 、 、 本节摘要: 是 Linux 里最被误解的命令之一——它的名字叫「杀死」,但它的本职其实是「发信号」。 默认发的是 SIGTERM(请求退出),不是 SIGKILL(强杀);进程收到 SIGTERM 可以选择优雅清理后再退,也可以忽略。本节要把信号机制讲透: / / 三者的差别、SIGTERM 与 SIGKILL 的关键区别(为什么优先 SIGTERM)、常用信号各是什么意思。理解了信号,你才懂得「优雅退出」与「强制终止」的边界,不再无脑 。 内容来源:原项目「Linux 命令大全」 、 、 ,精选并套用体系化模板。 学习目标 阅读完本节,你应当能够: 说清 的本质是「发信号」而非「杀死」;默认发 SIGTERM(15)。

第 6 章 · 04 信号与终止:killkillallpkill

本节摘要:kill 是 Linux 里最被误解的命令之一——它的名字叫「杀死」,但它的本职其实是「发信号」。kill 1234 默认发的是 SIGTERM(请求退出),不是 SIGKILL(强杀);进程收到 SIGTERM 可以选择优雅清理后再退,也可以忽略。本节要把信号机制讲透:kill/killall/pkill 三者的差别、SIGTERM 与 SIGKILL 的关键区别(为什么优先 SIGTERM)、常用信号各是什么意思。理解了信号,你才懂得「优雅退出」与「强制终止」的边界,不再无脑 kill -9

内容来源:原项目「Linux 命令大全」command/kill.mdcommand/killall.mdcommand/pkill.md,精选并套用体系化模板。

学习目标

阅读完本节,你应当能够:

  1. 说清 kill 的本质是「发信号」而非「杀死」;默认发 SIGTERM(15)。
  2. 区分 SIGTERM(15,请求退出,可被捕获/忽略)与 SIGKILL(9,强杀,不可阻挡)。
  3. 解释为什么生产环境应优先 SIGTERM(给程序清理机会),SIGKILL 是最后手段。
  4. kill PID(按 PID)、killall 名字(按命令名)、pkill 模式(按模式匹配)三种方式定位进程。
  5. 记住常用信号:SIGTERM(15)、SIGKILL(9)、SIGHUP(1,重载)、SIGINT(2,Ctrl+C)、SIGSTOP/SIGCONT(暂停/恢复)。

一、设计动机:kill 其实是「信号发射器」

很多人敲 kill 1234 以为是在「杀死 1234」,这个认知只对了一半。kill 干的事是:给进程 1234 发一个信号。默认发的是 SIGTERM(信号编号 15),它的语义是「请求你退出」——进程收到后,可以执行自己的清理逻辑(关闭文件、保存状态、通知其他服务)然后退出,也可以选择忽略(比如 vim 收到 SIGTERM 会先问你要不要保存)。

真正「不可阻挡的杀死」是 SIGKILL(9):kill -9 1234。内核收到这个信号,直接把进程干掉,进程没机会清理。这就是为什么 SIGKILL「绝对有效」但也「危险」——资源可能没释放、数据可能没落盘。

kill 1234 # 默认发 SIGTERM(15), 请求退出, 进程可清理/可忽略 kill -15 1234 # 显式发 SIGTERM, 等价上一行 kill -9 1234 # 发 SIGKILL, 强杀, 进程立刻消失, 无清理机会 kill -TERM 1234 # 用信号名也行, 更可读

关键概念:优先用 SIGTERM(kill 1234),SIGKILL(kill -9)是最后手段。生产环境里,直接 kill -9 数据库、消息队列等服务,可能导致数据损坏——它们没机会把内存里的数据刷盘。

二、常用信号速查

信号 编号 含义 能否被捕获/忽略
SIGHUP 1 挂起(原指终端断开;现常用于「重载配置」)
SIGINT 2 中断(Ctrl+C 触发)
SIGTERM 15 终止请求(默认,推荐)
SIGKILL 9 强制杀死(最后手段) 不能
SIGSTOP 19 暂停(不可恢复自己) 不能
SIGCONT 18 继续(恢复暂停的进程)
SIGUSR1/2 - 用户自定义(程序自己定义用途)

几个要点:

  • SIGKILL(9)和 SIGSTOP(19)不能被捕获或忽略——这是内核保证的「管理员终极手段」。D 状态除外(连 SIGKILL 也得等它从内核 IO 返回)。
  • SIGHUP「重载配置」的用法:很多服务(Nginx、sshd)收到 SIGHUP 会重新读配置文件而不重启,kill -HUP $(pidof nginx) 是平滑重载的标准做法。
  • Ctrl+C 其实就是发 SIGINT(2),等同于 kill -INT 自己

三、三种 kill 的差别

kill:按 PID

kill 1234 # 给 PID 1234 发 SIGTERM kill -9 1234 # 强杀 kill -l # 列出所有信号名与编号(记不住时查这个)

kill 精确,但你需要先知道 PID(通常先 ps aux | grep 查)。

killall:按命令名

killall nginx # 给所有命令名是 "nginx" 的进程发 SIGTERM killall -9 chrome # 强杀所有 chrome killall -u user # 杀某用户的所有进程

killall 按名字批量,不用先查 PID。但要注意:它是「精确匹配命令名」,不是模糊匹配。

pkill:按模式匹配

pkill -f 'python.*train' # 按完整命令行正则匹配, 杀匹配的进程 pkill -u user # 杀某用户的所有进程 pkill -t pts/0 # 杀某终端的所有进程(踢人)

pkillkillall 更灵活(支持正则、支持按用户/终端过滤)。-f 表示匹配整个命令行(而非只匹配命令名),能处理「带参数」的情况。

⚠️ 注意:pkill -f 'xxx' 用正则匹配,范围容易扩得太大。发送前先用 pgrep -f 'xxx'(pkill 的无害版,只打印不杀)预览会杀哪些进程,确认后再 pkill。

四、踩坑与排错

坑 1:无脑 kill -9 导致数据损坏

kill -9 $(pidof mysqld) # 危险! 数据库没机会刷盘, 可能损坏数据 kill $(pidof mysqld) # 对! 先 SIGTERM, 让它优雅退出

数据库、消息队列、有状态服务,务必先 SIGTERM 给它清理机会。只有 SIGTERM 无响应(等了几十秒还在)才升级到 SIGKILL。

坑 2:kill -9 也杀不掉的进程

D 状态(不可中断睡眠)的进程,kill -9 也不生效——因为信号要进程被调度时才处理,而 D 状态进程在内核里等 IO,暂时调度不了。解法见第 03 节(查 /proc/PID/stack 或解决底层 IO 问题)。

坑 3:killall/pkill 误杀

killall python # 会杀掉系统里所有名为 python 的进程, 包括别人的! pkill -f ssh # 会杀掉所有命令行含 ssh 的进程, 包括你的 ssh 连接!

批量 kill 范围广,误杀风险高。养成习惯:先 pgrep/ps 预览,再 kill。生产环境尤其谨慎。

坑 4:kill -l 查信号编号

kill -l # 列出所有信号: HUP INT QUIT ILL ... KILL ... TERM ...

记不住信号编号时,kill -l 列全部;用 kill -TERM(名字)比 kill -15(数字)更可读。

本节要点回顾

  1. kill 的本质是「发信号」,默认发 SIGTERM(15)请求退出,不是「强杀」
  2. SIGTERM(15)可被捕获/忽略,程序能优雅清理;SIGKILL(9)不可阻挡,是最后手段,程序无清理机会
  3. 生产优先 SIGTERM,数据/有状态服务千万别直接 kill -9,否则可能数据损坏。
  4. SIGHUP(1)常用于「重载配置」(Nginx 等服务),Ctrl+C = SIGINT(2)。
  5. 三种 kill:kill PID(精确)、killall 名字(按命令名批量)、pkill 模式(正则,最灵活)。
  6. 批量 kill 前先预览(pgrep/ps),避免误杀;D 状态进程连 kill -9 都无效。

下一节讲后台作业管理——&jobsbg/fgnohup,以及它们与信号的关系(尤其为什么终端关闭会让后台进程死掉)。


发布者: 作者: 灏天文库 转发
评论区 (0)
U