kill
kill 用于向进程发送信号。名字有误导性 —— 它的本职是发信号,终止进程只是其中最常用的一种。
kill [-信号] PID...kill -l不指定信号时发的是
TERM(15) 只能给自己有权限的进程发信号,别人的进程需要 root
信号是内核提供的一种异步通知机制。进程可以为大多数信号注册处理函数,收到时先跑自己的清理逻辑再退出;没注册的就执行内核规定的默认行为。
常用信号:
| 编号 | 名字 | 默认行为 | 能否被捕获 |
|---|---|---|---|
| 1 | HUP | 终止 | 能。守护进程通常把它约定成「重新读配置」 |
| 2 | INT | 终止 | 能。等同 Ctrl-C |
| 3 | QUIT | 终止并转储 core | 能。等同 Ctrl-\ |
| 9 | KILL | 立即终止 | 不能 |
| 15 | TERM | 终止 | 能。默认信号,给进程留出收尾的机会 |
| 18 | CONT | 继续运行 | 能 |
| 19 | STOP | 暂停 | 不能 |
| 20 | TSTP | 暂停 | 能。等同 Ctrl-Z |
KILL和STOP是仅有的两个不能被捕获、阻塞或忽略的信号,由内核直接执行 也正因如此,kill -9之后进程没有任何机会关文件、写日志、删临时文件、释放锁
| 选项 | 说明 |
|---|---|
-l |
列出所有信号名和编号 |
-<编号> |
按编号指定信号,如 -9 |
-<名字> |
按名字指定,如 -TERM、-HUP |
-s <名字> |
同上,写法更正式 |
-0 |
什么都不发,只检查进程是否存在、自己有没有权限 |
1. 终止进程的正确顺序
kill 1234 # 先发 TERM,让进程自己收尾kill -9 1234 # 等一会儿仍在,才上 KILL直接
-9是坏习惯:数据库来不及刷盘、编辑器留下交换文件、服务留下 pid 文件和锁 给几秒钟,TERM 处理不完再考虑 KILL
2. 让守护进程重读配置
kill -HUP $(cat /var/run/nginx.pid)HUP 的这个含义是约定俗成的,不是内核规定的,具体行为看程序自己的文档
3. D 状态的进程杀不掉
ps -o pid,stat,comm -p 1234
STAT显示D时进程卡在不可中断的内核态,通常是等一个出问题的 IO 这种情况-9也没用,信号要等进程回到用户态才会被处理 只能等 IO 超时,或者去修 IO 那一头(比如断掉的 NFS 挂载),见 ps
4. 按名字发信号
pkill nginxkillall nginxpkill -u alice -f 'python.*worker'
pkill和killall也是发信号,信号选项的写法和 kill 一致-f匹配完整命令行,不加则只匹配进程名 动手之前先用pgrep -a同样的条件跑一遍,确认匹配到的就是你想杀的
5. 发给整个进程组
kill -- -1234PID 写成负数表示进程组号,组内所有进程都会收到
--是为了让负号不被当成选项
6. 只检查进程还在不在
kill -0 1234 && echo "还活着"
-0不发任何信号,只做存在性和权限检查,脚本里常用来轮询等待进程退出
man 1 killman 7 signal(信号的完整列表和语义)