¿Puede ps mostrar solo procesos no kernel en Linux?

Respuestas:

37

Esto debería hacer (bajo Linux):

ps --ppid 2 -p 2 --deselect

kthreadd(PID 2) tiene PPID 0 ( en Linux 2.6+ ) pero psno permite filtrar por PPID 0; Por lo tanto, esta solución.

Hauke ​​Laging
fuente
Bien, pero ¿qué tan garantizado es que kthreaddsiempre sea PID 2?
l0b0
@ l0b0 No tengo idea :-) Puede hacer esto en dos pasos: determine el PID de kthreadd, luego cree la psllamada correspondiente. ¿Qué tan seguro está de que esta cosa "siempre" se llame "kthreadd"? Una solución segura sería más complicada, se ejecuta psnormalmente y analiza la salida, tal vez haga algunas pruebas.
Hauke ​​Laging
2
En Linux 2.4 en x86 arch al menos, esos procesos tenían ppid 1, por lo que no se podían distinguir de esa manera.
Stéphane Chazelas
1
ser como "ps -ef" do "ps --ppid 2 -p 2 --deselect -f" y hacerlo como "ps aux" do "ps --ppid 2 -p 2 --deselect u"
Peter
1
@Totor Lo revisé y parece que es la xbandera que no funciona con esto. ps au --ppid 2 -p 2 --deselectfunciona bien
Sankalp
9

Una forma de reconocer los procesos del kernel es que no usan memoria de usuario, por lo que el campo vsz es 0. Esto también atrapa a los zombies (gracias a Stephane Chazelas por esta observación), que pueden eliminarse en función de su estado.

ps axl | awk '$7 != 0 && $10 !~ "Z"'

Para enumerar solo los PID:

ps -e -o pid= -o state= -o vsize= | awk '$2 != "Z" && $3 != 0 {print $1}'
Gilles 'SO- deja de ser malvado'
fuente
Al igual que mi solución, también incluirá procesos zombie.
Stéphane Chazelas
1
@StephaneChazelas Buen punto, he agregado una condición al filtro.
Gilles 'SO- deja de ser malvado'
9

En la práctica, encontré el siguiente idioma suficiente:

ps auxf | grep -v ]$

Filtra las líneas que terminan entre paréntesis, lo que puede resultar en la omisión de entradas no deseadas, pero es muy poco probable. A cambio, es bastante fácil de recordar y relativamente rápido de escribir.

Algunos procesos como avahi-daemon agregan a su información de nombre de proceso entre paréntesis (el nombre de host en el caso de avahi-daemon) y serán filtrados por este comando.

onetom
fuente
8

Una de las particularidades de esos procesos es que no están respaldados por un archivo ejecutable, por lo que podría hacer ( en zsh ):

ps /proc/[0-9]*/exe(^-@:h:t)

O con cualquier shell POSIX:

ps -p "$(find -L /proc/[0-9]*/exe ! -type l | cut -d / -f3 | paste -sd , -)"

Eso es verificar los procesos cuyo /proc/<pid>/exees un enlace a un archivo.

Pero eso significa que debe ser superusuario para poder verificar el estado del /proc/<pid>/exeenlace simbólico.

Editar : como sucede, los procesos zombies (al menos) satisfacen la misma condición, por lo que si no desea que se excluyan, tendrá que volver a agregarlos. Me gusta:

ps -p "$(
  { find -L /proc/[0-9]*/exe ! -type l | cut -d / -f3
    ps -Ao pid=,state= | sed -n 's/ Z//p'
  } | paste -sd , -)"

Tenga en cuenta que ps -fmuestra esos nombres de proceso entre corchetes no porque sean procesos del núcleo, sino porque tienen un vacío argv[](por lo que ps muestra el nombre del proceso en lugar de argv[0]allí). Puede tener un proceso de espacio de usuario con un espacio vacío argv[]también y puede tener un nombre de proceso con un argv[0]formulario que sea [some-string]así que filtrar la pssalida en función de esos corchetes no es una opción infalible.

Stéphane Chazelas
fuente
Esta es una sintaxis de shell no estándar, supongo.
Totor
1
@Totor, como dije, el primero es la zshsintaxis. El segundo es estándar POSIX sh(y psy findy cuty paste) sintaxis. Por supuesto, /procPOSIX no lo especifica.
Stéphane Chazelas
Aceptando esta respuesta porque es universal (gracias por la edición). Sin embargo, la respuesta de Hauke ​​Laging también es bastante agradable y directa siempre que no se trate con un núcleo 2.4.
Totor
@Totor, la respuesta de Hauke ​​también tiene la ventaja de no requerir privilegios de superusuario. Mi respuesta funciona con núcleos 2.4 y 2.6 / 3, pero supongo que no hay garantía de que funcione en 4.x de todos modos.
Stéphane Chazelas
Hmm, tienes razón, no pensé en los privilegios de root. Puede conducir a errores ya que aún obtienes una respuesta cuando no eres root, pero es diferente (por lo que debes ser cauteloso al contarlos, por ejemplo wc -l). Bueno, entonces aceptaré la respuesta de Hauke ​​Laging y te daré un voto positivo. ;)
Totor
1

También podría analizar el psresultado y buscar nombres de procesos que no estén entre paréntesis:

ps aux | awk '$NF!~/^\[.+\]$/'
terdon
fuente
Una forma un poco menos confiable de obtener la lista de usuarios que le interesan: awk -F: '$7 ~ home { print $1 }' /etc/passwd- pero aún obtendrá procesos que mencionan dicho nombre de usuario, y dejará el archivo temporal por ahí. Retiraré mi voto negativo, pero solo porque su tercera solución es razonable.
Keith Thompson
Bah, tienes toda la razón, @KeithThompson, eliminaste a los demás, no valen la pena. ¿Podrías ayudarme a limpiar los (ahora) comentarios obsoletos?
terdon
2
Tenga en cuenta que $NFes la última palabra de la línea de comando en la ps auxsalida. Los procesos no kernel pueden tener [...]allí. Como dije en mi respuesta, la [xxx]notación no se debe a que son procesos del núcleo, sino porque no tienen línea de comando (sin argumento), lo que también está permitido para los procesos que no son del núcleo.
Stéphane Chazelas
1

Para cualquiera que intente esto en busybox donde psestá muy simplificado y el resultado es diferente, esta variante de la gran respuesta de Gilles funciona bien:

ps -o pid,user,comm,vsz,stat | awk '$4 != 0 && $5 !~ "Z"'

Según la respuesta de Gilles, la metodología aquí es encontrar procesos que no usan memoria de usuario (`vsz col == 0) y filtrar procesos zombies (el estado col no es 'Z').

Las columnas de salida se pueden ajustar fácilmente, siempre que los números de campo awk basados ​​en 1 se ajusten en consecuencia. Vea las opciones que tiene su ps disponible al poner un valor falso y se lo dirá. Por ejemplo:

$ ps -o foo
ps: bad -o argument 'foo', supported arguments: user,group,comm,args,pid,ppid,pgid,tty,vsz,stat,rss
Russ
fuente
0

Si solo necesita los recuentos ... Tenía una necesidad similar de filtrar los procesos kernel vs. usuario, pero solo necesitaba los respectivos recuentos de cada uno. Esta fue mi solución:

ps -eo vsize | awk '{p[$1==0]++} END {printf "%-16s %6d\n%-16s %6d\n%-16s %6d\n", "Kernel processes", p[1], "User processes", p[0], "Total processes", p[0]+p[1]}'

Salida de muestra :

Kernel processes    353
User processes       52
Total processes     405

Explicación : Estoy usando el truco de que se puede suponer que los procesos VSZ = 0 son procesos del núcleo. Entonces awk, con , evalúo una comparación en VSZ (desde ps -eo vsize), si es igual a cero. El resultado de la comparación será un booleano 0 o 1. Hago una matriz p[]y, a medida que avanzo en la lista de procesos, si es un proceso de kernel, incremente p[1]++. De lo contrario, como proceso de usuario, incremente p[0]++. Después de todo el incremento, etiqueto e imprimo los valores (es decir, los recuentos) para p [0] y p [1] en el END { }bloque.

Joshua Huber
fuente
0

Lo que estás buscando, mi amigo, no es ps, pero pstree.

Primero, identifique el primer proceso del núcleo. Su PID es comúnmente 1 en el sistema sin systemd y 2 con systemd.

Luego usa este comando:

$ pstree -p <1 or 2> | grep -o '([0-9]\+)' | grep -o '[0-9]\+'

La respuesta seleccionada (una con ✅) está usando otro comando:

$ ps --ppid 2 -p 2 --deselect

El problema con este pscomando es que solo incluye hijos directos pero no todos los descendientes. El pstreecomando incluye a todos los descendientes. Puede comparar y contar la salida de estos dos comandos (una manera fácil es usar | wc) para verificar.

ssppjj
fuente
0

He creado el script psa para ese propósito. Tenga en cuenta que depende de la herramienta linechop .

Tomáš Pospíšek
fuente