¿Cómo determinar si un proceso se está ejecutando o no y usarlo para hacer un script de shell condicional?

108

¿Cómo puedo determinar si un proceso se está ejecutando o no y luego hacer que un script bash ejecute algunas cosas en función de esa condición?

Por ejemplo:

  • si el proceso se abcestá ejecutando, haz esto

  • si no se está ejecutando, hazlo.

Nirmik
fuente
1
Considere importante tener en cuenta que ninguna de las soluciones a continuación tiene en cuenta el estado del proceso. Un comentario sobre una de mis preguntas me trajo aquí, pero una respuesta me dio pistas sobre diferentes estados de un programa, como zombieproceso '(No es lo que describiría como un proceso "en ejecución"). Aquí se encuentra una lista completa de lo que indican los STATvalores de la columna, en la salida de ps, para aquellos inclinados a escribir una respuesta que se adapte a esto, o editar la suya propia.
user66001
Discusión relacionada: unix.stackexchange.com/questions/74185/…
blong
existe la mejor manera de verificar el proceso: stackoverflow.com/questions/3043978/…
Trevor Boyd Smith

Respuestas:

166

Un script bash para hacer algo así se vería así:

#!/bin/bash

# Check if gedit is running
# -x flag only match processes whose name (or command line if -f is
# specified) exactly match the pattern. 

if pgrep -x "gedit" > /dev/null
then
    echo "Running"
else
    echo "Stopped"
fi

Este script solo está verificando si el programa "gedit" se está ejecutando.

O solo puede verificar si el programa no se ejecuta así:

if ! pgrep -x "gedit" > /dev/null
then
    echo "Stopped"
fi
John Vrbanac
fuente
@DreadPirateShawn, ¿puede decirme por qué usar / dev / null y no simplemente un 0? El uso del número hace que el código sea más legible, al menos para un novato (como yo). Sin redireccionamiento, sin nada
Silviu
2
@Silviu ¿eh? Google /dev/null: "/ dev / null redirige la salida estándar del comando al dispositivo nulo, que es un dispositivo especial que descarta la información escrita en él" ... el uso 0redirigiría la salida del comando a un archivo llamado 0. En este caso, te aconsejaría > /dev/nullque te sientas más cómodo : lo verás en todas partes, ya que es la forma estándar / adecuada de descartar la salida.
DreadPirateShawn
Gracias, utilicé esto para un pequeño script que verifica si un programa se está ejecutando antes de ejecutarse. (aunque tuve que extenderlo un poco ya que el ejecutable de google chrome no tiene el mismo nombre que el comando de ejecución, el nombre del ejecutivo es solo chrome.)
Cestarian
3
Agregue el -xparámetro para pgrepque busque la aplicación exacta o, de lo contrario, obtendrá una falsa corrección si encuentra la misma cadena dentro del nombre de otra aplicación. Acabo de pasar 1 hora para descubrirlo.
Thanos Apostolou
1
Para verificar si el programa no se está ejecutando, use! pgrep
Mohammed Noureldin el
36

Cualquier solución que use algo como ps aux | grep abcopgrep abc sea ​​defectuosa.

¿Por qué?

Debido a que no está verificando si se está ejecutando un proceso específico, está verificando si hay algún proceso en ejecución que coincida abc. Cualquier usuario puede crear y ejecutar fácilmente un archivo ejecutable llamado abc(o que contenga abcen algún lugar de su nombre o argumentos), causando un falso positivo para su prueba. Hay varias opciones a las que puede postularse ps, grepypgrep de restringir la búsqueda, pero todavía no conseguirán una prueba fiable.

Entonces, ¿cómo pruebo de manera confiable un determinado proceso en ejecución?

Eso depende de para qué necesita la prueba.

Quiero asegurarme de que el servicio abc esté ejecutando y, si no, iniciarlo

Para eso están init y advenedizo. Comenzarán el servicio y se asegurarán de que su pid se almacene en un archivo pid. Intente iniciar el servicio nuevamente (a través de init o upstart) y verificará el archivo pid, y lo iniciará si no está allí, o abortará si ya se está ejecutando. Esto todavía no es 100% confiable, pero es lo más cercano posible.

Vea ¿Cómo puedo verificar si mi servidor de juegos aún se está ejecutando? ... para otras soluciones.

ABC es mi guión. Necesito asegurarme de que solo se esté ejecutando una instancia de mi script.

En este caso, use un archivo de bloqueo o un lockdir. P.ej

#!/usr/bin/env bash

if ! mkdir /tmp/abc.lock; then
    printf "Failed to acquire lock.\n" >&2
    exit 1
fi
trap 'rm -rf /tmp/abc.lock' EXIT  # remove the lockdir on exit

# rest of script ...

Vea Bash FAQ 45 para otras formas de bloqueo.

geirha
fuente
3
Si bien esto es técnicamente cierto, nunca he encontrado personalmente un problema de este tipo en la vida real. La mayoría de los programas no cambian sus nombres de manera que rompan los scripts. Por lo tanto, para scripts simples, algo como pgrepo pses perfectamente adecuado y su enfoque parece excesivo. Sin embargo, si está escribiendo un script para distribución pública, debe escribirlo de la manera más segura posible.
Scott Severance
2
@ScottSeverance Programas cambiar nombres no es el problema; eso requeriría intervención independientemente. Son otros usuarios que ejecutan el mismo programa u otros programas con nombres similares que de repente harán que el script obtenga falsos positivos y, por lo tanto, haga lo incorrecto. Simplemente prefiero "trabajos" en lugar de "principalmente trabajos".
geirha
2
Yo hablo mal. Pero muchos de nosotros ejecutamos sistemas de usuario único. Y en una situación de múltiples usuarios, es fácil también buscar el nombre de usuario.
Scott Severance
1
¿Qué pasa si su script falla durante el tiempo de ejecución y muere antes de desbloquear el archivo?
jp093121
2
@ jp093121 La trampa EXIT se activa cuando sale el script. Si sale porque llega al final del script, un comando de salida o recibe una señal (que puede manejarse), el rmcomando se ejecuta. Por lo tanto, siempre que termine después de que se haya establecido la trampa, el bloqueo debería desaparecer.
geirha
18

Esto es lo que uso:

#!/bin/bash

#check if abc is running
if pgrep abc >/dev/null 2>&1
  then
     # abc is running
  else
     # abc is not running
fi

En inglés simple: si 'pgrep' devuelve 0, el proceso se está ejecutando, de lo contrario no lo está.


Lectura relacionada:

Bash Scripting :: Comparaciones de cadenas

Manuales de Ubuntu pgrep

Zuul
fuente
gracias!
Probé
pgreptiene el mismo "característica" de 15 caracteres límite anteriormente mencionado, así por ejemplo pgrep gnome-power-managertambién fallaría
Thorsen
1
Asegúrese de utilizar la -xopción pgrep : "Solo coincide con los procesos cuyo nombre (o línea de comando si se especifica -f) coincide exactamente con el patrón".
Alastair Irvine
5

Por lo general, tengo un pidof -x $(basename $0)en mis scripts para verificar si ya se está ejecutando.

Rommel Cid
fuente
2

Refiriéndose a la idea de @ rommel-cid, puede usar pidofcon el || (||) para ejecutar un comando si el proceso no existe y && para ejecutar algo si el proceso existe, creando así un condicional rápido if / then / else. Por ejemplo, aquí hay uno con un proceso en ejecución (mi navegador Chrome, cuyo nombre de proceso es "Chrome") y otro que prueba un proceso que no existe. Suprimí la salida estándar usando 1> / dev / null para que no se imprima:

$ (pidof chrome 1>/dev/null && echo "its running? ok, so am i then" ) || echo "it's not running? ok i'll run instea\
d"
its running? ok, so am i then
$ (pidof nosuchprocess 1>/dev/null && echo "its running? ok, so am i then" ) || echo "it's not running? ok i'll run\
 instead"
it's not running? ok i'll run instead
$
yuvilio
fuente
1

Ninguna de las soluciones "simples" funcionó para mí porque el binario que necesito verificar no está instalado en todo el sistema, por lo que tengo que verificar con la ruta, que a su vez requiere el uso de ps -ef | grepenfoque:

app="$_sdir/Logic 1.2.18 (64-bit)/Logic"

app_pid=`ps -ef | grep "$app" | awk '{print $2}'`

if `ps -p $app_pid > /dev/null`; then
    echo "An instance of logic analyzer is appear to be running."
    echo "Not starting another instance."
    exit 5
else
    nohup "$app" &> /dev/null &
fi
ceremcem
fuente
0

Lo primero que me vino a la mente para su problema:
ps aux | grep -i abcmostrará los detalles del proceso si se está ejecutando. Puede hacer coincidir el número de líneas o el tiempo durante el cual se ejecuta y comparar con cero o cualquier otra manipulación. Cuando ejecute el comando anterior, le mostrará al menos una línea de salida, es decir, detalles sobre el proceso creado por el comando grep. Así que tenga cuidado con eso.
Eso debería hacer como un simple truco. Póngalo en el script bash y vea si es útil.

drake01
fuente
0

Utilizando start-stop-daemon:

/sbin/start-stop-daemon --background --make-pidfile --pidfile /tmp/foo.pid -S --startas /usr/bin/program -- arg1 arg2

Funciona como usuario normal.

Martin Monperrus
fuente
0

Descubrí que la respuesta aceptada publicada por @John Vrbanac no funcionó para mí, y que la respuesta publicada por @geirha no responde a la pregunta original.

La solución de John Vrbanac no funcionó para verificar si un proceso PHP se estaba ejecutando o no para mí, estoy ejecutando CentOS 7.

La respuesta de @ geirha solo asegura que una instancia no se esté ejecutando antes de comenzar otra. Esta no era la pregunta original, la pregunta original era verificar si un proceso se está ejecutando o no.

Esto es lo que funcionó para mí:

Digamos que mi proceso tenía la cadena "Jane" en su nombre de proceso. Esto encontrará si se está ejecutando o no. Esto funciona para los scripts BASH y PHP.

ps -aux | grep "[J]ane" > /dev/null 2>&1
if [[ "$?" == "0" ]]; then
    echo "It's running"
else
    echo "It's not running"
fi
Wayne Workman
fuente
1
Ah, bueno, como este es un sitio de preguntas y respuestas de Ubuntu, no es sorprendente que algunas de las respuestas aquí no funcionen en CentOS 7, ya que Linux está fuera de tema aquí. Otras versiones de Linux son compatibles con unix.stackexchange.com
Elder Geek
Aunque el autor de la respuesta usa CentOS, esta respuesta todavía es válida para ubuntu.
Phillip -Zyan K Lee- Stockmann
0
## bash

## function to check if a process is alive and running:

_isRunning() {
    ps -o comm= -C "$1" 2>/dev/null | grep -x "$1" >/dev/null 2>&1
}

## example 1: checking if "gedit" is running

if _isRunning gedit; then
    echo "gedit is running"
else
    echo "gedit is not running"
fi

## example 2: start lxpanel if it is not there

if ! _isRunning lxpanel; then
    lxpanel &
fi

## or

_isRunning lxpanel || (lxpanel &)

Nota : pgrep -x lxpanelo pidof lxpanelaún informa que se lxpanelestá ejecutando incluso cuando está inactivo (zombie); así que para obtener un proceso vivo y en funcionamiento, necesitamos usar psygrep

Bach Lien
fuente
-1

A partir del 23 de septiembre de 2016, pgrep parece requerir una opción "-x" para que el script de muru funcione.

#!/bin/bash

if pgrep -x "conky" > /dev/null 2>&1
then
  echo "conky running already"
else
  echo "now starting conky"
  conky
fi
exit 0

Probé y probé el script anterior en una máquina Ubuntu 16.04.1. ¡Disfrutar!

dzmanto
fuente
-1
#!/bin/bash
while [ true ]; do     # Endless loop.
  pid=`pgrep -x ${1}`  # Get a pid.
  if [ -z $pid ]; then # If there is none,
    ${1} &             # Start Param to background.
  else
    sleep 60           # Else wait.
  fi
done
usuario7449824
fuente
1
Bienvenido a Ask Ubuntu! Recomiendo editar esta respuesta para expandirla con detalles específicos sobre lo que hace. (Consulte también ¿Cómo escribo una buena respuesta? Para obtener consejos generales sobre qué tipo de respuestas se consideran más valiosas en AskUbuntu.)
David Foerster
-3

isProcessRunning () {if [$ (pidof $ 1)> / dev / null]; entonces retval = 'verdadero'; sino retval = 'falso'; fi; echo $ retval; }

isProcessRunning geany

cierto

Dominic
fuente