¿Cómo escribo un script bash para reiniciar un proceso si muere?

Resuelto Tom asked hace 15 años • 12 respuestas

Tengo un script en Python que verificará una cola y realizará una acción en cada elemento:

# checkqueue.py
while True:
  check_queue()
  do_something()

¿Cómo escribo un script bash que comprobará si se está ejecutando y, si no, lo iniciará? Aproximadamente el siguiente pseudocódigo (¿o tal vez debería hacer algo como ps | grep?):

# keepalivescript.sh
if processidfile exists:
  if processid is running:
     exit, all ok

run checkqueue.py
write processid to processidfile

Lo llamaré desde un crontab:

# crontab
*/5 * * * * /path/to/keepalivescript.sh
Tom avatar Mar 30 '09 18:03 Tom
Aceptado

Evite archivos PID, crons o cualquier otra cosa que intente evaluar procesos que no sean sus hijos.

Hay una muy buena razón por la cual en UNIX SÓLO puedes atender a tus hijos. Cualquier método (ps análisis, pgrep, almacenamiento de un PID, ...) que intente solucionarlo es defectuoso y tiene grandes agujeros. Solo di no .

En su lugar, necesita que el proceso que monitorea su proceso sea el padre del proceso. ¿Qué quiere decir esto? Significa que solo el proceso que inicia su proceso puede esperar de manera confiable a que finalice. En bash, esto es absolutamente trivial.

until myserver; do
    echo "Server 'myserver' crashed with exit code $?.  Respawning.." >&2
    sleep 1
done

O para poder detenerlo:

trap 'kill $(jobs -p)' EXIT; until myserver & wait; do
    echo "ldap proxy crashed with exit code $?. Respawning.." >&2
    sleep 1
done

El fragmento de código bash anterior se ejecuta myserveren un untilbucle. La primera línea comienza myservery espera a que termine. Cuando finaliza, untilcomprueba su estado de salida. Si el estado de salida es 0, significa que finalizó correctamente (lo que significa que le pidió que se cerrara de alguna manera y lo hizo con éxito). En ese caso, no queremos reiniciarlo (¡solo le pedimos que se apague!). Si el estado de salida no 0 es , untilse ejecutará el cuerpo del bucle, que emite un mensaje de error en STDERR y reinicia el bucle (de vuelta a la línea 1) después de 1 segundo .

¿Por qué esperamos un segundo? Porque si algo anda mal con la secuencia de inicio myservery falla inmediatamente, tendrás un ciclo muy intensivo de reinicios y fallas constantes en tus manos. Esto le sleep 1quita la tensión a eso.

Ahora todo lo que necesita hacer es iniciar este script bash (probablemente de forma asincrónica), y lo monitoreará myservery reiniciará según sea necesario. Si desea iniciar el monitor al arrancar (haciendo que el servidor "sobreviva" los reinicios), puede programarlo en el cron(1) de su usuario con una @rebootregla. Abra sus reglas cron con crontab:

crontab -e

Luego agregue una regla para iniciar su secuencia de comandos de monitor:

@reboot /usr/local/bin/myservermonitor

Alternativamente; mire inittab(5) y /etc/inittab. Puede agregar una línea allí para myservercomenzar en un cierto nivel de inicio y reaparecer automáticamente.


Editar.

Permítanme agregar información sobre por qué no usar archivos PID. Si bien son muy populares; también tienen muchos defectos y no hay ninguna razón por la que no lo hagas de la manera correcta.

Considera esto:

  1. Reciclaje de PID (eliminando el proceso incorrecto):

    • /etc/init.d/foo start: iniciar foo, escribir fooel PID en/var/run/foo.pid
    • Un rato después: foomuere de alguna manera.
    • Un tiempo después: cualquier proceso aleatorio que se inicie (llámelo bar) toma un PID aleatorio, imagínese que toma fooel PID anterior.
    • Te das cuenta foode que se ha ido: /etc/init.d/foo/restartlee /var/run/foo.pid, comprueba si todavía está vivo, lo encuentra bar, cree que está foo, lo mata, comienza una nueva foo.
  2. Los archivos PID se vuelven obsoletos. Necesita una lógica demasiado complicada (o debería decir, no trivial) para comprobar si el archivo PID está obsoleto y si dicha lógica vuelve a ser vulnerable a 1..

  3. ¿Qué pasa si ni siquiera tienes acceso de escritura o estás en un entorno de sólo lectura?

  4. Es una complicación excesiva e inútil; Vea lo simple que es mi ejemplo anterior. No hay necesidad de complicar eso, en absoluto.

Ver también: ¿ Siguen siendo defectuosos los archivos PID cuando se hacen "bien"?

Por cierto; ¡Incluso peor que los archivos PID es el análisis ps! Nunca hagas esto.

  1. psEs muy poco portátil. Si bien lo encuentra en casi todos los sistemas UNIX; sus argumentos varían mucho si desea una salida no estándar. ¡Y la salida estándar es SÓLO para consumo humano, no para análisis mediante script!
  2. El análisis psconduce a MUCHOS falsos positivos. Tome el ps aux | grep PIDejemplo y ahora imagine a alguien iniciando un proceso con un número en algún lugar como argumento que resulta ser el mismo que el PID con el que miró su demonio. Imagina a dos personas iniciando una sesión X y tú buscando que X elimine la tuya. Es todo tipo de cosas malas.

Si no desea gestionar el proceso usted mismo; Existen algunos sistemas perfectamente buenos que actuarán como monitores de sus procesos. Mire runit , por ejemplo.

lhunath avatar Mar 30 '2009 12:03 lhunath

Eche un vistazo a monit ( http://mmonit.com/monit/ ). Maneja el inicio, la parada y el reinicio de su script y puede realizar comprobaciones de estado y reinicios si es necesario.

O haz un script simple:

while true
do
/your/script
sleep 1
done
Bernd avatar Mar 30 '2009 12:03 Bernd