用于杀死上一个命令提供的特定 PID 的命令

用于杀死上一个命令提供的特定 PID 的命令

有时我需要终止一个进程(原因并不重要)。我知道我可以使用以下命令找到该过程:lsof -i :8080,成为我的候选人最后一道工序在输出表中。

例如,如果我运行该命令,将出现如下输出:

COMMAND   PID USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
java    15112 dani   70u  IPv4 3178183      0t0  TCP localhost:39998->localhost:http-alt (CLOSE_WAIT)
java    15112 dani  137u  IPv4 3181607      0t0  TCP localhost:39999->localhost:http-alt (CLOSE_WAIT)
java    15112 dani  138u  IPv4 3181608      0t0  TCP localhost:40000->localhost:http-alt (CLOSE_WAIT)
java    15112 dani  139u  IPv4 3181609      0t0  TCP localhost:40001->localhost:http-alt (CLOSE_WAIT)
java    15112 dani  140u  IPv4 3181610      0t0  TCP localhost:40002->localhost:http-alt (CLOSE_WAIT)
java    19509 dani   50u  IPv6 4617361      0t0  TCP *:http-alt (LISTEN)
java    19509 dani   52u  IPv6 6642445      0t0  TCP localhost:http-alt->localhost:42996 (CLOSE_WAIT)

所以,我的目标是PID 19509。使用管道,我如何挑选最后一行的 PID?

我想达到这样的命令lsof -i :8080 | something here to get the PID | kill -9

我正在运行 Linux Mint KDE x64

答案1

从字面上回答你的问题,这是列出最后显示的 PID 的一种方法lsof

lsof … | awk 'END {print $2}'

awk是一种文本处理语言,它读取输入并逐行处理它。代码中,END {…}处理完整个输入后执行大括号内的代码,并对最后一行进行有效操作。$2是该行中第二个空格分隔的字段。

这里有一些杀死它的方法(每行都独立工作):

kill $(lsof … | awk 'END {print $2}')
lsof … | awk 'END {print $2}' | xargs kill
lsof … | awk 'END {system("kill " $2)}'

然而,我对你的说法提出异议,即杀死正确的进程总是最后一个进程。lsof通过增加PID来显示进程,这是没有意义的。即使在进程 ID 按顺序分配的系统上(并非所有 Unix 变体,甚至并非所有 Linux 安装),一旦达到最大值(通常为 32767),它们就会换行。因此通过比较 PID 来决定进程是没有意义的。

您需要一些其他信息来决定要终止哪个进程。根据您想要的信息类型以及您的输出是否可能包含“奇怪”字符(例如文件名或程序名中的空格),您可以使用 awk 等工具来处理 的输出lsof,或者您可以使用该-F选项lsof产生的输出在简单情况下解析起来有点困难,但(几乎)不容易产生歧义并且更容易稳健地解析。例如,如果您想终止正在侦听端口 8080 的任何进程,可以按以下方法操作:

lsof -n -i :8080 -F | awk '
    sub(/^p/,"") {pid = $0}
    $0 == "n*:http-alt" {print pid}
' | xargs kill

对该函数的调用将行的开头sub替换为空字符串。p如果执行此替换,则{pid = $0}执行该代码块;这样pid变量就包含了显示的最后一个 PID 值lsofpid如果该行恰好是,则第二个 awk 行将打印变量的值"n*:http-alt",这是 lsof 报告在所有接口上侦听端口 8080 的套接字的方法。

这个特定的标准实际上不需要任何解析(我只在上面作为示例展示)。您可以使lsof显示仅在指定端口上侦听的进程:

lsof -n -a -iTCP:8080 -sTCP:LISTEN -Fp | sed 's/^p//' | xargs kill

或者,为此,您可以使用netstat反而。

netstat -lnpt | awk '$4 ~ /:8080$/ {sub(/\/.*/, "", $7); print $7}'

awk 代码说明:如果第 4 列以 结尾:8080,则替换第 7 列中第一列之后的所有内容/(删除进程名称部分并仅保留 PID 部分),然后打印它。

相关内容