
Estoy intentando crear un script para encontrar el número PID solo con el nombre del proceso y el número bonito, pero no puedo.
Respuesta1
Usar pgrep
para obtener primero los PID de todos los procesos que coincidan con la expresión dada como primer argumento, y luego recorrerlos para extraer los que tienen un buen valor correspondiente al 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 }'
}
Pruebas:
$ 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
(ninguna salida)
Respuesta2
by_name_and_nice(){ grep -hoPs "^[^ ]+(?= \($1\)( [^ )]+){16} $2 )" /proc/*/stat; }
by_name_and_nice bash 0
encontrará todos bash
los procesos con su amabilidad = 0 (el valor predeterminado),
by_name_and_nice 'b.*' '.*'
encontrará todos los procesos cuyo nombre comience con a b
, sin importar su amabilidad, y así sucesivamente.
Si sigue lo anterior para obtener procesos con nuevas líneas y basura binaria en sus nombres, es posible que necesite algo un poco más complicado:
by_name_and_nice(){
local -; set -o pipefail
LC_ALL=C grep -zhoPs "^[^ ]+(?= \($1\)( [^ )]+){16} $2 )" /proc/*/stat | xargs -0rn1
}
Para hacer coincidir una nueva línea en el nombre del proceso, debe usar by_name_and_nice '(?s:foo.*)' 0
(lea más sobre elsintaxis de expresiones regulares pcreutilizado por la opción GNU grep -P
).
Esto es sólo para fines de demostración; es bastante inútil intentar seleccionar por buen valor sin algún operador mayor o menor que. Además, seleccionar por nombre de proceso no es muy confiable, porque el nombre del proceso está bajo el control total del proceso, que es abusado implacablemente por cualquier malware de dos bits y software basura que se llame a sí mismo ps
o bash
. Una mejor idea sería seleccionar por el nombre base del binario, como en
find /proc/*/exe -lname '*/whatever'
Desarrollando todo esto queda como ejercicio para el lector ;-)
Respuesta3
POSIXly, con ps
y 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
}'
}
Eso supone que hay un solo carácter de espacio entre la columna de amabilidad y el nombre del proceso. Ese es el caso de la implementación procps-ng que normalmente se encuentra en los sistemas basados en Linux, pero POSIX no lo garantiza. Podrías eliminar todos los espacios en blanco después de la columna de amabilidad, pero eso corre el riesgo de tergiversar los procesos cuyo nombre comienza con espacios en blanco.
Tenga en cuenta que procps-ng ps
al menos cambia los caracteres no imprimibles ?
en la salida y lo que constituye un carácter no imprimible depende de la ubicación de la persona que llama a ps
. Por ejemplo, un proceso con UTF-8 Stéphane
como nombre podría representarse como St??phane
si la configuración regional usara un juego de caracteres diferente al de UTF-8.
Sin embargo, las procps-ng
implementaciones de ps
Does admiten una -C
opción para hacer coincidir procesos en el nombre (inspirado en HP/UX' ps
), aunque se trata de una coincidencia exacta de igualdad byte a byte en lugar de una coincidencia de expresión regular, por lo que podría hacer:
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}'
}