2008-11-18 26 views
68

Estoy tratando de asegurar que un script permanezca ejecutándose en un servidor de desarrollo. Coteja las estadísticas y proporciona un servicio web, por lo que se supone que persiste; sin embargo, algunas veces al día, se apaga por razones desconocidas. Cuando nos damos cuenta de que solo lo lanzamos de nuevo, pero es un dolor en la parte trasera y algunos usuarios no tienen permiso (o el know-how) para lanzarlo.Cómo asegurarme de que una aplicación siga ejecutándose en Linux

El programador en mí quiere pasar unas pocas horas para llegar al fondo del problema, pero la persona ocupada en mí piensa que debe haber una manera fácil de detectar si una aplicación no se está ejecutando, y ejecutarla de nuevo.

sé que podría ps cron-escritura a través de grep:

ps -A | grep appname 

Pero, de nuevo, eso es otra hora de mi vida desperdiciada en hacer algo que ya debe existir ... ¿No hay una pre aplicación hecha que puedo pasar un ejecutable (opcionalmente con argumentos) y que mantendrá un proceso ejecutándose indefinidamente?

En caso de que haya alguna diferencia, es Ubuntu.

+1

Depende de si las estadísticas se pierden cuando la secuencia de comandos no se está ejecutando, pero creo que el programador que es correcto - usted debe saber más acerca de por qué la secuencia de comandos no continúa indefinidamente. –

+0

Es más una utilidad de servicio a pedido que algo que constantemente está machacando números. Si se bloquea antes de guardar datos, no se pierde nada; simplemente completará el trabajo la próxima vez que se ejecute. – Oli

+0

Posible duplicado de [¿Cómo escribo un script bash para reiniciar un proceso si se muere?] (Http://stackoverflow.com/questions/696839/how-do-i-write-a-bash-script-to- restart-a-process-if-it-dies) – tripleee

Respuesta

33

Dado que está utilizando Ubuntu, puede interesarle Upstart, que ha reemplazado al tradicional sysV init.Una característica clave es que puede reiniciar un servicio si muere inesperadamente. Fedora se ha movido al advenedizo, y Debian está en fase experimental, por lo que puede valer la pena investigarlo.

Esto puede ser excesivo para esta situación, ya que un script cron tardará 2 minutos en implementarse.

#!/bin/bash 
if [[ ! `pidof -s yourapp` ]]; then 
    invoke-rc.d yourapp start 
fi 
+0

Debo señalar que la configuración de advenedizo para administrar su servicio y mantenerlo en ejecución es bastante simple (usted escribe un pequeño archivo de configuración). Esta solución es mucho más limpia, simple y mejor que cualquier otra supervisión "simple" basada en scripts cron/shell. – thor

+0

@thor - (tenga en cuenta que esto es de 2008, cuando advenedizo era nuevo y la documentación era más difícil). Estoy de acuerdo, el script cron "simple" fue solo para ilustrar que un script no necesita ser complejo para hacer el trabajo tampoco. – JimB

+0

Ya veo. He votado de todos modos su respuesta al colocar mi comentario – thor

39

Monit es perfecto para esto :)

Puede escribir archivos de configuración simples que cuentan Monit para ver, por ejemplo, un puerto TCP, un archivo PID, etc.

monit ejecutará un comando que usted especifica cuando el proceso que está monitoreando no está disponible/usando demasiada memoria/está conectando la CPU demasiado tiempo/etc. También aparecerá una alerta por correo electrónico que le informará qué sucedió y si podría hacer algo al respecto.

Lo usamos para mantener una carga de nuestros sitios web en ejecución al tiempo que nos da una advertencia temprana cuando algo va mal.

- Su empleado fiel, Monit

+0

"ladrando a los demonios"! Me gusta :) – Ken

+0

Parece impresionante. –

+14

¿Cómo mantienes a Monit corriendo? – JohnMudd

1

Es un trabajo para un DMD (Demonio de demonio). hay algunos alrededor; pero normalmente solo escribo un script que comprueba si el daemon se está ejecutando, y lo ejecuta si no, y lo pongo en cron para que se ejecute cada minuto.

1

en primer lugar, ¿cómo se inicia esta aplicación? ¿Se bifurca al fondo? ¿Se comenzó con nohup .. & etc.? Si es el último, comprueba por qué murió en nohup.out, si es el primero, compila el registro.

cuanto a su pregunta principal: usted podría cron, o ejecutar otro proceso en el fondo (no la mejor opción) y utilizar pidof en un bashscript, bastante fácil:

if [ `pidof -s app` -eq 0 ]; then 
    nohup app & 
fi 
7

Deja de correr en una loop- entonces cuando sale, se ejecuta de nuevo ... while (true) {ejecuta mi aplicación ...}

+2

Si el script se está muriendo por razones desconocidas, es probable que también lo haga, ¿no? – Gareth

+0

simple y efectivo – orip

+3

Im con Garath, si es el sistema que mata los procesos de larga ejecución, entonces el bucle sugerido, que comenzaría antes de la aplicación, sería eliminado primero. – ekerner

1

Puedes hacer que sea un servicio lanzado desde inittab (aunque algunos Linux han pasado a algo más nuevo en/etc /event.d). Estos sistemas integrados aseguran que su servicio siga funcionando sin escribir sus propios scripts o instalar algo nuevo.

1

Consulte 'nanny' al que se hace referencia en el Capítulo 9 (p197 o menos) de "Unix Hater's Handbook" (una de varias fuentes para el libro en PDF).

7

he utilizado desde cron "killall -0 ProgramName || /etc/init.d/programname empezar". matar será un error si el proceso no existe. Si existe, enviará una señal nula al proceso (que el kernel ignorará y no se molestará en transmitir).

Este idioma es fácil de recordar (en mi humilde opinión). En general, uso esto cuando todavía estoy tratando de descubrir por qué el servicio en sí está fallando. En mi humilde opinión, un programa no debería simplemente desaparecer inesperadamente :)

65

He utilizado un script simple con cron para asegurarme de que el programa se está ejecutando. Si no es así, entonces lo pondrá en marcha. Puede que esta no sea la solución perfecta que está buscando, pero es simple y funciona bastante bien.

#!/bin/bash 
#make-run.sh 
#make sure a process is always running. 

export DISPLAY=:0 #needed if you are running a simple gui app. 

process=YourProcessName 
makerun="/usr/bin/program" 

if ps ax | grep -v grep | grep $process > /dev/null 
then 
    exit 
else 
    $makerun & 
fi 

exit 

A continuación, agregue un trabajo cron cada minuto, o cada 5 minutos.

+5

+1 por simplicidad – Dooltaz

+2

Eso es genio. Sobrevivirá a un reinicio y nada que instalar. –

+0

Lo he usado yo mismo porque no requiere instalación de privilegios. – JohnMudd

1

Una manera agradable, fácil de hacer esto es como sigue:

  1. Escribe tu servidor a morir si no puede escuchar en el puerto que espera
  2. Establecer una tarea programada para tratar de poner en marcha el servidor cada minuto

Si no se está ejecutando, se iniciará y, si se está ejecutando, no funcionará. En cualquier caso, su servidor siempre estará activo.

0

Creo que una mejor solución es si prueba la función también. Por ejemplo, si tuvo que probar un apache, no es suficiente solo para probar, si existen procesos "apache" en el sistema.

Si desea probar si apache es correcto, intente descargar una página web simple y compruebe si su código exclusivo está en la salida.

Si no, apague el apache con -9 y luego reinicie. Y envíe un correo a la raíz (que es una dirección de correo reenviado a las raíces de la empresa/servidor/proyecto).

+1

Esto es cierto. Muchas de las soluciones de monitoreo sugeridas en otras respuestas sí proporcionan monitoreo de protocolo. – Oli

1

La herramienta supervise de daemontools sería mi preferencia - pero luego todo escribe Dan J Bernstein es mi preferencia :)

http://cr.yp.to/daemontools/supervise.html

Tienes que crear una estructura de directorios en particular para su script de inicio de la aplicación, pero es muy simple de usar.

0

Es aún más simple:

#!/bin/bash 

export DISPLAY=:0 

process=processname 
makerun="/usr/bin/processname" 

if ! pgrep $process > /dev/null 
then 
    $makerun & 
fi 

Hay que recordar, aunque para asegurarse de ProcessName es único.

13

Si está utilizando una distribución basada en sistema como Fedora y versiones recientes de Ubuntu, puede usar systemd's "Restart" capability para servicios.Se puede configurar como un servicio de sistema o como un servicio de usuario si necesita ser administrado y ejecutado como un usuario particular, lo cual es más probable en la situación particular de OP.

La opción Reiniciar takes one ofno, on-success, on-failure, on-abnormal, on-watchdog, on-abort o always.

Para ejecutarlo como usuario, sólo tiene que colocar un archivo como el siguiente en ~/.config/systemd/user/something.service:

[Unit] 
Description=Something 

[Service] 
ExecStart=/path/to/something 
Restart=on-failure 

[Install] 
WantedBy=graphical.target 

a continuación:

systemctl --user daemon-reload 
systemctl --user [status|start|stop|restart] something 

Sin raíz privilegio/modificación de los archivos de sistema necesarios, no hay trabajos de cron necesario, nada que instalar, flexible como el infierno (ver todas las opciones de servicio relacionadas en la documentación).

Consulte también https://wiki.archlinux.org/index.php/Systemd/User para obtener más información sobre el uso de la instancia del sistema por usuario.

2

No pude obtener Chris Wendt solución para trabajar por alguna razón, y era difícil de depurar. Este es más o menos el mismo, pero más sencillo de depurar, excluye bash de la coincidencia de patrones. Para depurar solo ejecuta: bash ./root/makerun-mysql.sh. En el siguiente ejemplo con mysql-server simplemente reemplace el valor de las variables para process y makerun para su proceso.

  • Crear un BASH-script como el siguiente (nano /root/makerun-mysql.sh):
#!/bin/bash 
process="mysql" 
makerun="/etc/init.d/mysql restart" 
if ps ax | grep -v grep | grep -v bash | grep --quiet $process 
then 
    printf "Process '%s' is running.\n" "$process" 
    exit 
else 
    printf "Starting process '%s' with command '%s'.\n" "$process" "$makerun" 
    $makerun 
fi 
exit 
  • Asegúrese de que sea ejecutable mediante la adición de permisos de archivo adecuados (es decir chmod 700 /root/makerun-mysql.sh)

  • A continuación, añadir esta a su crontab (crontab -e):

# Keep processes running every 5 minutes 
*/5 * * * * bash /root/makerun-mysql.sh 
+0

Preste atención, en comparación con la solución de Chris Wendt, el script no se inicia aquí como tarea de fondo. – Mason

Cuestiones relacionadas