尽管 Linux 被认为是一个健壮的操作系统,应用程序的问题很少,但程序有时会变得无响应。 发生这种情况时,它们可能会消耗大量系统资源或关闭整个系统。 通常,这些应用程序无法自动重新启动。
如果进程或应用程序仍在运行并且不会完全关闭,则需要使用命令终止 Linux 中的进程。 发生这种情况时,需要重新启动整个系统或结束特定的应用程序进程。 由于重新启动整个系统需要时间并且会给客户端带来很大的不便,因此在 Linux 中杀死进程要容易得多。
什么是过程?
进程是当前正在执行的程序的工作机制。 在创建后,每个进程都会自动分配一个唯一的进程标识号 (PID)。 当一个进程死亡时,它的 PID 被返回到一个可用的池中,然后另一个进程可以重用它。
我们可以在服务器上使用多个命令来查找特定的 PID。 为了 example,我们可以使用 top 命令,它会给我们一个所有正在运行的进程的表。 有了这个,我们可以找到进程的 PID 以及其他有用的系统信息。
另一种查找 PID 的方法是使用 ps 命令。 下面,我们看到了使用 ps 命令查找 PID 的几种不同方法。
[root@host ~]# ps faux | grep systemd
Root 1 0.0 0.6 96656 11260 ? Ss Jan24 0:08 /usr/lib/systemd/systemd --switched-root --system --deserialize 18
Root 533 0.0 1.3 125588 22832 ? Ss Jan24 0:25 /usr/lib/systemd/systemd-journald
Root 564 0.0 0.5 107440 9248 ? Ss Jan24 0:00 /usr/lib/systemd/systemd-udevd
Dbus 684 0.0 0.3 73540 5524 ? Ss Jan24 0:06 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
Root 743 0.0 0.4 95736 7760 ? Ss Jan24 0:01 /usr/lib/systemd/systemd-logind
Root 66199 0.0 0.0 12108 1060 pts/0 S+ 08:28 0:00 _ grep --color=auto systemd
Root 66153 0.0 0.5 93212 9472 ? Ss 08:27 0:00 /usr/lib/systemd/systemd --user
[root@host ~]#
[root@host ~]# ps -eo user,pid,command | grep systemd
[root@host ~]# ps -eo user,pid,command | grep systemd
root 1 /usr/lib/systemd/systemd --switched-root --system --deserialize 18
root 533 /usr/lib/systemd/systemd-journald
root 564 /usr/lib/systemd/systemd-udevd
dbus 684 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
root 743 /usr/lib/systemd/systemd-logind
root 66153 /usr/lib/systemd/systemd --user
root 66213 grep --color=auto systemd
[root@host ~]#
我们还可以使用 pidof process_name 和 pgrep process_name 命令来找出该进程的相应 PID。
[root@host ~]# pidof systemd
66156 66153 1
[root@host ~]#
[root@host ~]# pgrep systemd
1
533
564
743
66153
[root@host ~]#
要终止 Linux 中的进程,我们可以使用 kill 命令。 它是向指定进程发送信号的内置命令。 Linux 操作系统将停止有问题的进程。
什么是信号?
信号是来自其他进程、内核或特定进程本身的进程之间对话的一种形式。 每个进程都有一个当前行为或处置,其中有五种类型:
- 学期
- 点火
- 核
- 停止
- 续
这些属性决定了当信号被传递给它时进程的行为方式。 Term 的默认操作是终止进程,这主要由 kill 命令使用。
kill 命令总共使用了 64 个信号。 我们发送的信号将取决于期望的结果,因为不同的信号具有不同的效果和结果。 在这 64 个信号中,前 31 个是标准信号。 其余的是实时信号。
这两种信号的主要区别在于标准信号不能排队,而实时信号可以。 这意味着与标准信号的第一个实例相关的信息由进程接收。 实时信号将与其相关的信息排队,允许接收多个信号。
我们可以使用命令 kill -l 或在信号手册页中输入 man 7 signal 来查看可用信号的完整列表。
[root@host ~]# kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT
7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2
13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD
18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH
29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1
36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5
40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9
44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13
52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9
56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5
60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1
64) SIGRTMAX
[root@host ~]#
对于这些信号中的大多数,程序可能会或可能不会指定不同的操作。 如果程序定义了动作,则称为捕获或处理信号。 如果没有动作发生,信号将被忽略。
最常用的信号如下。
Signal 姓名 | 单值 | 影响 |
---|---|---|
SIGHUP | 1 | 挂断,重新加载进程 |
信号情报 | 2 | 从键盘中断 |
杀戮 | 9 | 杀死一个进程 |
SIGTERM | 15 | 优雅地终止进程 |
信号停止 | 17、19、23 | 停止一个进程 |
SIGKILL 和 SIGSTOP 信号不能被捕获、阻塞或忽略,而 SIGTERM 信号可以被捕获或忽略。 这就是为什么当 SIGTERM 无法停止或结束进程时,我们可以在 Linux 中使用 SIGKILL。
在下面 example, kill -15 (SIGTERM) 不会停止 Java 进程。 因此,在这种情况下,Linux 必须强制终止进程。
[root@host ~]# ps -eo user,pid,command | grep java
tomcat 59815 /usr/bin/java -Djava.util.logging.config.file=/usr/local/tomcat9/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -classpath /usr/local/tomcat9/bin/bootstrap.jar:/usr/local/tomcat9/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat9 -Dcatalina.home=/usr/local/tomcat9 -Djava.io.tmpdir=/usr/local/tomcat9/temp org.apache.catalina.startup.Bootstrap start
root 66401 grep --color=auto java
[root@host ~]# kill -15 59815
[root@host ~]#
一般规则
关于如何在 Linux 中停止进程,还有其他一般规则。 需要注意的是,普通用户可以向自己的进程发送信号,但不能向其他用户的进程发送信号。 另一方面,root 用户可以向所有其他用户的进程发送信号。 以下是一些额外的一般规则:
- 发送的信号取决于我们传递给命令的 PID。
- 如果 PID 大于零,则将信号发送到具有该 PID 的进程。
- 如果 PID 等于 0,则信号被发送到 kill 命令所涉及的 shell 的进程组 (PGID) 中的所有进程。
- 如果 PID 等于 -1,则将信号发送到与调用 kill 命令的用户具有相同用户 ID 的所有进程。
- 如果 PID 小于 -1,则将信号发送给进程组中进程组 ID 等于 PID 绝对值的所有进程。
使用 Kill 命令
如上所述,kill 命令发送一个信号以终止 Linux 中的进程。 默认情况下,如果没有定义其他信号,它将发送一个 TERM 信号。 该信号将尝试在 Linux 操作系统中优雅地停止该进程。
如果失败,请尝试使用另一个信号终止进程,因为该信号可能已被捕获或忽略。 在 Linux 中,您可以通过使用数字 (kill -9)、SIG 前缀 (kill -SIGkill) 或不使用 SIG 前缀 (kill -kill) 来定义具有不同信号的进程来终止进程。
如您所见,kill -9 (SIGKILL) 命令终止了 Java 进程。
[root@host ~]# ps -eo user,pid,command | grep java
tomcat 66469 /usr/bin/java -Djava.util.logging.config.file=/usr/local/tomcat9/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -classpath /usr/local/tomcat9/bin/bootstrap.jar:/usr/local/tomcat9/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat9 -Dcatalina.home=/usr/local/tomcat9 -Djava.io.tmpdir=/usr/local/tomcat9/temp org.apache.catalina.startup.Bootstrap start
root 66516 grep --color=auto java
[root@host ~]# kill -9 66469
[root@host ~]#
[root@host ~]# ps -eo user,pid,command | grep java
root 66530 grep --color=auto java
[root@host ~]#
使用以下语法调用 kill 命令。
kill [OPTIONS] [PID]
为了 example,如果我们发现一个 httpd 进程的进程 ID 是 21567,我们可以尝试通过调用以下命令来优雅地杀死它。 它将发送 TERM 信号。
[root@host ~]# kill 21567
如果这没有停止进程,我们可以尝试使用信号 SIGKILL 终止它,这将在不先等待进程正确关闭的情况下终止它。 为此,您可以使用以下命令之一。
[root@host ~]# kill -9 21567
[root@host ~]# kill -SIGKILL 21567
[root@host ~]# kill -kill 21567
杀死所有
此外,我们可以通过使用唯一的 PID、kill 命令或进程名称和 killall 命令来杀死 Linux 中的进程。 使用 killall 命令应用相同的语法,调用 killall [signal] [process_name]就像在这个 example.
killall -9 httpd
此命令将终止 Linux 中的 httpd 进程,而无需等待它正常停止。
在确定信号发送到哪个进程时,它将与参数名称完全匹配,如下所示 example.
killall httpd
该命令将向所有名为 httpd 的进程发送终止信号。
如果您对不存在的服务运行相同的命令,它将显示一个错误,即没有具有该名称的进程。 自从 Apache 使用 httpd 作为进程名而不是 http,下面的命令会产生这样的错误。
killall http
杀戮
类似于 killall 的命令是 pkill,它也可以通过名称杀死 Linux 中的进程。 它将模式作为参数并将其与正在运行的进程的名称进行匹配,因此它不需要确切的名称。 为了 example,我们可以用这样的方式终止 httpd。
pkill http
虽然这不是确切的进程名称,但它会找到包含此模式的进程并将终止信号发送到 httpd。
技能
Skill 命令使用与 kill 命令相同的语法来发送终止信号。 此处主要使用默认的 TERM 信号。
skill [signal] [options]
[root@host ~]# ps -eo user,pid,command | grep tomcat
tomcat 66546 /usr/bin/java -Djava.util.logging.config.file=/usr/local/tomcat9/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -classpath /usr/local/tomcat9/bin/bootstrap.jar:/usr/local/tomcat9/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat9 -Dcatalina.home=/usr/local/tomcat9 -Djava.io.tmpdir=/usr/local/tomcat9/temp org.apache.catalina.startup.Bootstrap start
root 66846 grep --color=auto tomcat
[root@host ~]# skill -9 66546
建议使用 kill、pkill 或 killall 命令代替技能。
mysql_zap
另一个将在 Linux 中停止与特定模式匹配的进程的命令是 mysql_zap。 如果 ps 命令的输出行包含该模式,则已识别的进程将匹配该模式。 与其他命令一样,mysql_zap 将默认发送一个 TERM 信号,除非指定了另一个信号。 该命令使用的语法如下。
[root@host ~]# mysql_zap [signal] [pattern].
从版本 10.2 开始,mysql_zap 命令在 MariaDB 中已被弃用。 替代方法是 pkill 命令。
杀戮
使用 mk-kill 命令终止与指定条件匹配的 MySQL 查询。 如果将文件传递给 mk-kill,它将从该文件中读取查询,其中包含 SHOW PROCESSLIST 的输出。 如果没有给出文件作为参数,mk-kill 将在 MySQL 中执行 SHOW PROCESSLIST 以获取查询。 以下是该命令的两个示例。
[root@host ~]# mk-kill --busy-time 60 --print
[root@host ~]# mk-kill --match-command Sleep --kill --no-only-oldest --interval 10
第一个命令将终止所有发现运行时间超过 60 秒的 MySQL 查询。 第二个命令每十秒检查一次任何休眠进程(需要当前不可用的资源的进程)并结束找到的任何进程。
麦基尔
另一个与 mk-kill 相关的命令是 mkill 命令。 此命令将终止发现的慢查询。
它将根据以下因素终止这些查询:
- 查询时间
- 主持人
- 用户
- 数据库
- 状态
- 查询内容
mkill 命令仍处于 alpha 版本状态。
Tkill 和 Tgkill
如果我们想杀死一个特定线程而不是整个进程中的任意线程,我们可以使用 tkill 和 tgkill 命令来实现。 tkill 命令是 tgkill 的前身。
tkill 命令只允许指定目标线程 ID,如果该线程 ID 被回收(用于另一个线程)导致不正确的线程终止。另一方面,tgkill 将向具有线程 ID 的线程发出信号线程组 ID (tgid)。
杀戮
另一个用于向进程组发送信号的命令是 killpg。 killpg 命令将向进程组 (pgrp) 发送信号。 如果 pgrp 为 0,则向调用进程组发送信号。 否则,killpgrp 命令不接受任何其他参数并杀死同一进程组中的所有进程。
tcpkill
我们还可以使用 tcpkill 命令终止正在进行的特定传输控制协议 (TCP) 连接。 使用此命令,我们可以指定要侦听的网络接口(作为选项)或确定用于终止连接的强制程度(使用 1-9 的数字)。 默认的力度为 3。
以下命令是 tcpkill 的语法。
[root@host ~]# tcpkill [-i interface] [-1...9] expression
[root@host ~]# tcpkill -i eth0 port 21
LXC杀
如果我们需要停止在 Ubuntu 上的虚拟化容器内运行的 Linux 进程(例如,如果使用 Kubernetes 或 Docker),我们可以使用 lxc-kill 命令。 该命令将向容器的第一个进程发送一个数字信号以结束一个进程。
lxc-kill 命令的语法如下。
lxc-kill --name=NAME SIGNUM
阿尔基尔
arckill 命令用于终止启用 ARC 的资源上正在运行的作业。 高级资源连接器 (ARC) 是一种网格计算中间件,它为向分布式系统提交计算任务提供了一个通用接口。
如果属性已提交,您可以使用 jobid 或 jobname 来引用作业。
arckill -j filename.xml (<jobid#>)
pvm_kill
要终止指定的 PVM 进程(消息传递系统),我们可以使用 pvm_kill 命令。 它将向由任务标识符 (tid) 标识的 PVM 进程发送终止信号。 此命令主要用于较大的程序,如下所示:
- 在 C 中: info = pvm_kill( tid );
- 在 Fortran 中:调用 PVMFKILL(TID, INFO)
杀戮
xkill 命令是一种终止应用程序的图形方式。 当您在具有图形用户界面 (GUI) 的系统上的终端中输入命令 xkill 时,鼠标光标将变为加号(取决于您的图标集)。 然后左键单击一个无响应的窗口以 close 它。
xkill 命令指示 xserver 终止所选窗口中的程序。 它的语法如下。
xkill [-display displayname] [-id resource] [-button number] [-frame] [-all]
结论
正如我们所见,在 Linux 中有几种方法可以终止进程。 但是,在使用这些命令时应谨慎行事,以防止错误地终止可能杀死不应被杀死的应用程序的所需进程。 它还可能导致基本服务中断,从而导致许多问题。
考虑到这一点,请始终查阅 Linux 终端中每个命令的相应手册页。 如果您不确定,请与您的网络托管支持团队或系统管理员联系以寻求帮助。
随着我们继续向未来迈进,您的知识应该增长以跟上您的竞争对手。 阅读以下内容,了解我们的一位客户如何利用这一想法 快速粉碎案例研究,其中详细介绍了他们的旅程!