Filtre processos por nome e número legal

Filtre processos por nome e número legal

Estou tentando criar um script para encontrar o número PID apenas com o nome do processo e o número legal, mas não estou conseguindo.

Responder1

Usando pgreppara primeiro obter os PIDs de todos os processos que correspondem à expressão dada como o primeiro argumento e, em seguida, fazer um loop por eles para extrair aqueles que possuem um bom valor correspondente ao segundo argumento.

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

Teste:

$ 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

(sem saída)

Responder2

by_name_and_nice(){ grep -hoPs "^[^ ]+(?= \($1\)( [^ )]+){16} $2 )" /proc/*/stat; }

by_name_and_nice bash 0encontrará todos bashos processos com gentileza = 0 (o padrão),

by_name_and_nice 'b.*' '.*'encontrará todos os processos com seus nomes começando com b, não importando sua gentileza, e assim por diante.

Se você também obtém processos com novas linhas e lixo binário em seus nomes, pode precisar de algo um pouco mais complicado:

by_name_and_nice(){
    local -; set -o pipefail
    LC_ALL=C grep -zhoPs "^[^ ]+(?= \($1\)( [^ )]+){16} $2 )" /proc/*/stat | xargs -0rn1
}

Para corresponder a uma nova linha no nome do processo, você deve usar by_name_and_nice '(?s:foo.*)' 0(leia sobre osintaxe regex pcreusado pela opção do GNU grep -P).


Isto é apenas para fins de demonstração; é bastante inútil tentar selecionar por um valor agradável sem algum operador maior ou menor que. Além disso, a seleção pelo nome do processo não é muito confiável, porque o nome do processo está sob o controle total do processo, que é cruelmente abusado por qualquer malware e crapware de dois bits para se autodenominar psou bash. Uma ideia melhor seria selecionar pelo nome base do binário, como em

find /proc/*/exe -lname '*/whatever'

Desenvolvendo tudo o que resta como exercício para o leitor ;-)

Responder3

POSIXly, com pse 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
      }'
}

Isso pressupõe que haja um único caractere de espaço entre a coluna de gentileza e o nome do processo. Esse é o caso da implementação procps-ng normalmente encontrada em sistemas baseados em Linux, mas não é garantida pelo POSIX. Você pode remover todos os caracteres de espaço em branco após a coluna de gentileza, mas isso corre o risco de deturpar processos cujo nome começa com espaço em branco.

Observe que o procps-ng pspelo menos altera caracteres não imprimíveis ?na saída e o que constitui um caractere não imprimível depende da localidade do chamador de ps. Por exemplo, um processo com UTF-8 Stéphanecomo nome poderia ser renderizado como St??phanese a localidade usasse um conjunto de caracteres diferente de UTF-8.

As procps-ngimplementações de psdoes suportam uma -Copção para combinar processos por nome (inspirado em HP/UX' ps), embora seja uma correspondência exata de igualdade byte a byte em vez de uma correspondência de expressão regular, então você poderia fazer:

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

informação relacionada