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?
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?
Respuestas:
Si bien pidof
y pgrep
son 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 ax
que 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 which
para verificar una ruta completa siempre que sea posible.
Referencias:
grep
También se encontrará en funcionamiento (por ejemplo, ps cax | grep randomname
siempre devolverá 0 porque grep
hallazgos 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
.
ps cax | rev | cut -f1 -d' ' | rev
mostrará solo la columna de nombre, para facilitar el análisis.
ps cax
puede que no muestre el nombre del comando por completo. Por ejemplo, imprime "chrome-browser" en lugar de "chromium-browser".
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.
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 ps
comando 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 ps
debe 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.
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.
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 bash
y una instancia de remmina
ejecución):
$ pidof bash remmina
6148 6147 6144 5603 21598
En otros Unices, pgrep
o una combinación de ps
y grep
logrará lo mismo, como otros han señalado con razón.
pidof httpd
funciona bien en Red Hat 5. Pero en mi Red Hat 4, pidof
no está presente :-(
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:
PATH=...
]ps
. Para evitar el segundo grep
sugiero:ps aux | grep [h]ttpd
grep
.
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
ps cax
elimina la necesidad de usar grep -v
. Así, por ejemplo, puede utilizar: ps cax | grep java > /dev/null || echo "Java not running"
.
Solo una pequeña adición: si agrega la -c
bandera a ps, no necesita eliminar la línea que contiene el proceso grep con grep -v
posterioridad. Es decir
ps acux | grep cron
es toda la escritura que necesitará en un sistema bsd-ish (esto incluye MacOSX). Puede dejar de -u
lado si necesita menos información.
En un sistema donde la genética del ps
comando 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.
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"
Lo uso pgrep -l httpd
pero no estoy seguro de que esté presente en cualquier plataforma ...
¿Quién puede confirmar en OSX?
pidof
por favor? OK lo hiciste. Gracias. Así que deberíamos encontrar algo más que funcione en OSX ... Su básico ps|grep
puede ser la solución única ;-)
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 $PID
instrucción.
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:
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 gwak
como awk
alternativa 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"
Aquí está mi versión. caracteristicas:
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
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 .
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 ps
opciones 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
)
$ 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í.