如何获取长命令名称的进程 ID 列表,而不是命令行参数?

如何获取长命令名称的进程 ID 列表,而不是命令行参数?

由于 pgrep 中进程名称的长度有 15 个字符的限制,因此我一直使用pgrep -f较长名称的运行命令的进程 ID 列表。但是,它包含完整的命令行参数,这会给出错误的结果。

例如:假设my_long_script_name.sh正在运行,而我vi my_long_script_name.sh(暂时忽略编辑正在运行的程序)。

如果我运行,它会返回和pgrep -f my_long_script_name.sh的进程 ID 。my_long_script_name.shvi my_long_script_name.sh

pgrep -d ' '如何获取仅基于进程名称而不是参数列表的进程 ID 列表(我可以在列表中将其杀死,以相同的方式创建它们)?

我正在运行 Buster,但在早期操作系统(例如 Wheezy)中看到同样的问题。根据要求,如果我运行sed -n l "/proc/$pid/comm",我的终端会话$pid在哪里$BASHPID,我会得到bash$。如果我跑步sed -n l "/proc/$pid/cmdline",我就会得到-bash\000$。后面是小写的 L,而不是 1 -n。如果我运行cat -vte,它就会挂起。

答案1

问题是没有这样的事情长进程名称

有的是进程名称/proc/pid/comm在 Linux 上)在 Linux 上最多 15 个字节长,从父进程继承,并且每次进程execve()对正在执行的文件的基本名称的前 15 个字节进行系统调用时都会更改(但也可以更改为任意值prctl()或通过写入该comm文件)。

这就是不带或带 的ps报告内容。以及默认情况下匹配的内容。-f-o commpgrep

还有就是参数列表传递给它最后执行的命令的进程(/proc/pid/cmdline在 Linux 上)。按照约定,第一个参数是正在执行的文件的基本名称或路径。

ps -f或者ps -o args打印这些参数与空格字符的串联,并pgrep -f匹配结果字符串。由于这种串联,您会丢失每个参数开始和结束位置的信息。

但是,如果您可以假设第一个参数不包含空格字符,那么您仍然可以匹配第一个参数包含my_long_script_name.sh以下内容的进程:

pgrep -f '^[^ ]*my_long_script_name\.sh'

(如果要杀死相应的进程,请替换pgrep为)。pkill

为了更可靠,如果在 Linux 上,使用zsh,您可以这样做:

print -C1 /proc/<->(Ne[$'[[ ${"$(<$REPLY/cmdline)"%%\0*} = (*/|)my_long_script_name.sh ]]']:t)

也就是说,直接从 获取信息/proc/pid/cmdline,其中参数由 分隔$'\0',并检查导致第一个参数的部分$'\0'是否以my_long_script_name.sh或 结尾/my_long_script_name.sh

xargs kill如果您想终止相应的进程,请通过管道连接到。

相关内容