由于 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.sh
vi 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 comm
pgrep
还有就是参数列表传递给它最后执行的命令的进程(/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
如果您想终止相应的进程,请通过管道连接到。