¿Comando Linux / Unix para determinar si el proceso se está ejecutando?

97

Necesito un comando shell / bash independiente de la plataforma (Linux / Unix | OSX) que determinará si se está ejecutando un proceso específico. por ejemplo mysqld, httpd... ¿Cuál es la forma / comando más simple de hacer esto?

Carretera de la vida
fuente

Respuestas:

168

Si bien pidofy pgrepson excelentes herramientas para determinar qué se está ejecutando, ambos, desafortunadamente, no están disponibles en algunos sistemas operativos. Una seguridad definitiva sería utilizar lo siguiente:ps cax | grep command

La salida en Gentoo Linux:

14484? S 0:00 apache2
14667? S 0:00 apache2
19620? Sl 0:00 apache2
21132? Ss 0:04 apache2

La salida en OS X:

42582 ?? Z 0: 00.00 (smbclient)
46529 ?? Z 0: 00.00 (smbclient)
46539 ?? Z 0: 00.00 (smbclient)
46547 ?? Z 0: 00.00 (smbclient)
46586 ?? Z 0: 00.00 (smbclient)
46594 ?? Z 0: 00.00 (smbclient)

Tanto en Linux como en OS X, grep devuelve un código de salida, por lo que es fácil verificar si el proceso se encontró o no:

#!/bin/bash
ps cax | grep httpd > /dev/null
if [ $? -eq 0 ]; then
  echo "Process is running."
else
  echo "Process is not running."
fi

Además, si desea la lista de PID, también puede grep fácilmente para ellos:

ps cax | grep httpd | grep -o '^ [] * [0-9] *'

Cuya salida es la misma en Linux y OS X:

3519 3521 3523 3524

El resultado de lo siguiente es una cadena vacía, lo que hace que este enfoque sea seguro para los procesos que no se están ejecutando:

eco ps cax | grep aasdfasdf | grep -o '^[ ]*[0-9]*'

Este enfoque es adecuado para escribir una prueba de cadena vacía simple e incluso iterar a través de los PID descubiertos.

#!/bin/bash
PROCESS=$1
PIDS=`ps cax | grep $PROCESS | grep -o '^[ ]*[0-9]*'`
if [ -z "$PIDS" ]; then
  echo "Process not running." 1>&2
  exit 1
else
  for PID in $PIDS; do
    echo $PID
  done
fi

Puede probarlo guardándolo en un archivo (llamado "en ejecución") con permisos de ejecución (chmod + x en ejecución) y ejecutándolo con un parámetro: ./running "httpd"

#!/bin/bash
ps cax | grep httpd
if [ $? -eq 0 ]; then
  echo "Process is running."
else
  echo "Process is not running."
fi

¡¡¡ADVERTENCIA!!!

Tenga en cuenta que simplemente está analizando la salida, lo ps axque significa que, como se ve en la salida de Linux, no solo coincide con los procesos, sino también con los argumentos que se pasan a ese programa. Recomiendo encarecidamente ser lo más específico posible al utilizar este método (por ejemplo ./running "mysql", también coincidirá con los procesos 'mysqld'). Recomiendo encarecidamente usarlo whichpara verificar una ruta completa siempre que sea posible.


Referencias:

http://linux.about.com/od/commands/l/blcmdl1_ps.htm

http://linux.about.com/od/commands/l/blcmdl1_grep.htm

Caleb Grey
fuente
El proceso puede estar en ejecución, pero detenido. Entonces, si el objetivo es probar si mysqld o httpd están "en funcionamiento" (respondiendo), también debe verificar si está detenido o no.
oluc
2
Lo siento, pero si bien la respuesta es ciertamente correcta desde un punto de vista semántico, estoy totalmente en contra de intentar encontrar un proceso mediante la coincidencia de patrones en el vector arg de proceso. Cualquier enfoque de este tipo está condenado al fracaso tarde o temprano (de hecho, usted mismo lo admite, diciendo que se necesitan más controles). Agregué mi propia recomendación en una respuesta separada.
Peterh
6
grepTambién se encontrará en funcionamiento (por ejemplo, ps cax | grep randomnamesiempre devolverá 0 porque grephallazgos grep randomname(espero que esto está claro ...) Una solución es añadir corchetes alrededor de la primera letra del nombre del proceso, por ejemplo. ps cax | grep [r]andomname.
Kyle G.
ps cax | rev | cut -f1 -d' ' | revmostrará solo la columna de nombre, para facilitar el análisis.
Tyzoid
1
ps caxpuede que no muestre el nombre del comando por completo. Por ejemplo, imprime "chrome-browser" en lugar de "chromium-browser".
jarno
24

¡DEBE conocer el PID!

Encontrar un proceso tratando de hacer algún tipo de reconocimiento de patrones en los argumentos del proceso (como pgrep "mysqld") es una estrategia que está condenada al fracaso tarde o temprano. ¿Qué pasa si tienes dos mysqld ejecutándose? Olvídese de ese enfoque. PUEDE hacerlo bien temporalmente y PUEDE funcionar durante uno o dos años, pero luego sucede algo en lo que no ha pensado.

Solo el ID de proceso (pid) es verdaderamente único.

Guarde siempre el pid cuando lance algo en segundo plano. En Bash, esto se puede hacer con la $!variable Bash. Te ahorrarás TANTOS problemas al hacerlo.

Cómo determinar si el proceso se está ejecutando (por pid)

Así que ahora la pregunta es cómo saber si se está ejecutando un pid.

Simplemente haz:

ps -o pid = -p <pid>

Esto es POSIX y por lo tanto portátil. Devolverá el pid en sí mismo si el proceso se está ejecutando o no devolverá nada si el proceso no se está ejecutando. Estrictamente hablando, el comando devolverá una sola columna, el pid, pero dado que le hemos dado un encabezado de título vacío (lo que precede inmediatamente al signo igual) y esta es la única columna solicitada, el comando ps no usará el encabezado en absoluto. Que es lo que queremos porque facilita el análisis.

Esto funcionará en Linux, BSD, Solaris, etc.

Otra estrategia sería probar el valor de salida del pscomando anterior . Debería ser cero si el proceso se está ejecutando y distinto de cero si no lo está. La especificación POSIX dice que psdebe salir> 0 si se ha producido un error, pero no me queda claro qué constituye "un error". Por lo tanto, personalmente no estoy usando esa estrategia, aunque estoy bastante seguro de que funcionará también en todas las plataformas Unix / Linux.

Peterh
fuente
1
Excepto que esto no responde a la pregunta, que es determinar si se está ejecutando un servicio. El PID no se conocerá en estos casos, por lo tanto, esta respuesta sólo es válida si se hace saber el PID.
Highway of Life
2
Incorrecto. Mi punto del comentario es dar un paso atrás y decir que si primero te encuentras en la situación en la que tienes que hacer alguna forma de grep <sometext>encontrar un proceso dado, entonces has hecho algo mal cuando comenzaste el proceso, en mi humilde opinión. De la pregunta del OP, deduzco que de hecho él tiene control sobre cómo se inicia el proceso.
Peterh
2
El "término" más correcto para la pregunta OP debería haber sido "comando multiplataforma para determinar si un servicio se está ejecutando", no es el mismo sistema que ejecuta la verificación, sino un sistema externo, por lo que el PID simplemente no va a ser conocido en absoluto.
Highway of Life
2
Esto no es infalible. El proceso en el que está interesado puede haber muerto después de que el sistema haya estado activo el tiempo suficiente para que los PID se envuelvan, y es posible que se haya asignado a otro proceso el mismo PID que está buscando. stackoverflow.com/questions/11323410/linux-pid-recycling
Claymation
1
@claymation. Punto justo. Sin embargo, el método PID sigue siendo mejor que la coincidencia de patrones en argumentos de proceso, ya que el conflicto PID es mucho más improbable que iniciar accidentalmente dos instancias del mismo servicio. Solo mis dos centavos. :-)
peterh
15

En la mayoría de las distribuciones de Linux, puede usar pidof(8).

Imprimirá los identificadores de proceso de todas las instancias en ejecución de procesos especificados, o nada si no hay instancias en ejecución.

Por ejemplo, en mi sistema (tengo cuatro instancias de bashy una instancia de remminaejecución):

$ pidof bash remmina
6148 6147 6144 5603 21598

En otros Unices, pgrepo una combinación de psy greplogrará lo mismo, como otros han señalado con razón.

Frédéric Hamidi
fuente
+1 pidof httpdfunciona bien en Red Hat 5. Pero en mi Red Hat 4, pidofno está presente :-(
olibre
De hecho, este comando está menos extendido de lo que pensaba, edité mi respuesta para aclararlo.
Frédéric Hamidi
Buena respuesta limpia de hecho. (en sistemas compatibles). Gracias.
Mtl Dev
7

Esto debería funcionar en la mayoría de versiones de Unix, BSD y Linux:

PATH=/usr/ucb:${PATH} ps aux | grep httpd | grep -v grep

Probado en:

  • SunOS 5.10 [De ahí el PATH=...]
  • Linux 2.6.32 (CentOS)
  • Linux 3.0.0 (Ubuntu)
  • Darwin 11.2.0
  • FreeBSD 9.0-ESTABLE
  • Red Hat Enterprise Linux ES versión 4
  • Red Hat Enterprise Linux Server versión 5
Johnsyweb
fuente
2
+1 Sí, simplemente ps. Para evitar el segundo grepsugiero:ps aux | grep [h]ttpd
olibre
No utilicé el truco del corchete aquí para facilitar la colocación de una variable en el archivo principal grep.
Johnsyweb
1
Muy bien;) Acabo de probar en Red Hat AS 4 y Red Hat AP 5. ¡Por supuesto que funciona! Por lo tanto, puede agregar a su lista: Red Hat Enterprise Linux ES versión 4 y Red Hat Enterprise Linux Server versión 5 . Saludos
olibre
@Downvoter: ¿Por qué? ¿Qué me perdí? Por lo que puedo decir, ¡la respuesta aceptada es hacer la misma búsqueda!
Johnsyweb
6

La forma más sencilla es usar ps y grep:

command="httpd"
running=`ps ax | grep -v grep | grep $command | wc -l`
if [ running -gt 0 ]; then
    echo "Command is running"
else
    echo "Command is not running"
fi

Si su comando tiene algunos argumentos de comando, también puede poner más 'grep cmd_arg1' después de 'grep $ command' para filtrar otros procesos posibles que no le interesan.

Ejemplo: muéstrame si hay algún proceso java con el argumento proporcionado:

-Djava.util.logging.config.file = logging.properties

Esta corriendo

ps ax | grep -v grep | grep java | grep java.util.logging.config.file=logging.properties | wc -l
Pawel Solarski
fuente
2
En realidad, usar ps caxelimina la necesidad de usar grep -v. Así, por ejemplo, puede utilizar: ps cax | grep java > /dev/null || echo "Java not running".
Highway of Life
1
Hay un error en la tercera línea. por favor cambie "corriendo" a "$ corriendo".
Programador
5

Solo una pequeña adición: si agrega la -cbandera a ps, no necesita eliminar la línea que contiene el proceso grep con grep -vposterioridad. Es decir

ps acux | grep cron

es toda la escritura que necesitará en un sistema bsd-ish (esto incluye MacOSX). Puede dejar de -ulado si necesita menos información.

En un sistema donde la genética del pscomando nativo apunta a SysV, usaría

ps -e |grep cron

o

ps -el |grep cron 

para obtener una lista que contenga más que solo pid y nombre de proceso. Por supuesto, puede seleccionar los campos específicos para imprimir usando la -o <field,field,...>opción.

Tatjana Heuser
fuente
¿Cómo es esta respuesta portátil? (Usted dice que se deben usar diferentes formas del comando ps en diferentes plataformas)
peterh
ps desafortunadamente es una de esas herramientas con un conjunto diferente de opciones para el mismo resultado dependiendo de su ascendencia. Entonces, a menos que escriba su propio envoltorio (nuevamente incompatible con cualquier otra cosa) alrededor de esto, el camino a seguir sería conocer las principales líneas de herencia y adaptarse en consecuencia. Es diferente cuando está escribiendo un script: allí usaría estas diferencias para determinar en qué rama se encuentra y adaptar el comportamiento de su script. En pocas palabras: necesitará conocer ambos. Ejemplo famoso: el script "configure" de Larry Wall. Cita famosa: Felicitaciones, no estás dirigiendo a Eunice.
Tatjana Heuser
5

Al juntar las diversas sugerencias, la versión más limpia que pude encontrar (sin grep poco confiable que desencadena partes de palabras) es:

kill -0 $(pidof mysql) 2> /dev/null || echo "Mysql ain't runnin' message/actions"

kill -0 no mata el proceso, pero verifica si existe y luego devuelve verdadero, si no tiene pidof en su sistema, almacene el pid cuando inicie el proceso:

$ mysql &
$ echo $! > pid_stored

luego en el guión:

kill -0 $(cat pid_stored) 2> /dev/null || echo "Mysql ain't runnin' message/actions"
gletscher
fuente
3

Lo uso pgrep -l httpdpero no estoy seguro de que esté presente en cualquier plataforma ...
¿Quién puede confirmar en OSX?

olibre
fuente
Gracias @Johnsyweb. ¿Puedes comprobar también pidofpor favor? OK lo hiciste. Gracias. Así que deberíamos encontrar algo más que funcione en OSX ... Su básico ps|greppuede ser la solución única ;-)
olibre
1

Debe conocer el PID de su proceso.

Cuando lo inicie, su PID se registrará en la $!variable. Guarde este PID en un archivo.

Luego, deberá verificar si este PID corresponde a un proceso en ejecución. Aquí hay un script esqueleto completo:

FILE="/tmp/myapp.pid"

if [ -f $FILE ];
then
   PID=$(cat $FILE)
else
   PID=1
fi

ps -o pid= -p $PID
if [ $? -eq 0 ]; then
  echo "Process already running."  
else
  echo "Starting process."
  run_my_app &
  echo $! > $FILE
fi

Basado en la respuesta de peterh. El truco para saber si un PID determinado se está ejecutando está en la ps -o pid= -p $PIDinstrucción.

icarito
fuente
0

Este enfoque se puede utilizar en caso de que los comandos 'ps', 'pidof' y rest no estén disponibles. Yo personalmente uso procfs con mucha frecuencia en mis herramientas / scripts / programas.

   egrep -m1  "mysqld$|httpd$" /proc/[0-9]*/status | cut -d'/' -f3

Pequeña explicación de lo que está pasando:

  1. -m1 - detener el proceso en el primer partido
  2. "mysqld $ | httpd $" - grep coincidirá con las líneas que terminaron en mysqld O httpd
  3. / proc / [0-9] * - bash coincidirá con la línea que comenzó con cualquier número
  4. cortar - simplemente divida la salida por delimitador '/' y extraiga el campo 3
Tom Lime
fuente
0

Esto imprime el número de procesos cuyo nombre base es "navegador de cromo":

ps -e -o args= | awk 'BEGIN{c=0}{
 if(!match($1,/^\[.*\]$/)){sub(".*/","",$1)} # Do not strip process names enclosed by square brackets.
 if($1==cmd){c++}
}END{print c}' cmd="chromium-browser"

Si imprime "0", el proceso no se está ejecutando. El comando asume que la ruta del proceso no contiene espacio de ruptura. No he probado esto con procesos suspendidos o procesos zombie.

Probado usando gwakcomo awkalternativa en Linux.

Aquí hay una solución más versátil con algunos ejemplos de uso:

#!/bin/sh
isProcessRunning() {
if [ "${1-}" = "-q" ]; then
 local quiet=1;
 shift
else
 local quiet=0;
fi
ps -e -o pid,args= | awk 'BEGIN{status=1}{
 name=$2
 if(name !~ /^\[.*\]$/){sub(".*/","",name)} # strip dirname, if process name is not enclosed by square brackets.
 if(name==cmd){status=0; if(q){exit}else{print $0}}
}END{exit status}' cmd="$1" q=$quiet
}

process='chromium-browser'

printf "Process \"${process}\" is "
if isProcessRunning -q "$process" 
 then printf "running.\n"
 else printf "not running.\n"; fi

printf "Listing of matching processes (PID and process name with command line arguments):\n"
isProcessRunning "$process"
jarno
fuente
0

Aquí está mi versión. caracteristicas:

  • comprueba el nombre exacto del programa (primer argumento de la función). la búsqueda de "mysql" no coincidirá con la ejecución de "mysqld"
  • busca argumentos del programa (segundo argumento de la función)

guión:

#!/bin/bash

# $1 - cmd
# $2 - args
# return: 0 - no error, running; 1 - error, not running
function isRunning() {
    for i in $(pidof $1); do
        cat /proc/$i/cmdline | tr '\000' ' ' | grep -F -e "$2" 1>&2> /dev/null
        if [ $? -eq 0 ]; then
            return 0
        fi
    done
    return 1
}

isRunning java "-Djava.util.logging.config.file=logging.properties"
if [ $? -ne 0 ]; then
    echo "not running, starting..."
fi
Raigedas
fuente
0

Ninguna de las respuestas funcionó para mí, así que aquí está la mía:

process="$(pidof YOURPROCESSHERE|tr -d '\n')"
if [[ -z "${process// }" ]]; then
  echo "Process is not running."
else
  echo "Process is running."
fi

Explicación:

|tr -d '\n'

Esto elimina el retorno de carro creado por el terminal. El resto se puede explicar en este artículo .

Jeff Luyet
fuente
-1

La siguiente función de shell, que solo se basa en los comandos y opciones estándar POSIX, debería funcionar en la mayoría (si no en alguno) de los sistemas Unix y Linux. :

isPidRunning() {
  cmd=`
    PATH=\`getconf PATH\` export PATH
    ps -e -o pid= -o comm= |
      awk '$2 ~ "^.*/'"$1"'$" || $2 ~ "^'"$1"'$" {print $1,$2}'
  `
  [ -n "$cmd" ] &&
    printf "%s is running\n%s\n\n" "$1" "$cmd" ||
    printf "%s is not running\n\n" $1
  [ -n "$cmd" ]
}

$ isPidRunning httpd
httpd is running
586 /usr/apache/bin/httpd
588 /usr/apache/bin/httpd

$ isPidRunning ksh
ksh is running
5230 ksh

$ isPidRunning bash
bash is not running

Tenga en cuenta que se bloqueará cuando se le pase el dudoso nombre de comando "0]" y tampoco podrá identificar los procesos que tengan un espacio incrustado en sus nombres.

Tenga en cuenta también que la solución más votada y aceptada exige psopciones no portátiles y utiliza gratuitamente un shell que, a pesar de su popularidad, no se garantiza que esté presente en todas las máquinas Unix / Linux ( bash)

jlliagre
fuente
$ isPidRunning 0]imprime, por ejemplo, "0] se está ejecutando 3 [ksoftirqd / 0] 8 [rcuop / 0] 17 [rcuos / 0] 26 [rcuob / 0] 34 [migración / 0] 35 [watchdog / 0]" aquí.
jarno
¿Para qué necesitas esa cosa PATH?
jarno
Desarrollé la solución más aquí .
jarno
@jarno La configuración PATH es un requisito para que el script sea portátil. De lo contrario, fallaría al menos en Solaris 10 y anteriores y posiblemente en otras implementaciones de Unix.
jlliagre
1
@jarno Podría hacerlo, pero también tendré que repetir esta configuración de PATH para awk. Tenga en cuenta que volví a la antigua sintaxis de comillas invertidas para ser portátil con sintaxis bourne anterior a POSIX.
jlliagre