bash - usuario - ver proceso por pid linux
¿Cómo puedo encontrar el PID principal de nivel superior de un proceso dado usando bash? (5)
Bash definitivamente puede hacer recursión.
Puede recuperar el cuarto campo del archivo de estadísticas sin usar la utilidad de cut
externo haciendo algo como esto:
stat=($(</proc/$$/stat)) # create an array
ppid=${stat[3]} # get the fourth field
Digamos que ejecuto ps axf
y puedo ver que el árbol de proceso de mi comando se ve así:
800 ? Ss 0:00 /usr/sbin/sshd
10186 ? Ss 0:00 /_ sshd: yukondude [priv]
10251 ? S 0:00 /_ sshd: yukondude@pts/0
10252 pts/0 Ss 0:00 /_ -bash
10778 pts/0 S 0:00 /_ su -
10785 pts/0 S 0:00 /_ -su
11945 pts/0 R+ 0:00 /_ ps axf
Sé que puedo verificar $$
para el PID del shell actual (10785) o $PPID
para el PID principal (10778).
Pero solo quiero el PID principal de nivel superior, que sería 800 (daemon SSH) en este ejemplo. ¿Hay alguna manera de hacer eso fácilmente?
Aprendí de esta respuesta SO que puedo verificar recursivamente la cuarta entrada en el archivo /proc/PID/stat
para encontrar el PID primario de cada proceso:
# cut -f4 -d'' '' /proc/10785/stat
10778
# cut -f4 -d'' '' /proc/10778/stat
10252
# cut -f4 -d'' '' /proc/10252/stat
10251
# cut -f4 -d'' '' /proc/10251/stat
10186
# cut -f4 -d'' '' /proc/10186/stat
800
# cut -f4 -d'' '' /proc/800/stat
1
(El PID principal de nivel superior será el justo antes de que alcance el PID de init
, es decir, 1.)
Antes de escribir un pequeño bucle (no estoy seguro de si puedes usar la recursión en bash) para hacer esto, ¿hay un método mucho más directo que me esté perdiendo? Tal vez sólo otro parámetro de un archivo en /proc
? Un grep
través de esos archivos no reveló nada obvio.
Edición : Por supuesto, el proceso de nivel superior para todos los procesos de Linux es / sbin / init con un PID de 1. Lo que quiero es el PID del padre justo antes de eso: el padre del penúltimo.
Otra solución (desde here ):
ps -p $$ -o ppid=
Si falla una solución mejor, aquí hay un script simple (recursivo) para obtener el PID principal de nivel superior de cualquier número de proceso que le dé (o el shell actual si deja de lado el argumento PID):
#!/bin/bash
# Look up the top-level parent Process ID (PID) of the given PID, or the current
# process if unspecified.
function top_level_parent_pid {
# Look up the parent of the given PID.
pid=${1:-$$}
stat=($(</proc/${pid}/stat))
ppid=${stat[3]}
# /sbin/init always has a PID of 1, so if you reach that, the current PID is
# the top-level parent. Otherwise, keep looking.
if [[ ${ppid} -eq 1 ]] ; then
echo ${pid}
else
top_level_parent_pid ${ppid}
fi
}
Simplemente top_level_parent_pid
esta secuencia de comandos y llame a top_level_parent_pid
con o sin un argumento PID, según corresponda.
Gracias a @Dennis Williamson por sus muchas sugerencias sobre cómo escribir este script de manera compacta y eficiente.
Versión iterativa:
# ppid -- Show parent PID
# $1 - The process whose parent you want to show, default to $$
function ppid() {
local stat=($(</proc/${1:-$$}/stat))
echo ${stat[3]}
}
# apid -- Show all ancestor PID
# $1 - The process whose ancestors you want to show, default to $$
# $2 - Stop when you reach this ancestor PID, default to 1
function apid() {
local ppid=$(ppid ${1:$$})
while [ 0 -lt $ppid -a ${2:-1} -ne $ppid ]; do
echo $ppid
ppid=$(ppid $ppid)
done
}
Como dos funciones separadas, porque a veces solo quieres el PID principal y otras veces todo el árbol.
La versión OS X , adaptada de las respuestas de @albert y @ yukondude:
#!/usr/bin/env bash
# Look up the top-level parent Process ID (PID) of the given PID, or the current
# process if unspecified.
# From http://.com/questions/3586888/how-do-i-find-the-top-level-parent-pid-of-a-given-process-using-bash
function top_level_parent_pid {
# Look up the parent of the given PID.
PID=${1:-$$}
PARENT=$(ps -p $PID -o ppid=)
# /sbin/init always has a PID of 1, so if you reach that, the current PID is
# the top-level parent. Otherwise, keep looking.
if [[ ${PARENT} -eq 1 ]] ; then
echo ${PID}
else
top_level_parent_pid ${PARENT}
fi
}