Tengo un cronjob que ejecuta PHP en un archivo cron.php de wordpress. Se utiliza principalmente para programar publicaciones y creo que puede actualizar el caché.
Ejecuto el trabajo cron cada minuto. Revisé el ps con frecuencia y veo DOS instancias de PHP ejecutando cron.php. Ahora bien, esto es innecesario porque ejecutar una instancia hará todo lo necesario. Tengo otro trabajo que verifica la RAM y, a veces, dos instancias la desconectan (espero que haya una gran cantidad de RAM disponible en todo momento, puedo reducirla pero no quiero). No creo que un trabajo pueda llevar más de un minuto (aunque puede que así sea).
¿Cómo ejecuto un trabajo pero no si el proceso ya existe? No creo que el código PHP en sí pueda verificarse a menos que se conecte/use la base de datos. ¿Existe algún comando cron que pueda usar? No quiero matar una instancia si es >1 minuto. Simplemente no generar otros nuevos.
Respuesta1
Aquí hay una solución simple de script bash; probablemente puedas hacer lo mismo en el script cron.php. De hecho, busca procesos que se ejecuten demasiado tiempo; para un sistema automatizado, probablemente sea una buena idea.
#!/bin/bash
# Exit if process is already running
if test -e /tmp/wordpress-job.pid; then
# Check if the pid that was stored in /tmp/wordpress-job.pid does exist
if ps ax -o pid= | grep $(cat /tmp/wordpress-job.pid ) &> /dev/null; then
exit 0
fi
fi
# Create the file that marks this process as running
echo $$ > /tmp/wordpress-job.pid
# Some extra security check to prevent the pid file
# to survive.
trap "rm -f /tmp/wordpress-job.pid" EXIT TERM INT HUP
# Start the long-running process in the background
sleep 3600 & # long-running process
# Sleep some time before trying to kill that process
sleep 300
# Kill job if it takes longer than it should
kill %1
# Delete the file that marks this process as running
rm -f /tmp/wordpress-job.pid
Debe reemplazar "sleep 3600" con su línea de comando php y cambiar el 300 a continuación al tiempo máximo que se le debe permitir ejecutar su script.
Respuesta2
Haga que su entrada crontab ejecute esto:
if mv /var/run/my-php-job.pending /var/run/my-php-job.running 2>/dev/null; then
echo $$ >|/var/run/my-php-job.running # optional
… # run the job
: >|/var/run/my-php-job.running # optional
mv /var/run/my-php-job.running /var/run/my-php-job.pending
fi
Pon esto en una @reboot
entrada de crontab:
rm -f /var/run/my-php-job.running
touch /var/run/my-php-job.pending
El nombre del archivo sirve como bloqueo. Mientras es así .running
, hay un trabajo en ejecución y el siguiente trabajo no se inicia. Cuando es .pending
, el trabajo en ejecución comienza y cambia a .running
.
Si incluye las líneas opcionales, el ID del proceso del shell se escribirá en el .running
archivo, con fines de investigación si un trabajo se atasca. Un archivo de registro haría que esto fuera mayoritariamente redundante.
Si el shell que ejecuta el trabajo falla (lo cual es poco probable y solo existe el riesgo de que suceda si alguien lo elimina deliberadamente o si tiene poca memoria, el archivo de bloqueo se atascará en .running
. (Si el trabajo en sí falla, no hay problema). detectar la muerte repentina de un guión anterior, pero es mucho más difícil.
Respuesta3
Existen utilidades especiales para evitar ejecuciones paralelas: Flock en util-linux, lockf en sistemas BSD, shlock en NetBSD y con paquetes INN y cnews.
En el caso más probable (Linux), llame a algo similar a:
flock -w 60 /somedir/lockfile cron.php
Las recetas en otras respuestas son alternativas de rebaños de cosecha propia y son útiles solo en caso de ausencia de dicha herramienta.
OTOH puede lidiar con dicho bloqueo en su programa directamente, pero debe repetir todos los detalles cuidadosamente; de lo contrario, puede crear una condición de carrera.