
Я пытаюсь создать скрипт для поиска номера PID, используя только имя процесса и nice номер, но у меня это не получается.
решение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
процессы с их приятностью = 0 (по умолчанию),
by_name_and_nice 'b.*' '.*'
найдет все процессы, имена которых начинаются с буквы 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 regexиспользуется -P
опцией GNU grep).
Это только для демонстрационных целей; довольно бессмысленно пытаться выбирать по хорошему значению без какого-либо оператора "больше" или "меньше". Кроме того, выбор по имени процесса не очень надежен, поскольку имя процесса находится под полным контролем процесса, который безжалостно используется любым двухбитным вредоносным ПО и дерьмовым ПО, чтобы называть себя 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
}'
}
Это предполагает, что между столбцом niceness и именем процесса есть один пробел. Так и происходит с реализацией procps-ng, которая обычно встречается в системах на базе Linux, но не гарантируется POSIX. Вы можете удалить все пробельные символы после столбца niceness, но это создает риск неправильного представления процессов, имена которых начинаются с пробела.
Обратите внимание, что procps-ng ps
по крайней мере изменяет непечатаемые символы на ?
в выводе, а то, что составляет непечатаемый символ, зависит от локали вызывающего ps
. Например, процесс с Stéphane
именем UTF-8 может быть отображен так, как St??phane
будто локаль использует другой набор символов, нежели UTF-8.
Реализации поддерживают возможность сопоставления процессов по имени (вдохновлено HP/UX' ), хотя это точное побайтовое сопоставление, а не сопоставление с регулярным выражением, поэтому вы можете сделать следующее procps-ng
:ps
-C
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}'
}