尽管 Linux 被认为是一个健壮的操作系统,应用程序几乎没有问题,但程序有时会变得无响应。 发生这种情况时,它们可能会消耗大量系统资源或关闭整个系统。 通常,这些应用程序无法自动重启。
如果进程或应用程序仍在运行并且不会完全关闭,则需要在 Linux 中使用命令终止该进程。 发生这种情况时,需要重新启动整个系统或结束特定的应用程序进程。 由于重新启动整个系统需要时间,并且会给客户端带来很大的不便,因此在 Linux 中杀死进程要容易得多。
什么是进程?
进程是当前正在执行的程序的工作机制。 创建后,每个进程都会自动分配一个唯一的进程标识号 (PID)。 当一个进程死亡时,它的 PID 被返回到一个可用的池中,然后另一个进程可以重用它。
我们可以在服务器上使用多个命令来查找特定的 PID。 例如,我们可以使用 top 命令,它将为我们提供所有正在运行的进程的表。 有了这个,我们可以找到进程的 PID 以及其他有用的系统信息。
另一种查找 PID 的方法是使用 ps 命令。 下面,我们将看到使用 ps 命令查找 PID 的几种不同方法。
[[email protected] ~]# 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 [[email protected] ~]#
[[email protected] ~]# ps -eo user,pid,command | grep systemd [[email protected] ~]# 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 [[email protected] ~]#
我们还可以使用 pidof process_name 和 pgrep process_name 命令来找出该进程的相应 PID。
[[email protected] ~]# pidof systemd 66156 66153 1 [[email protected] ~]#
[[email protected] ~]# pgrep systemd 1 533 564 743 66153 [[email protected] ~]#
要终止 Linux 中的进程,我们可以使用 kill 命令。 它是一个向指定进程发送信号的内置命令。 Linux 操作系统将停止相关进程。
什么是信号?
信号是来自其他进程、内核或特定进程本身的进程之间对话的一种形式。 每个进程都有一个当前的行为或倾向,其中有五种类型:
- 学期
- 伊恩
- 核
- 停止
- 帐户
这些属性决定了当信号传递给进程时进程的行为方式。 Term 的默认动作是终止进程,主要由kill 命令使用。
kill 命令总共使用了 64 个信号。 我们发送的信号将取决于所需的结果,因为不同的信号具有不同的效果和结果。 在这 64 个信号中,前 31 个是标准信号。 其余的是实时信号。
这两种信号的主要区别在于标准信号不能排队,而实时信号可以。 这意味着与标准信号的第一个实例相关联的信息由进程接收。 实时信号会将与之相关的信息排队,从而允许接收多个信号。
我们可以使用命令 kill -l 或在信号手册页中输入 man 7 signal 来查看可用信号的完整列表。
[[email protected] ~]# 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 [[email protected] ~]#
对于这些信号中的大多数,程序可能会或可能不会指定不同的操作。 如果程序定义了动作,则称为捕获或处理信号。 如果没有动作发生,信号将被忽略。
最常用的信号如下。
信号名称 | 单值 | 影响 |
---|---|---|
签到 | 1 | 挂断,重载进程 |
信号情报 | 2 | 键盘中断 |
SIGKILL | 9 | 杀死一个进程 |
SIGTERM | 15 | 优雅地终止进程 |
停止信号 | 17、19、23 | 停止进程 |
SIGKILL 和 SIGSTOP 信号不能被捕获、阻塞或忽略,而 SIGTERM 信号可以被捕获或忽略。 这就是为什么当 SIGTERM 无法停止或结束进程时,我们可以在 Linux 中使用 SIGKILL。
在下面的示例中,kill -15 (SIGTERM) 不会停止 Java 进程。 因此,在这种情况下,Linux 必须强制终止进程。
[[email protected] ~]# 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 [[email protected] ~]# kill -15 59815 [[email protected] ~]#
通用规则
关于如何在 Linux 中停止进程,还有其他一般规则。 必须注意的是,普通用户可以向自己的进程发送信号,但不能向属于其他用户的进程发送信号。 另一方面,root 用户可以向所有其他用户的进程发送信号。 以下是一些额外的一般规则:
- 发送的信号取决于我们传递给命令的 PID。
- 如果 PID 大于零,则将信号发送到具有该 PID 的进程。
- 如果 PID 为零,则将信号发送到 kill 命令中涉及的 shell 的进程组 (PGID) 中的所有进程。
- 如果 PID 等于 -1,则将信号发送到与调用 kill 命令的用户具有相同用户 ID 的所有进程。
- 如果PID小于-1,则将信号发送给进程组ID等于PID绝对值的进程组中的所有进程。
使用 Kill 命令
如上所述,kill 命令发送信号以终止 Linux 中的进程。 默认情况下,如果没有定义其他信号,它将发送一个 TERM 信号。 该信号将尝试在 Linux 操作系统中优雅地停止进程。
如果失败,请尝试使用另一个信号终止进程,因为该信号可能已被捕获或忽略。 您可以通过使用数字 (kill -9)、带 SIG 前缀 (kill -SIGkill) 或不带 SIG 前缀 (kill -kill) 来定义 Linux 中使用不同信号的进程。
如您所见,kill -9 (SIGKILL) 命令终止了 Java 进程。
[[email protected] ~]# 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 [[email protected] ~]# kill -9 66469 [[email protected] ~]# [[email protected] ~]# ps -eo user,pid,command | grep java root 66530 grep --color=auto java [[email protected] ~]#
使用以下语法调用 kill 命令。
kill [OPTIONS] [PID]
例如,如果我们发现一个 httpd 进程的进程 ID 是 21567,我们可以尝试通过调用以下命令优雅地杀死它。 它将发送 TERM 信号。
[[email protected] ~]# kill 21567
如果这没有停止进程,我们可以尝试使用信号 SIGKILL 杀死它,这将杀死它而无需先等待进程正确关闭。 为此,请使用以下命令之一。
[[email protected] ~]# kill -9 21567 [[email protected] ~]# kill -SIGKILL 21567 [[email protected] ~]# kill -kill 21567
杀死所有
此外,我们可以使用唯一的 PID、kill 命令或使用进程名称和 killall 命令来终止 Linux 中的进程。 应用与 killall 命令相同的语法,调用 killall [signal] [process_name],如本例所示。
killall -9 httpd
此命令将终止 Linux 中的 httpd 进程,而无需等待它正常停止。
在确定信号发送到哪个进程时,它将与参数名称完全匹配,如本例所示。
killall httpd
该命令将向所有名为 httpd 的进程发送终止信号。
如果您对不存在的服务运行相同的命令,则会显示错误,指出没有具有该名称的进程。 自从 Apache 使用 httpd 作为进程名称而不是 http,以下命令会产生这样的错误。
killall http
杀戮
一个类似于killall的命令是pkill,它也可以按名称杀死Linux中的进程。 它将模式作为参数并将其与正在运行的进程的名称进行匹配,因此它不需要确切的名称。 例如,我们可以用这样的方式终止 httpd。
pkill http
尽管这不是确切的进程名称,但它会找到包含此模式的进程并将终止信号发送到 httpd。
技能
Skill 命令使用与 kill 命令相同的语法来发送终止信号。 这里主要使用默认的 TERM 信号。
skill [signal] [options] [[email protected] ~]# 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 [[email protected] ~]# skill -9 66546
建议使用kill、pkill 或killall 命令而不是skill。
mysql_zap
另一个将在 Linux 中停止匹配特定模式的进程的命令是 mysql_zap。 如果 ps 命令的输出行包含该模式,则识别的进程将匹配该模式。 与其他命令一样,除非指定了另一个信号,否则默认情况下 mysql_zap 将发送 TERM 信号。 此命令使用的语法如下。
[[email protected] ~]# mysql_zap [signal] [pattern].
从版本 10.2 开始,MariaDB 中的 mysql_zap 命令已弃用。 替代方法是 pkill 命令。
杀戮
使用 mk-kill 命令终止匹配指定条件的 MySQL 查询。 如果将文件传递给 mk-kill,它将从该文件读取查询,其中包含 SHOW PROCESSLIST 的输出。 如果没有给出文件作为参数,mk-kill 将在 MySQL 中执行一个 SHOW PROCESSLIST 来获取查询。 这是该命令的两个示例。
[[email protected] ~]# mk-kill --busy-time 60 --print [[email protected] ~]# 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的语法。
[[email protected] ~]# tcpkill [-i interface] [-1...9] expression [[email protected] ~]# tcpkill -i eth0 port 21
杀戮
如果我们需要停止在 Ubuntu 虚拟化容器中运行的 Linux 进程(例如,如果使用 Kubernetes 或 Docker),我们可以使用 lxc-kill 命令。 该命令将向容器的第一个进程发送一个数字信号以结束一个进程。
lxc-kill 命令的语法如下。
lxc-kill --name=NAME SIGNUM
Arckill
arckill 命令用于终止在启用 ARC 的资源上运行的作业。 高级资源连接器 (ARC) 是一种网格计算中间件,它为向分布式系统提交计算任务提供了一个通用接口。
如果提交了属性,您可以使用 jobid 或 jobname 来引用作业。
arckill -j filename.xml (<jobid#>)
pvm_kill
要终止指定的 PVM 进程(消息传递系统),我们可以使用 pvm_kill 命令。 它将向由任务标识符 (tid) 标识的 PVM 进程发送终止信号。 此命令主要用于较大的程序,如下所示:
- 在 C: info = pvm_kill( tid );
- 在 Fortran 中: CALL PVMFKILL( TID, INFO )
杀戮
xkill 命令是一种终止应用程序的图形方式。 当您在具有图形用户界面 (GUI) 的系统上的终端中输入命令 xkill 时,鼠标光标将变为加号(取决于您的图标集)。 然后左键单击一个没有响应的窗口 close 它。
xkill 命令指示 xserver 终止所选窗口中的程序。 其语法如下。
xkill [-display displayname] [-id resource] [-button number] [-frame] [-all]
结论
正如我们所见,在 Linux 中有多种方法可以终止进程。 但是,在使用这些命令时应谨慎行事,以防止错误地终止所需的进程,该进程可能会终止不应终止的应用程序。 它还可能导致基本服务中断,从而导致许多问题。
考虑到这一点,请始终在 Linux 终端中为每个命令查阅相应的手册页。 如果您不确定,请与您的网络托管支持团队或系统管理员联系以获得帮助。
随着我们继续迈向未来,您的知识应该增长以跟上您的竞争对手。 阅读以下内容,了解我们的一位客户如何利用这一想法 快速粉碎案例研究,详细介绍了他们的旅程!