我正在尝试创建一个脚本来查找仅包含进程名称和好编号的 PID 编号,但我无法做到。
答案1
用于pgrep
首先获取与第一个参数给出的表达式匹配的所有进程的 PID,然后循环遍历这些进程以提取具有与第二个参数相对应的良好值的进程。
find_pid_by_name_and_nice () {
pgrep -- "${1:?missing process name}" |
xargs -I {} ps -o pid= -o nice= -p {} |
awk -v nice="${2?missing nice value}" '$NF == nice { print $1 }'
}
测试:
$ find_pid_by_name_and_nice
find_pid_by_name_and_nice:1: 1: missing process name
find_pid_by_name_and_nice:3: 2: missing nice value
$ find_pid_by_name_and_nice netdata
find_pid_by_name_and_nice:3: 2: missing nice value
$ find_pid_by_name_and_nice netdata 19
258881
258937
$ find_pid_by_name_and_nice netdata 15
(无输出)
答案2
by_name_and_nice(){ grep -hoPs "^[^ ]+(?= \($1\)( [^ )]+){16} $2 )" /proc/*/stat; }
by_name_and_nice bash 0
将找到所有bash
进程的niceness = 0(默认值),
by_name_and_nice 'b.*' '.*'
将找到名称以 a 开头的所有进程b
,无论它们的好坏,依此类推。
如果您还想在名称中获取带有换行符和二进制垃圾的进程,您可能需要一些更复杂的东西:
by_name_and_nice(){
local -; set -o pipefail
LC_ALL=C grep -zhoPs "^[^ ]+(?= \($1\)( [^ )]+){16} $2 )" /proc/*/stat | xargs -0rn1
}
要匹配进程名称中的换行符,您应该使用by_name_and_nice '(?s:foo.*)' 0
(请阅读有关PCRE 正则表达式语法由 GNU grep-P
选项使用)。
这仅用于演示目的;在没有大于或小于运算符的情况下尝试按良好值进行选择是毫无意义的。另外,通过进程名称进行选择也不是很可靠,因为进程名称处于进程的完全控制之下,任何两位恶意软件和垃圾软件都会无情地滥用进程名称来称呼自己ps
或bash
.更好的想法是通过二进制文件的基本名称进行选择,如下所示
find /proc/*/exe -lname '*/whatever'
开发所有剩下的内容作为读者的练习;-)
答案3
POSIXly,使用ps
和awk
:
by_name_and_nice() {
# returns pids of processes with $2 as niceness and whose
# process name matches the $1 extended regexp
ps -A -o pid= -o nice= -o comm= |
NAME=$1 NICE=$2 awk '
$2 == ENVIRON["NICE"] {
pid = $1
sub(/^[[:space:]]*[^[:space:]]+ +[^[:space:]]+ /, "")
if ($0 ~ ENVIRON["NAME"]) print pid
}'
}
假设友好列和进程名称之间有一个空格字符。这恰好是 procps-ng 实现的情况,通常在基于 Linux 的系统上发现,但 POSIX 不保证。您可以删除 Niceness 列后的所有空格字符,但这存在错误表示名称以空格开头的进程的风险。
请注意,procps-ngps
至少将?
输出中的不可打印字符更改为不可打印字符,并且不可打印字符的构成取决于 调用者的区域设置ps
。例如,Stéphane
名称为 UTF-8 的进程可能会呈现为好像St??phane
语言环境使用与 UTF-8 不同的字符集。
procps-ng
的实现确实ps
支持一个-C
选项来匹配名称上的进程(受到 HP/UX' 的启发ps
),尽管这是精确的字节到字节相等匹配而不是正则表达式匹配,所以你可以这样做:
by_name_and_nice() {
# returns pids of processes with $2 as niceness and whose
# process name is exactly $1
ps -C "$1" -o pid= -o nice= |
awk -v nice="$2" '$2 == nice {print $1}'
}