Linux 中使用 killall 命令按名称终止进程

当某个程序运行失常时,它可能会留下多个仍在运行的进程。现代浏览器会启动各自独立的 worker 进程,而一个卡住的脚本也可能在多个终端里被反复启动。如果要用 kill 命令逐一终止它们,你得先查出每一个 PID。而 killall 命令省掉了这一步:你只需给出进程名,它就会向所有使用这个名字运行的进程发送信号。

本指南介绍如何使用 killall 按名称终止进程、选择要发送的信号,以及按用户、运行年龄或匹配模式来缩小目标范围。

安装 killall

killallpsmisc 软件包的一部分,在大多数桌面和服务器发行版中已预装。如果系统中没有该命令,可从标准仓库安装。

在 Ubuntu、Debian 及其衍生版上:

sudo apt install psmisc

在 Fedora、RHEL 及其衍生版上:

sudo dnf install psmisc

警告:在 Linux 上,psmisc 版本的 killall 只影响与给定名称匹配的进程;而在某些其他 Unix 系统(如 Solaris 和 AIX)中,killall 会向机器上几乎每一个进程发送信号——那些系统在关机时正是靠它来结束所有进程的。在远程系统(尤其是以 root 身份)运行 killall 之前,请先确认安装的是哪个实现。

killall 语法

killall 命令的一般语法如下:

killall [OPTIONS] NAME...

NAME 是要匹配的进程名。你可以传入多个名称,killall 会向匹配其中任意一个名称的所有进程发送信号。与 pkill 匹配部分名称不同,killall 要求名称完全匹配。

当你提供的每个名称都至少成功信号到一个进程时,killall 以状态码 0 退出。如果某个名称没有匹配到,它会打印一条消息并以非零状态返回:

killall firefox
firefox: no process found

按名称终止进程

要终止一个进程,传入它的确切名称即可:

killall firefox

默认情况下,killall 发送 SIGTERM 信号,请求每个匹配的进程干净地关闭。命令成功时不产生任何输出。加上 -v 可以确认具体信号了哪些进程:

killall -v vlc
Killed vlc(8143) with signal 15

输出显示了进程名、PID 和信号编号。信号 15 即 SIGTERM

在发送信号之前,可以用 pgrep 预览精确匹配及其完整命令行:

pgrep -a -x firefox

如果该命令没有输出,可以查看 ps -e -o pid,comm 来查找 Linux 报告的进程名。

发送特定信号

当进程忽略 SIGTERM 时,你可以发送一个更强的信号。-s 选项接受信号名或信号编号:

killall -s KILL myscript

SIGKILL 既不能被捕获也不能被忽略,因此进程会被立即终止,没有机会做清理工作。同一个信号还有两种更简短的写法:

killall -9 myscript
killall -SIGKILL myscript

只有在普通 killall 已经失败之后,才使用 SIGKILL。以这种方式被杀死的进程无法刷新缓冲区或删除其临时文件,这也是为什么先尝试 SIGTERM 是更安全的习惯。关于各类信号以及何时使用的深入讨论,请参阅如何在 Linux 中终止进程的指南。

信号也不仅仅用于终止。例如,当 named 进程收到 SIGHUP 时,BIND 会重新加载其配置:

sudo killall -s HUP named

要列出 killall 支持的所有信号名,使用 -l

killall -l
HUP INT QUIT ILL TRAP ABRT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT
CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH POLL PWR SYS

忽略大小写匹配名称

默认情况下,进程名匹配是区分大小写的。如果你不确定大小写,可以加上 -I

killall -I "teamviewer"

这会匹配 TeamViewerteamviewer 以及该名称的任何其他大小写变体。

使用正则表达式匹配

-r 选项将名称解释为一个扩展正则表达式,因此你可以一次性给多个相关进程发送信号:

killall -r '^chrom.*'

^ 锚点将匹配限制在以 chrom 开头的名称上,例如 chromechromium。给模式加上引号,以免 shell 在 killall 看到之前就先解释了其中的特殊字符。

终止特定用户拥有的进程

-u 选项将匹配限制为某个特定用户拥有的进程:

killall -u sarah node

这只会终止运行在 sarah 账户下的 node 进程,而不影响其他用户的 node 进程。

如果你在 -u 后不跟进程名,killall 会信号该用户拥有的每一个进程:

sudo killall -u sarah

使用这种形式要小心。它会终止该用户的整个会话,包括其 shell 以及任何未保存工作的编辑器。当你想先逐个检查进程时,可将其与 -i 结合使用。

交互式确认每次终止

-i 选项会在信号每个匹配的进程之前要求确认:

killall -i node
Kill node(2211) ? (y/N)
Kill node(2384) ? (y/N)

回答 y 以信号该进程,或按回车跳过它。当一个名称足够常见、可能匹配到你没想到的进程时,交互模式是一个很好的安全网。

按进程年龄过滤

-o(older,较老)和 -y(younger,较新)选项按进程已运行的时长来过滤匹配。时间是一个后接单位的整数:s 表示秒,m 表示分钟,h 表示小时,d 表示天,w 表示周,M 表示月,y 表示年。

要终止已运行超过一小时的 myscript 进程:

killall -o 1h myscript

要只终止最近十分钟内启动的实例:

killall -y 10m myscript

年龄过滤器非常适合清理卡住的 worker 或失控的 cron 任务,同时让新鲜的、健康的实例继续运行。

等待进程结束

默认情况下,killall 发送信号后立即返回。-w 选项让它一直等待,直到所有被信号的进程真正终止:

killall -w myscript && echo "all stopped"

这在那些必须等服务完全停止后才能继续的脚本中很有用。如果信号被忽略、没有生效,或者让进程停留在僵尸状态,这个等待可能永远持续。

要给等待加上十秒上限,可以通过 timeout 命令来运行 killall

timeout 10s killall -w myscript

如果超过上限,timeout 会停止 killall 命令,但目标进程可能仍在运行。在决定是否发送 SIGKILL 之前,先用 pgrep 检查它。一个停留在僵尸状态的进程也会导致 killall -w 一直等待。

killall 与 kill、pkill 的区别

这三条命令都发送信号,区别在于你如何选择目标进程:

  • kill 针对特定的 PID,是最精确的选择,但你得先查出 PID。
  • killall 针对确切的进程名,并信号它的每一个实例。
  • pkill 针对名称模式,因此 pkill fire 会匹配 firefox。它也可以通过 -f 针对完整命令行进行匹配。

killall 的精确名称行为使得它在日常使用中比 pkill 更可预测:killall node 不会意外匹配到 node_exporter。Linux 将存储在 /proc/PID/stat 中的进程名限制为 15 个字符。对于更长的名称,当完整名称不可用时,killall 可能不得不回退到前 15 个字符。加上 -e 可以跳过那个无法精确验证的长名称匹配。

常用选项

  • -s SIGNAL - 发送指定信号,而不是 SIGTERM。也接受 -SIGNAL 和数字形式。
  • -l - 列出已知信号名。
  • -v - 报告每个成功发送的信号。
  • -q - 当没有进程匹配时不报错。
  • -I - 不区分大小写地匹配进程名。
  • -r - 将名称解释为一个扩展正则表达式。
  • -e - 对超过 15 字符的名称要求精确匹配。
  • -u USER - 只匹配指定用户拥有的进程。
  • -i - 在信号每个进程之前要求确认。
  • -o TIME - 只匹配比给定年龄更老的进程。
  • -y TIME - 只匹配比给定年龄更年轻的进程。
  • -w - 等待所有被信号的进程都已死亡。

快速参考

任务 命令
终止所有同名进程killall firefox
终止失败后的强制杀死killall -9 firefox
重新加载 BIND 配置sudo killall -s HUP named
忽略名称大小写killall -I teamviewer
按正则匹配名称killall -r '^chrom.*'
终止某用户的程序实例killall -u sarah node
终止某用户的所有进程sudo killall -u sarah
确认每次终止killall -i node
终止超过一小时的实例killall -o 1h myscript
等待进程退出killall -w myscript
列出信号名killall -l

故障排查

killall: no process found
killall 要求进程名精确匹配,除非你使用 -r-I。在重试之前,先运行 pgrep -a patternps -e -o pid,comm 来检查报告的名称、大小写和命令行。

Operation not permitted
你可以信号自己的进程,但要信号另一个用户的进程通常需要 root 权限。先确认确切目标,再仅在需要时加上 sudo 重新运行命令。

killall -w 不返回
进程可能忽略了信号、停留在僵尸状态,或者在 killall 检查期间被一个具有相同 PID 的新进程替换。用 Ctrl+C 停止等待,用 pgrep -a -x NAME 检查目标,只有当进程仍在运行且无法干净关闭时才使用 SIGKILL

结论

killall 用一条命令就能终止一个程序的每一个实例,并提供了按用户、年龄和大小写过滤的选项——当仅凭名称过于宽泛时,这些过滤器非常有用。当你需要模式匹配而非精确名称时,请改用 pkill;而当你需要在终止之前先检查进程时,可以从 pgrep 入手。