linux - reiniciar - Ejecute el trabajo cron solo si no se está ejecutando
instalar crontab ubuntu (15)
Así que estoy tratando de configurar un trabajo cron como una especie de perro guardián para un daemon que he creado. Si el daemon se equivoca y falla, quiero que el trabajo cron lo reinicie periódicamente ... No estoy seguro de qué tan posible es esto, pero leí un par de tutoriales cron y no pude encontrar nada que hiciera lo que Estoy buscando ...
My daemon se inicia desde un script de shell, así que solo estoy buscando una manera de ejecutar un trabajo cron SOLO si la ejecución anterior de ese trabajo aún no se está ejecutando.
Encontré esta publicación , que proporcionó una solución para lo que estoy tratando de hacer usando archivos de bloqueo, no estoy seguro de si hay una mejor manera de hacerlo ...
Gracias por tu ayuda.
Como otros han declarado, escribir y verificar un archivo PID es una buena solución. Aquí está mi implementación de bash:
#!/bin/bash
mkdir -p "$HOME/tmp"
PIDFILE="$HOME/tmp/myprogram.pid"
if [ -e "${PIDFILE}" ] && (ps -u $(whoami) -opid= |
grep -P "^/s*$(cat ${PIDFILE})$" &> /dev/null); then
echo "Already running."
exit 99
fi
/path/to/myprogram > $HOME/tmp/myprogram.log &
echo $! > "${PIDFILE}"
chmod 644 "${PIDFILE}"
Como seguimiento de la respuesta de Earlz, necesita un script de envoltura que cree un archivo $ PID.running cuando se inicie, y elimínelo cuando termine. El script de contenedor llama al script que desea ejecutar. El contenedor es necesario en caso de que la secuencia de comandos de destino falle o los errores salgan, el archivo pid se elimina.
Con lockrun
no necesita escribir un script de contenedor para su tarea cron. http://www.unixwiz.net/tools/lockrun.html
Considere usar pgrep (si está disponible) en lugar de ps por grep si va a seguir esa ruta. Aunque, personalmente, obtuve mucho kilometraje de los guiones del formulario
while(1){
call script_that_must_run
sleep 5
}
Aunque esto puede fallar y los trabajos de cron son a menudo la mejor manera para cosas esenciales. Solo otra alternativa.
Es sorprendente que nadie haya mencionado sobre el run-one . He resuelto mi problema con esto.
apt-get install run-one
luego agrega run-one
antes de tu script crontab
*/20 * * * * * run-one python /script/to/run/awesome.py
Mira this respuesta askubuntu SE. Puede encontrar un enlace a una información detallada allí también.
Hago esto para un programa de cola de impresión que escribí, es solo un script de shell:
#!/bin/sh
if ps -ef | grep -v grep | grep doctype.php ; then
exit 0
else
/home/user/bin/doctype.php >> /home/user/bin/spooler.log &
#mailing program
/home/user/bin/simplemail.php "Print spooler was not running... Restarted."
exit 0
fi
Corre cada dos minutos y es bastante efectivo. Lo tengo por correo electrónico con información especial si por alguna razón el proceso no se está ejecutando.
La forma en que lo estoy haciendo cuando estoy ejecutando scripts php es:
El crontab:
* * * * * php /path/to/php/script.php &
El código php:
<?php
if (shell_exec(''ps aux | grep '' . __FILE__ . '' | wc -l'') > 1) {
exit(''already running...'');
}
// do stuff
Este comando está buscando en la lista de procesos del sistema para el nombre de archivo php actual, si existe, el contador de líneas (wc -l) será mayor que uno porque el comando de búsqueda contiene el nombre del archivo
así que si ejecutas php crons agrega el código anterior al inicio de tu código php y se ejecutará solo una vez.
No intentes hacerlo a través de cron. Haga que cron ejecute un script sin importar qué, y luego haga que el script decida si el programa se está ejecutando e inícielo si es necesario (tenga en cuenta que puede usar Ruby o Python o su lenguaje de scripting favorito para hacer esto)
Simple PHP personalizado es suficiente para lograrlo. No hay necesidad de confundir con el script de shell.
supongamos que quieres ejecutar php /home/mypath/example.php si no se está ejecutando
A continuación, utilice la siguiente secuencia de comandos personalizada de PHP para hacer el mismo trabajo.
crear siguiente /home/mypath/forever.php
<?php
$cmd = $argv[1];
$grep = "ps -ef | grep ''".$cmd."''";
exec($grep,$out);
if(count($out)<5){
$cmd .= '' > /dev/null 2>/dev/null &'';
exec($cmd,$out);
print_r($out);
}
?>
Luego en tu cron agrega lo siguiente
* * * * * php /home/mypath/forever.php ''php /home/mypath/example.php''
Sugeriría lo siguiente como una mejora a la respuesta de rsanden (lo publicaría como un comentario, pero no tengo suficiente reputación ...):
#!/usr/bin/env bash
PIDFILE="$HOME/tmp/myprogram.pid"
if [ -e "${PIDFILE}" ] && (ps -p $(cat ${PIDFILE}) > /dev/null); then
echo "Already running."
exit 99
fi
/path/to/myprogram
Esto evita posibles coincidencias falsas (y la sobrecarga de grepping), y suprime la salida y se basa únicamente en el estado de salida de ps.
También puede hacerlo como una línea directamente en su crontab:
* * * * * [ `ps -ef|grep -v grep|grep <command>` -eq 0 ] && <command>
Usa flock
Es nuevo. Es mejor.
Ahora no tiene que escribir el código usted mismo. Consulte más motivos aquí: https://serverfault.com/a/82863
/usr/bin/flock -n /tmp/my.lockfile /usr/local/bin/my_script
Este nunca me falló:
one.sh :
LFILE=/tmp/one-`echo "$@" | md5sum | cut -d/ -f1`.pid
if [ -e ${LFILE} ] && kill -0 `cat ${LFILE}`; then
exit
fi
trap "rm -f ${LFILE}; exit" INT TERM EXIT
echo $$ > ${LFILE}
$@
rm -f ${LFILE}
trabajo de cron :
* * * * * /path/to/one.sh <command>
# one instance only (works unless your cmd has ''grep'' in it)
ALREADY_RUNNING_EXIT_STATUS=0
bn=`basename $0`
proc=`ps -ef | grep -v grep | grep "$bn" | grep -v " $$ "`
[ $? -eq 0 ] && {
pid=`echo $proc | awk ''{print $2}''`
echo "$bn already running with pid $pid"
exit $ALREADY_RUNNING_EXIT_STATUS
}