ver usuario todos terminar servicios saber procesos proceso los ejecucion detener corriendo como comando bash awk

bash - usuario - ver procesos en ejecucion linux



Cómo obtener el PID de un proceso en proceso (8)

Mejorando las respuestas de @Marvin y @Nils Goroll con un delineador que extrae los pids de todos los comandos en una variable de matriz de shell:

# run some command ls -l | rev | sort > /dev/null & # collect pids pids=(`jobs -l % | egrep -o ''^(/[[0-9]+/]/+| ) [ 0-9]{5} '' | sed -e ''s/^[^ ]* /+//'' -e ''s! $!!''`) # use them for something echo pid of ls -l: ${pids[0]} echo pid of rev: ${pids[1]} echo pid of sort: ${pids[2]} echo pid of first command e.g. ls -l: $pids echo pid of last command e.g. sort: ${pids[-1]} # wait for last command in pipe to finish wait ${pids[-1]}

¡En mi solución ${pids[-1]} contiene el valor normalmente disponible en $! . Tenga en cuenta el uso de jobs -l % que genera solo el trabajo "actual", que por defecto es el último iniciado.

Muestra de salida:

pid of ls -l: 2725 pid of rev: 2726 pid of sort: 2727 pid of first command e.g. ls -l: 2725 pid of last command e.g. sort: 2727

ACTUALIZACIÓN 2017-11-13: Se mejoró el pids=... que funciona mejor con comandos complejos (varias líneas).

Considere el siguiente ejemplo simplificado:

my_prog|awk ''...'' > output.csv & my_pid="$!" #Gives the PID for awk instead of for my_prog sleep 10 kill $my_pid #my_prog still has data in its buffer that awk never saw. Data is lost!

En bash, $my_pid apunta al PID para awk . Sin embargo, necesito el PID para my_prog . Si my_prog awk , my_prog no sabe descargar su búfer de salida y se pierden datos. Entonces, ¿cómo se obtendría el PID para my_prog ? Tenga en cuenta que ps aux|grep my_prog no funcionará, ya que puede haber varios my_prog en marcha.

NOTA: cambié cat a awk ''...'' para ayudar a aclarar lo que necesito.


Agregue un envoltorio de shell alrededor de su comando y capture el pid. Para mi ejemplo, uso iostat.

#!/bin/sh echo $$ > /tmp/my.pid exec iostat 1

Exec reemplaza el shell con el nuevo proceso preservando el pid.

test.sh | grep avg

Mientras eso funciona:

$ cat my.pid 22754 $ ps -ef | grep iostat userid 22754 4058 0 12:33 pts/12 00:00:00 iostat 1

Así que puedes:

sleep 10 kill `cat my.pid`

¿Es eso más elegante?


En función de su comentario, todavía no veo por qué prefiere matar a my_prog para que se complete de manera ordenada. Diez segundos es una medida bastante arbitraria en un sistema de multiprocesamiento mediante el cual my_prog podría generar 10k líneas o 0 líneas de salida dependiendo de la carga del sistema.

Si quieres limitar la salida de my_prog a algo más determinado, prueba

my_prog | head -1000 | awk

sin desprenderse del caparazón. En el peor de los casos, head cerrará su entrada y my_prog obtendrá un SIGPIPE. En el mejor de los casos, cambie my_prog para que le proporcione la cantidad de salida que desea.

agregado en respuesta al comentario :

En la medida en que tengas control sobre my_prog dale un argumento de -s duration opcional. Luego, en algún lugar de tu ciclo principal, puedes poner el predicado:

if (duration_exceeded()) { exit(0); }

donde la salida a su vez vaciará correctamente los ARCHIVOS de salida. Si está desesperado y no hay lugar para poner el predicado, esto podría implementarse usando la alarma (3), que intencionalmente no mostraré porque es malo.

El núcleo de tu problema es que my_prog ejecuta para siempre. Todo lo demás aquí es un truco para superar esa limitación.


Pude resolverlo nombrando explícitamente la tubería con mkfifo .

Paso 1: mkfifo capture .

Paso 2: ejecuta este script

my_prog > capture & my_pid="$!" #Now, I have the PID for my_prog! awk ''...'' capture > out.csv & sleep 10 kill $my_pid #kill my_prog wait #wait for awk to finish.

No me gusta la gestión de tener un mkfifo. Con suerte, alguien tiene una solución más fácil.


Aquí hay una solución sin envoltorios o archivos temporales. Esto solo funciona para una canalización en segundo plano cuyo resultado se captura fuera de stdout del script que lo contiene, como en su caso. Supongamos que quieres hacer:

cmd1 | cmd2 | cmd3 >pipe_out & # do something with PID of cmd2

Si solo bash pudiera proporcionar ${PIPEPID[n]} !! El "truco" de reemplazo que encontré es el siguiente:

PID=$( { cmd1 | { cmd2 0<&4 & echo $! >&3 ; } 4<&0 | cmd3 >pipe_out & } 3>&1 | head -1 )

Si es necesario, también puede cerrar el fd 3 (para cmd* ) y fd 4 (para cmd2 ) con 3>&- y 4<&- , respectivamente. Si haces eso, para cmd2 asegúrate de cerrar fd 4 solo después de redirigir fd 0 desde él.


Solo tuve el mismo problema. Mi solución:

process_1 | process_2 & PID_OF_PROCESS_2=$! PID_OF_PROCESS_1=`jobs -p`

Solo asegúrese de que el proceso_1 sea el primer proceso en segundo plano. De lo contrario, debe analizar la salida completa de jobs -l .


Con la inspiración de la respuesta de @Demosthenex: usando subshells:

$ ( echo $BASHPID > pid1; exec vmstat 1 5 ) | tail -1 & [1] 17371 $ cat pid1 17370 $ pgrep -fl vmstat 17370 vmstat 1 5


Estaba buscando desesperadamente una buena solución para obtener todos los PID de un trabajo de tuberías, y un enfoque prometedor falló miserablemente (ver revisiones previas de esta respuesta).

Por lo tanto, desafortunadamente, lo mejor que pude encontrar es analizar los jobs -l salida usando GNU awk:

function last_job_pids { if [[ -z "${1}" ]] ; then return fi jobs -l | awk '' /^/[/ { delete pids; pids[$2]=$2; seen=1; next; } // { if (seen) { pids[$1]=$1; } } END { for (p in pids) print p; }'' }