第 6 章 · 04 信号与终止: 、 、 本节摘要: 是 Linux 里最被误解的命令之一——它的名字叫「杀死」,但它的本职其实是「发信号」。 默认发的是 SIGTERM(请求退出),不是 SIGKILL(强杀);进程收到 SIGTERM 可以选择优雅清理后再退,也可以忽略。本节要把信号机制讲透: / / 三者的差别、SIGTERM 与 SIGKILL 的关键区别(为什么优先 SIGTERM)、常用信号各是什么意思。理解了信号,你才懂得「优雅退出」与「强制终止」的边界,不再无脑 。 内容来源:原项目「Linux 命令大全」 、 、 ,精选并套用体系化模板。 学习目标 阅读完本节,你应当能够: 说清 的本质是「发信号」而非「杀死」;默认发 SIGTERM(15)。
kill、killall、pkill本节摘要:
kill是 Linux 里最被误解的命令之一——它的名字叫「杀死」,但它的本职其实是「发信号」。kill 1234默认发的是 SIGTERM(请求退出),不是 SIGKILL(强杀);进程收到 SIGTERM 可以选择优雅清理后再退,也可以忽略。本节要把信号机制讲透:kill/killall/pkill三者的差别、SIGTERM 与 SIGKILL 的关键区别(为什么优先 SIGTERM)、常用信号各是什么意思。理解了信号,你才懂得「优雅退出」与「强制终止」的边界,不再无脑kill -9。
内容来源:原项目「Linux 命令大全」
command/kill.md、command/killall.md、command/pkill.md,精选并套用体系化模板。
阅读完本节,你应当能够:
kill 的本质是「发信号」而非「杀死」;默认发 SIGTERM(15)。kill PID(按 PID)、killall 名字(按命令名)、pkill 模式(按模式匹配)三种方式定位进程。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 |
- | 用户自定义(程序自己定义用途) | 能 |
几个要点:
kill -HUP $(pidof nginx) 是平滑重载的标准做法。kill -INT 自己。kill 1234 # 给 PID 1234 发 SIGTERM kill -9 1234 # 强杀 kill -l # 列出所有信号名与编号(记不住时查这个)
kill 精确,但你需要先知道 PID(通常先 ps aux | grep 查)。
killall nginx # 给所有命令名是 "nginx" 的进程发 SIGTERM killall -9 chrome # 强杀所有 chrome killall -u user # 杀某用户的所有进程
killall 按名字批量,不用先查 PID。但要注意:它是「精确匹配命令名」,不是模糊匹配。
pkill -f 'python.*train' # 按完整命令行正则匹配, 杀匹配的进程 pkill -u user # 杀某用户的所有进程 pkill -t pts/0 # 杀某终端的所有进程(踢人)
pkill 比 killall 更灵活(支持正则、支持按用户/终端过滤)。-f 表示匹配整个命令行(而非只匹配命令名),能处理「带参数」的情况。
⚠️ 注意:
pkill -f 'xxx'用正则匹配,范围容易扩得太大。发送前先用pgrep -f 'xxx'(pkill 的无害版,只打印不杀)预览会杀哪些进程,确认后再 pkill。
kill -9 导致数据损坏kill -9 $(pidof mysqld) # 危险! 数据库没机会刷盘, 可能损坏数据 kill $(pidof mysqld) # 对! 先 SIGTERM, 让它优雅退出
数据库、消息队列、有状态服务,务必先 SIGTERM 给它清理机会。只有 SIGTERM 无响应(等了几十秒还在)才升级到 SIGKILL。
kill -9 也杀不掉的进程D 状态(不可中断睡眠)的进程,kill -9 也不生效——因为信号要进程被调度时才处理,而 D 状态进程在内核里等 IO,暂时调度不了。解法见第 03 节(查 /proc/PID/stack 或解决底层 IO 问题)。
killall python # 会杀掉系统里所有名为 python 的进程, 包括别人的! pkill -f ssh # 会杀掉所有命令行含 ssh 的进程, 包括你的 ssh 连接!
批量 kill 范围广,误杀风险高。养成习惯:先 pgrep/ps 预览,再 kill。生产环境尤其谨慎。
kill -l 查信号编号kill -l # 列出所有信号: HUP INT QUIT ILL ... KILL ... TERM ...
记不住信号编号时,kill -l 列全部;用 kill -TERM(名字)比 kill -15(数字)更可读。
kill 的本质是「发信号」,默认发 SIGTERM(15)请求退出,不是「强杀」。kill -9,否则可能数据损坏。kill PID(精确)、killall 名字(按命令名批量)、pkill 模式(正则,最灵活)。kill -9 都无效。下一节讲后台作业管理——&、jobs、bg/fg、nohup,以及它们与信号的关系(尤其为什么终端关闭会让后台进程死掉)。