- 我的主机上运行着 3 个 java 进程 - 我通过 ssh 客户端访问主机。其中某个进程冻结了,我需要杀死该 pid 进程才能重新启动它
- 我知道文件名,但不知道文件号。
- 该进程正在屏幕内运行。如果我在屏幕上加入,则 java 进程已打开并正在运行,并且我无法通过命令停止它或
ctrl+c
导致其冻结。我看到的独特解决方案就是杀死它。
[root@vmi1478348 ~]# screen -ls
There are screens on:
18043.lob (Detached)
10196.fac (Detached)
10100.hu3 (Detached)
9868.bung (Detached)
该 pid 号与进程 pid 号不同,可能是屏幕 pid 号。所以如果你杀了它,你就不会杀掉你想杀的java进程,杀掉屏幕。
使用
ps aux
命令我可以检查pid,但是java文件的名称位于java进程行的末尾,并且它不会像图片一样显示在ssh客户端控制台屏幕上。我已经尝试减小字体大小,但问题仍然存在,它没有显示该行的其余部分,已经尝试用鼠标选择该行以在记事本上复制,但它仍然剪切它。有什么解决办法吗?
答案1
所有你需要的是pgrep
:
pgrep -fa 'file\.jar'
-f
:强制pgrep
将扩展正则表达式与包含文件名的完整调用命令行 进行匹配。-a
:强制pgrep
输出完整的调用命令行(其中将包括文件名),自动折叠行超出终端的宽度。
通过这样做,您将获得与表达式匹配的进程 ID 列表,以及它们的完整调用命令行,如果需要,每个条目可以很好地折叠到多行中。
此时,您可以选择kill
正确的pid
,或者传递相同的正则表达式pkill -f
来代替pgrep -fa
(如果使用第二种方法,请确保您的目标进程只出现在由 生成的列表中,pgrep -fa 'file\.jar'
因为这将向所有与正则表达式匹配的进程发出信号file\.jar
)。
另一种方式:如果可用,您可以使用htop
箭头键向右滚动。
另一种可能的方式:我非常确定screen
正确地向进程发出信号也将强制传播并最终终止子进程。我也许会弄清楚这一点并报告回来,我对这个话题有点生疏。
1 从技术上讲,至少在基于 Linux 的系统上当前版本的 procps 实现中,这是传递给进程(或其任何祖先)进行的pgrep
最后一个系统调用的参数空格的串联,其中有一些转义个字符,并截断为 128KiB,与 procps' 报告的 pidexecve()
相同。ps -wwo args=
答案2
如果您想了解更多命令行,有许多ps
实现,包括来自procps
¹ 在 Linux 上,您只需添加该-w
选项(或w
使用您正在使用的 BSD 风格的 API)两次即可获得完整的命令行²:
ps auxww # BSD-style
ps -Afww # standard style
procps
'ps
还有一个-C
选项来报告运行给定命令的进程(使用启发式),因此您可以执行以下操作:
ps -fwwC java
列出java
进程的完整命令行。
在 GNU/Linux 上,要可靠地查找将file.jar
参数之一传递给它(或其祖先)执行的命令的进程,您可以执行以下操作:
grep -lFzx file.jar /proc/*/cmdline
(l
列出了至少有一个z
以 ero 分隔的记录file.jar
作为F
固定字符串和 e x
actly(不是作为子字符串)进行匹配的文件)。
或者将其限制为正在运行的进程/usr/bin/java
:
find /proc -maxdepth 2 \
-name cmdline \
-execdir test exe -ef /usr/bin/java ';' \
-exec grep -lFzx file.jar {} +
或者使用 shell 更短、更高效zsh
:
print -rC1 /proc/<2->(e[$'
[[ $REPLY/exe -ef /usr/bin/java && \0$(<$REPLY/cmdline) = *\0file.jar\0* ]]
']:t)
(替换print -rC1
为kill
以终止这些进程)。
使用这种方法,您可以通过将模式更改为 来仅选择那些file.jar
在 1 之后作为下一个参数的进程,从而使选择更加严格。-jar
*\0-jar\0file.jar\0*
不过,按照@kos的建议使用pkill
可能已经足够好了,并且可以通过以下方式变得更严格:
pkill -f '^java (.* )?-jar file\.jar( |$)'
它不如以下可靠:
- 它不检查正在运行的可执行文件,只检查传递给它的参数。
- 它可能会遇到 128KiB 限制(例如,在
-jar file.jarringly.unlikely.jar
一个非常长的 java 命令行末尾的命令行上进行匹配) 'java and lambada' -f 'jam -jar file.jar'
当参数与空格连接时,我们会丢失每个参数开始和结束位置的信息,因此它可以匹配例如启动的进程。- 如果命令行中存在无法解码为区域设置编码中的字符的字节序列,它将失败。
所有这些都是极不可能的。
1 在使用 Linux 作为内核的非嵌入式操作系统上最常用的一种。
² from procps 仍然限制为 128KiB ,并且要注意旧版本的 Linux 仅公开了从中获取信息的ps
命令行(参数列表)的前 4KiB 。/proc/<pid>/cmdline
ps
答案3
虽然不是一个好的解决方案,但解决了部分问题,编辑 ssh 客户端的配置并将字体大小更改为1
除了选择最长的行并在记事本上复制之外,您无法阅读任何内容,我发现了该行:
root 12868 19.2 8.4 5963840 1381788 pts/1 Sl+ 15:45 3:39 java --illegal-access=permit -Duser.timezone=America/Sao_Paulo -Dlog4j2.formatMsgNoLookups=true -Xms1G -Xmx1G -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:+AlwaysPreTouch -XX:G1NewSizePercent=30 -XX:G1MaxNewSizePercent=40 -XX:G1HeapRegionSize=8M -XX:G1ReservePercent=20 -XX:G1HeapWastePercent=5 -XX:G1MixedGCCountTarget=4 -XX:InitiatingHeapOccupancyPercent=15 -XX:G1MixedGCLiveThresholdPercent=90 -XX:G1RSetUpdatingPauseTimePercent=5 -XX:SurvivorRatio=32 -XX:+PerfDisableSharedMem -XX:MaxTenuringThreshold=1 -Dusing.aikars.flags=https://mcflags.emc.gs/ -Daikars.new.flags=true -jar bung.jar nogui
- 我想要的进程的名称是
bung.jar
现在我知道 pid12868