Tengo un script de 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 verificará si se está ejecutando y, si no, inícielo? Aproximadamente el siguiente pseudocódigo (¿o tal vez debería hacer algo así ps | grep
?):
# keepalivescript.sh
if processidfile exists:
if processid is running:
exit, all ok
run checkqueue.py
write processid to processidfile
Llamaré eso desde un crontab:
# crontab
*/5 * * * * /path/to/keepalivescript.sh
Respuestas:
Evite los 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, SOLO puede esperar a sus hijos. Cualquier método (análisis ps, pgrep, almacenamiento de un PID, ...) que intente solucionarlo es defectuoso y tiene agujeros enormes. Solo di que no .
En su lugar, necesita que el proceso que supervisa su proceso sea el padre del proceso. ¿Qué significa esto? Significa que solo el proceso que inicia su proceso puede esperar confiablemente a que termine. En bash, esto es absolutamente trivial.
La parte anterior del código bash se ejecuta
myserver
en ununtil
bucle. La primera línea comienzamyserver
y espera a que termine. Cuando termina,until
verifica su estado de salida. Si el estado de salida es0
, significa que terminó con gracia (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 es0
,until
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 está mal con la secuencia de inicio
myserver
y se bloquea de inmediato, tendrá un ciclo muy intenso de reinicio constante y bloqueo en sus manos. Elsleep 1
quita la tensión de eso.Ahora todo lo que necesita hacer es iniciar este script bash (probablemente de forma asincrónica), y lo monitoreará
myserver
y reiniciará según sea necesario. Si desea iniciar el monitor en el arranque (haciendo que el servidor "sobreviva" los reinicios), puede programarlo en el cron de su usuario (1) con una@reboot
regla. Abra sus reglas cron concrontab
:Luego agregue una regla para iniciar su script de monitor:
Alternativamente; mira inittab (5) y / etc / inittab. Puede agregar una línea allí para
myserver
comenzar 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 son muy defectuosos y no hay razón para que no lo hagas de la manera correcta.
Considera esto:
Reciclaje de PID (matar el proceso incorrecto):
/etc/init.d/foo start
: iniciofoo
, escribafoo
el PID en/var/run/foo.pid
foo
muere de alguna manera.bar
) toma un PID aleatorio, imagínelo tomandofoo
el PID anterior.foo
de que se ha ido:/etc/init.d/foo/restart
lee/var/run/foo.pid
, verifica si todavía está vivo, lo encuentrabar
, piensa que lofoo
mata, comienza un nuevofoo
.Los archivos PID quedan obsoletos. Necesita una lógica demasiado complicada (o debería decir, no trivial) para verificar si el archivo PID está obsoleto y si dicha lógica es nuevamente vulnerable
1.
.¿Qué sucede si ni siquiera tiene acceso de escritura o está en un entorno de solo lectura?
Es una sobrecomplicación sin sentido; vea cuán simple es mi ejemplo anterior. No hay necesidad de complicar eso, en absoluto.
Ver también: ¿Los archivos PID todavía tienen fallas cuando lo hacen 'bien'?
Por cierto; incluso peor que los archivos PID está analizando
ps
! Nunca hagas esto.ps
Es muy inportable. 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 SOLO para consumo humano, no para análisis con secuencias de comandos!ps
conduce a MUCHOS falsos positivos. ¡Tome elps aux | grep PID
ejemplo, y ahora imagine que alguien comienza un proceso con un número en algún lugar como argumento que resulta ser el mismo que el PID con el que miró a su demonio! Imagina a dos personas que comienzan una sesión X y estás buscando X para matar a la tuya. Es todo tipo de cosas malas.Si no desea administrar el proceso usted mismo; Existen algunos sistemas perfectamente buenos que actuarán como monitor de sus procesos. Mira en runit , por ejemplo.
fuente
while true; do myprocess; done
pero tenga en cuenta que ahora no hay forma de detener el proceso.trap 'kill $(jobs -p)' EXIT; until myserver & wait; do sleep 1; done
Echa un vistazo a monit ( http://mmonit.com/monit/ ). Maneja el inicio, la detención y el reinicio de su secuencia de comandos y puede realizar comprobaciones de estado y reinicios si es necesario.
O haz un script simple:
fuente
La forma más fácil de hacerlo es usar flock en el archivo. En el script Python que harías
En shell puedes probar si se está ejecutando:
Pero, por supuesto, no tiene que probar, porque si ya se está ejecutando y lo reinicia, saldrá con
'other instance already running'
Cuando el proceso muere, todos sus descriptores de archivo se cierran y todos los bloqueos se eliminan automáticamente.
fuente
flock
... de hecho, la página del manual demuestra explícitamente cómo.exec {lock_fd}>/tmp/script.lock; flock -x "$lock_fd"
es el bash equivalente a su Python, y deja el bloqueo retenido (por lo tanto, si luego ejecuta un proceso, el bloqueo permanecerá retenido hasta que el proceso salga).flock
es la forma correcta, pero sus scripts están equivocados. El único comando que debe configurar en crontab es:flock -n /tmp/script.lock -c '/path/to/my/script.py'
Debe usar monit, una herramienta estándar de Unix que puede monitorear diferentes cosas en el sistema y reaccionar en consecuencia.
De los documentos: http://mmonit.com/monit/documentation/monit.html#pid_testing
También puede configurar monit para que le envíe un correo electrónico cuando reinicie.
fuente
fuente
ps ax|grep ...
. Puede instalarlo o escribir una función para eso: function psgrep () {ps ax | grep -v grep | grep -q "$ 1"}No estoy seguro de cuán portátil es en todos los sistemas operativos, pero puede verificar si su sistema contiene el comando 'run-one', es decir, "man run-one". Específicamente, este conjunto de comandos incluye 'run-one-constantemente', que parece ser exactamente lo que se necesita.
Desde la página del manual:
Nota: obviamente, esto podría llamarse desde su script, pero también elimina la necesidad de tener un script.
fuente
He utilizado el siguiente script con gran éxito en numerosos servidores:
notas:
$INSTALLATION
contiene suficiente de la ruta del proceso que es totalmente inequívocaEste script se usa para cerrar una instancia en ejecución de tomcat, que quiero cerrar (y esperar) en la línea de comandos, por lo que iniciarlo como un proceso secundario simplemente no es una opción para mí.
fuente
grep | awk
sigue siendo un antipatrón : deseaawk "/$INSTALLATION/ { print \$1 }"
combinar lo inútilgrep
en el script Awk, que puede encontrar líneas por expresión regular en sí muy bien, muchas gracias.Lo uso para mi proceso npm
fuente