kill 命令详解
更新时间:2026-08-29。本文是「一个命令一个文档」系列,属于进程管理命令。服务卡死要停,
kill是标准手段,但kill -9用错了会丢数据。
为什么写 kill?因为太多人把 kill -9 当万能键,结果数据库没刷盘、锁文件残留、子进程变孤儿。理解"信号"的本质——kill 不是"杀",是"发个消息让进程自己处理"——才能用对。SIGTERM 是礼貌请离,SIGKILL 是直接断电。
kill 向进程发送信号(signal,一个整数编号的事件)。默认发 SIGTERM(15),进程可捕获并优雅退出;SIGKILL(9) 内核直接终止,进程无机会清理。
一、最基本的用法
kill 1234 # 向 PID 1234 发 SIGTERM(15),请求退出
kill -9 1234 # 发 SIGKILL(9),强制立刻杀,进程无法反抗
kill -TERM 1234 # 等价 kill 1234,用名字更可读关键认知:
kill默认是"请退出"不是"立刻死"。多数程序收到 SIGTERM 会做收尾(关连接、刷盘、删 pid 文件)再走。只有 SIGTERM 无效(进程卡死/忽略)才上 SIGKILL。
二、常用信号列表
kill -l 可列出全部(1~64 取决于架构),最常用的几个:
| 信号 | 编号 | 含义 | 典型用途 |
|---|---|---|---|
SIGHUP | 1 | 挂断 | 守护进程重读配置(如 nginx reload) |
SIGINT | 2 | 中断 | Ctrl+C 发的就是它 |
SIGQUIT | 3 | 退出+核心转储 | Ctrl+\ |
SIGKILL | 9 | 强制终止,不可捕获 | 进程无清理机会,最后手段 |
SIGTERM | 15 | 终止(默认),可捕获 | 礼貌请求退出 |
SIGSTOP | 19 | 暂停(不可捕获) | Ctrl+Z 发的 |
SIGCONT | 18 | 继续 | 恢复被 STOP 的 |
SIGUSR1/2 | 10/12 | 用户自定义 | 程序自定义动作(如重新打开日志) |
记住两个数字就够:
15(默认,友好)和9(强杀,粗暴)。kill -l随时查全表。
三、高频选项一张表
| 用法 | 作用 |
|---|---|
kill PID | 发 SIGTERM(默认 15) |
kill -9 PID | 发 SIGKILL,强杀 |
kill -s TERM PID / kill -TERM | 用名字发信号 |
kill -l | 列出所有信号 |
kill 0 | 向当前进程组所有进程发信号 |
kill -PID(负 PID) | 向 PID 的进程组发(如 kill -1234 杀组 1234 全部) |
kill -1 PID | 发 SIGHUP,常触发重读配置 |
四、实战 demo
demo 1:优雅停掉一个服务(首选 SIGTERM)
kill 1234 # 发 SIGTERM,进程自己收尾后退出
sleep 2
ps -p 1234 > /dev/null && echo "还没退,考虑 -9" || echo "已退出"demo 2:SIGTERM 无效,升级 SIGKILL
kill -9 1234 # 仅当 SIGTERM 等了仍不死才用
# 注意:-9 后进程来不及删 pid 文件/关连接,可能需手动清理demo 3:让 nginx 重新加载配置(不中断服务)
kill -HUP $(cat /run/nginx.pid) # 或 nginx -s reload
# SIGHUP 让主进程重读配置、平滑起新 worker,老请求处理完再退demo 4:杀掉整个进程组(父+所有子)
kill -- -1234 # 注意前面的 -- 和负号:向进程组 1234 全部发 SIGTERM
# 或 kill -TERM -1234;避免只杀父、子变孤儿继续跑demo 5:按名批量杀(配合 pgrep/pkill)
pkill -f "python app.py" # 按完整命令行匹配杀,见 pkill
kill $(pgrep -u www php) # pgrep 找 PID 喂给 kill,见 pgrepdemo 6:向自己所在进程组广播(脚本退出清理)
trap 'kill 0' EXIT # 脚本退出时,向本进程组所有子进程发 SIGTERM
# 防止脚本结束留下后台子进程孤儿五、为什么 -9 不是首选
SIGKILL(9) 让内核直接回收进程,进程没有任何运行代码的机会:
- 来不及刷盘/写日志 → 数据丢失、文件半截。
- 来不及删 pid 文件/释放锁 → 重启时报"已在运行"。
- 子进程变孤儿,被 init 接管继续跑,占用端口/资源。
- 共享内存/信号量可能残留。
所以正确顺序是:先 kill(SIGTERM)等几秒 → 仍存活才 kill -9。很多服务(systemd/docker)的 stop 命令内部就是这个逻辑。
六、和 pkill / killall 的关系
- pkill:按名字/模式杀,不用先查 PID,见 pkill。
- killall:按程序名杀全部同名进程(
killall nginx),部分系统行为略有差异。 - 它们底层都是发信号,和
kill是同一套机制,只是选目标的方式不同。
pkill -9 nginx # 强制杀所有 nginx(紧急时)
killall php-fpm # 按名杀七、常见坑
kill -9不是"更强",是"更粗暴且无清理",能不用就不用。- 杀进程组要用负号
kill -1234(组 ID)或kill -- -1234,单kill 1234只杀父。 kill自己没权限的进程(别人的、root 的)会Operation not permitted,需 sudo。- 僵尸进程(STAT=Z)
kill -9无效——它已死,要重启其父进程。 kill 0会连自己一起杀,脚本里用trap要小心作用范围。
八、一条完整的"进程失控"排障链路
把 kill 放进取实际排障流程里才显出价值,下面这套顺序几乎每天都会用到:
# 1. 谁在吃资源?top 里按 P 找到 PID
top -b -n 1 | head -12
# 2. 确认它是不是真失控(是不是僵尸/是不是 D 状态卡 IO)
ps -o pid,stat,etime,cmd -p 1234
# 3. 礼貌请退,等 3 秒
kill 1234; sleep 3
# 4. 还活着?看它卡在哪(打开的文件/连接没释放)
lsof -p 1234
# 5. 确认真的赖着不走,才强杀并清进程组
kill -9 -1234这条链路的精华在第 4 步:强杀前先 lsof 看进程还占着什么,能避免"杀了之后端口还被占着、重启报 bind 失败"的连锁问题。信号机制本身很简单,难的是"杀之前先判断该不该杀、杀完会不会留尾巴"。
九、信号清单速查(最常用的几个)
| 信号 | 编号 | 典型用途 |
|---|---|---|
| SIGHUP | 1 | 重载配置(nginx/sshd 常见) |
| SIGINT | 2 | 终端 Ctrl+C,前台进程中断 |
| SIGQUIT | 3 | 类似 INT 但产生 core dump |
| SIGKILL | 9 | 强制终止,不可捕获 |
| SIGTERM | 15 | 默认,礼貌请求退出 |
| SIGSTOP | 19 | 暂停(不可捕获,fg 恢复) |
| SIGCONT | 18 | 继续被 STOP 的进程 |
记住两个"不可捕获":SIGKILL(9) 和 SIGSTOP(19) 进程无法拦截,所以 -9 一定能杀掉(除非是 D 状态卡内核 IO,那种连 -9 也无奈,只能解决底层存储)。
相关命令
一句话总结
kill = 向进程发信号(非直接杀):默认 SIGTERM(15) 礼貌请退、进程可清理;SIGKILL(9) 内核强杀、无清理机会(丢数据/留孤儿),仅当 SIGTERM 无效才用;SIGHUP(1) 常触发重载配置;杀进程组用 kill -- -PGID;按名杀换 pkill。