Фильтрация процессов по имени и номеру

Фильтрация процессов по имени и номеру

Я пытаюсь создать скрипт для поиска номера 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-Cps

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}'
}

Связанный контент