script - Comando Linux/Unix para determinar si el proceso se está ejecutando
scripts bash ejemplos (13)
Necesito un comando shell / bash independiente de la plataforma (Linux / Unix | OSX) que determinará si se está ejecutando un proceso específico. ej. mysqld
, httpd
... ¿Cuál es la forma / comando más simple para hacer esto?
Debe conocer el PID de su proceso.
Cuando lo ejecute, su PID se registrará en $!
variable. Guarde este PID en un archivo.
Luego deberá verificar si este PID corresponde a un proceso en ejecución. Aquí hay una secuencia de comandos esqueleto completa:
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 answer de peterh
. El truco para saber si un PID determinado se está ejecutando es en la instrucción ps -o pid= -p $PID
.
¡DEBERÍAS saber 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á destinada a fallar tarde o temprano. ¿Qué pasa si tienes dos mysqld corriendo? Olvida ese enfoque. PUEDE hacerlo bien temporalmente y PUEDE funcionar durante un año o dos, pero luego sucede algo en lo que no ha pensado.
Solo el id de proceso (pid) es verdaderamente único.
Siempre almacene el pid cuando ejecute algo en el fondo. ¡En Bash esto se puede hacer con $!
Bash variable. Te ahorrarás TANTO problema al hacerlo.
Cómo determinar si el proceso se está ejecutando (por pid)
Entonces ahora la pregunta es cómo saber si un pid se está ejecutando.
Simplemente hazlo:
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 hemos dado un encabezado de título vacío (el material 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 comando ps
anterior. Debería ser cero si el proceso se está ejecutando y distinto de cero si no es así. La especificación POSIX dice que ps
debe salir> 0 si ha ocurrido un error pero no está claro para mí qué constituye ''un error''. Por lo tanto, no estoy usando esa estrategia personalmente, aunque estoy bastante seguro de que funcionará en todas las plataformas Unix / Linux.
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
Combinando varias 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 guion:
kill -0 $(cat pid_stored) 2> /dev/null || echo "Mysql ain''t runnin'' message/actions"
En la mayoría de las distribuciones de Linux, puede usar pidof
(8).
Imprimirá los id. De proceso de todas las instancias en ejecución de procesos especificados, o nada si no hay instancias ejecutándose.
Por ejemplo, en mi sistema (tengo cuatro instancias de bash
y una instancia de remmina
ejecutándose):
$ pidof bash remmina
6148 6147 6144 5603 21598
En otras Unices, pgrep
o una combinación de ps
y grep
lograrán lo mismo, como otros han señalado con razón.
Este enfoque se puede usar en caso de que los comandos ''ps'', ''pidof'' y resto 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:
- -m1 - detener el proceso en el primer partido
- "mysqld $ | httpd $" - grep coincidirá con las líneas que terminaron en mysqld O httpd
- / proc / [0-9] * - bash coincidirá con la línea que comenzó con cualquier número
- corte: simplemente divida la salida por el delimitador ''/'' y extraiga el campo 3
Esto debería funcionar en la mayoría de los sabores de Unix, BSD y Linux:
PATH=/usr/ucb:${PATH} ps aux | grep httpd | grep -v grep
Probado en:
- SunOS 5.10 [De ahí la
PATH=...
] - Linux 2.6.32 (CentOS)
- Linux 3.0.0 (Ubuntu)
- Darwin 11.2.0
- FreeBSD 9.0-STABLE
- Versión 4 de Red Hat Enterprise Linux ES
- Versión 5 del servidor Red Hat Enterprise Linux
Esto imprime la cantidad de procesos cuyo nombre base es "cromo-navegador":
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 esto imprime "0", el proceso no se está ejecutando. El comando asume que la ruta del proceso no contiene espacio de última hora. No he probado esto con procesos suspendidos o procesos zombie.
Probado usando gwak
como la alternativa de awk
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"
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, entonces también puede poner más ''grep cmd_arg1'' después de ''grep $ command'' para filtrar otros posibles procesos que no le interesan.
Ejemplo: muéstrame si hay algún proceso de 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
La siguiente función de shell, que solo se basa en los comandos y opciones estándar de 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 ahogará cuando pase el dudoso nombre de comando "0" y tampoco identificará procesos que tengan un espacio incrustado en sus nombres.
Tenga en cuenta también que la solución más votada y aceptada exige opciones ps
no portátiles y, de forma gratuita, utiliza un shell que, a pesar de su popularidad, no está garantizado que esté presente en todas las máquinas Unix / Linux ( bash
)
Si bien pidof
y pgrep
son excelentes herramientas para determinar qué se está ejecutando, lamentablemente no están disponibles en algunos sistemas operativos. Un fallo seguro definitivo sería usar lo siguiente: ps cax | grep command
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 obtener fácilmente los siguientes:
ps cax | grep httpd | grep -o ''^[ ]*[0-9]*''
Cuyo resultado es el mismo 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:
echo ps cax | grep aasdfasdf | grep -o ''^[ ]*[0-9]*''
Este enfoque es adecuado para escribir una simple prueba de cadena vacía, y luego 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
Puedes 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 de ps ax
que significa que, como se ve en la salida de Linux, no se trata simplemente de hacer coincidir los procesos, sino también los argumentos pasados a ese programa. Recomiendo ser lo más específico posible al usar este método (por ejemplo, ./running "mysql"
también coincidirá con los procesos de ''mysqld''). Recomiendo usar el which
comparar con un camino completo donde sea posible.
Referencias
Solo una pequeña adición: si agrega el -c
a ps, no necesita eliminar la línea que contiene el proceso grep -v
con grep -v
después. Es decir
ps acux | grep cron
es todo el tipeo que necesitarás en un sistema bsd-ish (esto incluye MacOSX). Puedes abandonar el -u
si necesitas menos información.
En un sistema donde la genética del comando ps
nativo apunta a SysV, usarías
ps -e |grep cron
o
ps -el |grep cron
para una lista que contiene más que solo pid y nombre del proceso. Por supuesto, puede seleccionar los campos específicos para imprimir utilizando la opción -o <field,field,...>
.
Yo uso pgrep -l httpd
pero no estoy seguro de que esté presente en ninguna plataforma ...
¿Quién puede confirmar en OSX?