Cómo verificar si existe una identificación de proceso (PID)

En un script bash, quiero hacer lo siguiente (en pseudo-código):

if [ a process exists with $PID ]; then kill $PID fi 

¿Cuál es la expresión apropiada para la statement condicional?

Para verificar la existencia de un proceso, use

 kill -0 $pid 

Pero igual que @unwind dijo, si vas a matarlo de todos modos, solo

 kill $pid 

o tendrás una condición de carrera.

Si desea ignorar la salida de texto de kill y hacer algo basado en el código de salida, puede

 if ! kill $pid > /dev/null 2>&1; then echo "Could not send SIGTERM to process $pid" >&2 fi 

La mejor manera es:

 if ps -p $PID > /dev/null then echo "$PID is running" # Do something knowing the pid exists, ie the process with $PID is running fi 

El problema con:

 kill -0 $PID 

es el código de salida será distinto de cero, incluso si el pid se está ejecutando y no tiene permiso para matarlo. Por ejemplo:

 kill -0 1 

y

 kill -0 $non-running-pid 

tiene un código de salida indistinguible (distinto de cero) para un usuario normal, pero el proceso de inicio (PID 1) ciertamente se está ejecutando.

DISCUSIÓN

Las respuestas que analizan las condiciones de muerte y carrera son exactas si el cuerpo de la prueba es “matar”. Vine buscando al general ” ¿cómo se prueba una existencia de PID en bash “?

El método / proc es interesante, pero en cierto sentido rompe el espíritu de la abstracción del comando “ps”, es decir, no necesita buscar en / proc porque, ¿qué pasa si Linus decide llamar al archivo “exe” algo más?

 if [ -n "$PID" -a -e /proc/$PID ]; then echo "process exists" fi 

o

 if [ -n "$(ps -p $PID -o pid=)" ] 

En la última forma, -o pid= es un formato de salida para mostrar solo la columna de ID de proceso sin encabezado. Las comillas son necesarias para el operador de cadena no vacía -n para dar un resultado válido.

ps comando ps con -p $PID puede hacer esto:

 $ ps -p 3531 PID TTY TIME CMD 3531 ? 00:03:07 emacs 

Tienes dos formas:

Comencemos por buscar una aplicación específica en mi computadora portátil:

 [root@pinky:~]# ps fax | grep mozilla 3358 ? S 0:00 \_ /bin/sh /usr/lib/firefox-3.5/run-mozilla.sh /usr/lib/firefox-3.5/firefox 16198 pts/2 S+ 0:00 \_ grep mozilla 

Todos los ejemplos ahora buscarán PID 3358.

Primera forma : Ejecute “ps aux” y grep para el PID en la segunda columna. En este ejemplo busco Firefox, y luego es PID:

 [root@pinky:~]# ps aux | awk '{print $2 }' | grep 3358 3358 

Entonces tu código será:

 if [ ps aux | awk '{print $2 }' | grep -q $PID 2> /dev/null ]; then kill $PID fi 

Segunda forma : solo busca algo en el /proc/$PID . Estoy usando “exe” en este ejemplo, pero puedes usar cualquier otra cosa.

 [root@pinky:~]# ls -l /proc/3358/exe lrwxrwxrwx. 1 elcuco elcuco 0 2010-06-15 12:33 /proc/3358/exe -> /bin/bash 

Entonces tu código será:

 if [ -f /proc/$PID/exe ]; then kill $PID fi 

Por cierto: ¿qué pasa con kill -9 $PID || true kill -9 $PID || true ?


EDITAR:

Después de pensarlo por unos meses … (alrededor de 24 …) la idea original que di aquí es un truco agradable, pero muy poco práctico. Si bien enseña algunos detalles de implementación de Linux, no funcionará en Mac, Solaris o * BSD. Incluso puede fallar en futuros kernels de Linux. Por favor, use “ps” como se describe en otras respuestas.

Creo que es una mala solución, que se abre para las condiciones de carrera. ¿Qué pasa si el proceso muere entre su prueba y su llamada a matar? Entonces matar fallará. Entonces, ¿por qué no probar el kill en todos los casos y verificar su valor de retorno para descubrir cómo fue?

Parece que quieres

 wait $PID 

que volverá cuando finalice $pid .

De lo contrario, puedes usar

 ps -p $PID 

para comprobar si el proceso aún está activo (esto es más efectivo que kill -0 $pid porque funcionará incluso si no posee el pid).

aquí guardo el PID en un archivo llamado .pid (que es algo así como / run / …) y solo ejecuto el script si aún no se está ejecutando.

 #!/bin/bash if [ -f .pid ]; then read pid < .pid echo $pid ps -p $pid > /dev/null r=$? if [ $r -eq 0 ]; then echo "$pid is currently running, not executing $0 twice, exiting now..." exit 1 fi fi echo $$ > .pid # do things here rm .pid 

nota: hay una condición de carrera ya que no verifica cómo se llama a ese pid. si el sistema se reinicia y existe .pid pero es utilizado por una aplicación diferente, esto podría generar “consecuencias imprevistas”.

Por ejemplo, en GNU / Linux puedes usar:

 Pid=$(pidof `process_name`) if [ $Pid > 0 ]; then do something else do something fi 

O algo así como

 Pin=$(ps -A | grep name | awk 'print $4}') echo $PIN 

y eso te muestra el nombre de la aplicación, solo el nombre sin identificación.