Ok, entonces tengo un cron que necesito ejecutar cada 30 segundos.
Esto es lo que tengo:
*/30 * * * * /bin/bash -l -c 'cd /srv/last_song/releases/20120308133159 && script/rails runner -e production '\''Song.insert_latest'\'''
Se ejecuta, pero ¿se está ejecutando cada 30 minutos o 30 segundos?
Además, he estado leyendo que cron podría no ser la mejor herramienta para usar si lo ejecuto con tanta frecuencia. ¿Hay otra herramienta mejor que pueda usar o instalar en Ubuntu 11.04 que será una mejor opción? ¿Hay alguna manera de arreglar el cron anterior?
ubuntu
cron
scheduled-tasks
Matt Elhotiby
fuente
fuente

Respuestas:
Tienes
*/30el especificador de minutos , eso significa cada minuto pero con un paso de 30 (en otras palabras, cada media hora). Comocronno se reduce a resoluciones de menos de un minuto, deberá buscar otra forma.Una posibilidad, aunque es un poco un error (a) , es tener dos trabajos, uno compensado por 30 segundos:
Verá que agregué comentarios y los formateé para garantizar que sea fácil mantenerlos sincronizados.
Ambos
crontrabajos realmente se ejecutan cada minuto, pero el último esperará medio minuto antes de ejecutar la "carne" del trabajo/path/to/executable.Para otras
cronopciones (no basadas), vea las otras respuestas aquí, particularmente las que mencionanfcronysystemd. Probablemente sean preferibles suponiendo que su sistema tenga la capacidad de usarlos (como instalarfcrono tener una distribuciónsystemddentro).Si no desea usar la solución kludgy, puede usar una solución basada en bucles con una pequeña modificación. Todavía tendrá que administrar mantener su proceso ejecutándose de alguna forma, pero, una vez que esté ordenado, el siguiente script debería funcionar:
El truco consiste en utilizar un
sleep 30pero para iniciarlo en segundo plano antes de que se ejecute su carga útil. Luego, una vez finalizada la carga útil, solo esperesleepa que termine el fondo .Si la carga útil tarda
nsegundos (donden <= 30), la espera después de la carga útil será30 - nsegundos. Si demora más de 30 segundos, el siguiente ciclo se retrasará hasta que finalice la carga útil, pero ya no.Verá que tengo un código de depuración para comenzar en un límite de un minuto para hacer que la salida sea inicialmente más fácil de seguir. También aumento gradualmente el tiempo máximo de carga útil para que eventualmente vea que la carga útil excede el tiempo de ciclo de 30 segundos (se genera una línea en blanco adicional para que el efecto sea obvio).
Sigue una ejecución de muestra (donde los ciclos normalmente comienzan 30 segundos después del ciclo anterior):
Si desea evitar la solución kludgy, probablemente sea mejor. Aún necesitará un
crontrabajo (o equivalente) para detectar periódicamente si este script se está ejecutando y, si no, iniciarlo. Pero el guión mismo maneja el tiempo.(a) Algunos de mis compañeros de trabajo dirían que los kludges son mi especialidad :-)
fuente
No puedes Cron tiene una granularidad de 60 segundos.
fuente
&&lugar de( ; ).&&operador realiza un cortocircuito, por lo que el siguiente comando en la cadena no se ejecuta si el anterior falla.La granularidad de Cron está en minutos y no fue diseñada para despertarse cada
xsegundo para ejecutar algo. Ejecute su tarea repetitiva dentro de un bucle y debería hacer lo que necesita:fuente
while [ true ]te hará tener muchas instancias del mismo script, ya que cron comenzará una nueva cada minuto?sleep $remainingTimedonde el tiempo restante sea 30 menos el tiempo que tomó el trabajo (y limitarlo a cero si tardó> 30 segundos). Entonces se toma el tiempo antes y después del trabajo real, y calcula la diferencia.Si está ejecutando un sistema operativo Linux reciente con SystemD, puede usar la unidad de temporizador SystemD para ejecutar su secuencia de comandos en cualquier nivel de granularidad que desee (teóricamente hasta nanosegundos) y, si lo desea, reglas de inicio mucho más flexibles de lo que Cron alguna vez permitió . No se
sleeprequieren erroresSe necesita un poco más de configuración que una sola línea en un archivo cron, pero si necesita algo mejor que "Cada minuto", vale la pena el esfuerzo.
El modelo de temporizador SystemD es básicamente esto: los temporizadores son unidades que inician unidades de servicio cuando transcurre un temporizador .
Entonces, para cada script / comando que desee programar, debe tener una unidad de servicio y luego una unidad de temporizador adicional. Una sola unidad de temporizador puede incluir múltiples horarios, por lo que normalmente no necesitaría más de un temporizador y un servicio.
Aquí hay un ejemplo simple que registra "Hello World" cada 10 segundos:
/etc/systemd/system/helloworld.service:/etc/systemd/system/helloworld.timer:Después de configurar estas unidades (en
/etc/systemd/system, como se describió anteriormente, para una configuración de todo el sistema o~/.config/systemd/userpara una configuración específica del usuario), debe habilitar el temporizador (no el servicio) ejecutandosystemctl enable --now helloworld.timer(el--nowindicador también inicia el temporizador inmediatamente, de lo contrario, solo comenzará después del siguiente arranque o inicio de sesión del usuario).Los
[Timer]campos de sección utilizados aquí son los siguientes:OnBootSec- inicie el servicio tantos segundos después de cada arranque.OnUnitActiveSec- inicie el servicio varios segundos después de la última vez que se inició. Esto es lo que hace que el temporizador se repita y se comporte como un trabajo cron.AccuracySec- Establece la precisión del temporizador. Los temporizadores son tan precisos como este campo establece, y el valor predeterminado es 1 minuto (emula cron). La razón principal para no exigir la mejor precisión es mejorar el consumo de energía: si SystemD puede programar la próxima ejecución para que coincida con otros eventos, debe reactivar la CPU con menos frecuencia. El1msejemplo anterior no es ideal: generalmente establezco la precisión en1(1 segundo) en mis trabajos programados de menos de un minuto, pero eso significaría que si mira el registro que muestra los mensajes de "Hola Mundo", verá que a menudo es tarde por 1 segundo. Si está de acuerdo con eso, sugiero configurar la precisión en 1 segundo o más.Como habrás notado, este temporizador no imita a Cron tan bien, en el sentido de que el comando no comienza al comienzo de cada período de reloj de pared (es decir, no comienza en el décimo segundo del reloj, luego el 20 y así sucesivamente). En cambio, solo sucede cuando el temporizador transcurre. Si el sistema se inició a las 12:05:37, la próxima vez que se ejecute el comando será a las 12:05:47, luego a las 12:05:57, etc. Si está interesado en la precisión real del reloj de pared, puede desee reemplazar las
OnBootSecyOnUnitActiveSeclos campos y en su lugar establecer unaOnCalendarregla con el programa que desea (que por lo que yo entiendo, no puede ser más rápido que 1 segundo, usando el formato del calendario). El ejemplo anterior también se puede escribir como:Última nota: como probablemente haya adivinado, la
helloworld.timerunidad inicia lahelloworld.serviceunidad porque tienen el mismo nombre (menos el sufijo del tipo de unidad). Este es el valor predeterminado, pero puede anularlo configurando elUnitcampo para la[Timer]sección.Se pueden encontrar más detalles sangrientos en:
man systemd.timerman systemd.timeman systemd.serviceman system.execfuente
No necesita dos entradas cron, puede ponerlas en una con:
entonces en tu caso:
* * * * * /bin/bash -l -c "cd /srv/last_song/releases/20120308133159 && script/rails runner -e production '\''Song.insert_latest'\'' ; sleep 30 ; cd /srv/last_song/releases/20120308133159 && script/rails runner -e production '\''Song.insert_latest'\''"fuente
Puedes ver mi respuesta a esta pregunta similar
Básicamente, he incluido un script de bash llamado "runEvery.sh" que puede ejecutar con cron cada 1 minuto y pasar como argumentos el comando real que desea ejecutar y la frecuencia en segundos en que desea ejecutarlo.
algo como esto
* * * * * ~/bin/runEvery.sh 5 myScript.shfuente
Usar reloj:
fuente
$ watch --interval .10 php some_file.php? owatchsolo funciona con archivos .sh?--interval .30lo que no se ejecutará dos veces por minuto. Es decirwatch -n 2 "sleep 1 && date +%s", se incrementará cada 3s.watchse diseñó para uso de terminal, por lo que, si bien puede funcionar sin un terminal (ejecutar connohupluego cerrar sesión) o con un terminal falso (comoscreen), no tiene posibilidades para un comportamiento similar al cron, como recuperarse de una falla, reiniciar después del arranque, etc.El trabajo Cron no se puede utilizar para programar un trabajo en intervalos de segundos. es decir, no puede programar un trabajo cron para que se ejecute cada 5 segundos. La alternativa es escribir un script de shell que use un
sleep 5comando en él.Cree un script de shell cada 5- segundos.sh usando bash while loop como se muestra a continuación.
Ahora, ejecute este script de shell en segundo plano usando
nohupcomo se muestra a continuación. Esto seguirá ejecutando el script incluso después de cerrar sesión en su sesión. Esto ejecutará su script de shell backup.sh cada 5 segundos.fuente
backup.shtarda 1,5 segundos en ejecutarse, se ejecutará cada 6,5 segundos. Hay formas de evitar eso, por ejemplosleep $((5 - $(date +%s) % 5))Use fcron ( http://fcron.free.fr/ ): le brinda granularidad en segundos y mucho mejor y más funciones que cron (vixie-cron) y también estable. Solía hacer cosas estúpidas, como tener alrededor de 60 scripts PHP ejecutados en una máquina en configuraciones muy estúpidas, ¡y todavía hizo su trabajo!
fuente
en dir
/etc/cron.d/nuevo crea un archivo
excute_per_30sejecutará cron cada 30 segundos
fuente
Actualmente estoy usando el siguiente método. Funciona sin problemas.
Si desea ejecutar cada N segundos y luego X habrá 60 / N y Y habrá N .
Gracias.
fuente
YOUR_COMMANDSaYOUR_COMMANDS &, para que el comando se ejecute en segundo plano, de lo contrario, si el comando tarda más de una fracción de segundo, retrasará el próximo lanzamiento. Entonces, con X = 2 e Y = 30, si el comando tarda 10 segundos, se lanzará en el minuto y luego 40 segundos después, en lugar de 30. Kudus a @paxdiablo./bin/bash -cparte (incluidas las comillas de argumento), el script solo se ejecuta cada minuto, ignorando la iteración (en mi casoX=12yY=5).El trabajo de Crontab se puede usar para programar un trabajo en minutos / horas / días, pero no en segundos. La alternativa :
Cree un script para ejecutar cada 30 segundos:
Use
crontab -ey un crontab para ejecutar este script:fuente
Puede ejecutar ese script como servicio, reiniciar cada 30 segundos
Registrar un servicio
Pega el comando a continuación
Servicios de recarga
Habilitar el servicio
Inicia el servicio
Verifique el estado de su servicio
fuente
Gracias por todas las buenas respuestas. Para simplificar, me gustó la solución mixta, con el control en crontab y la división de tiempo en el script. Entonces, esto es lo que hice para ejecutar un script cada 20 segundos (tres veces por minuto). Línea Crontab:
Guión:
fuente
escribir un script de shell crear archivo .sh
nano cada 30 segundos.sh
y escribir guion
luego configure cron para este script crontab -e
(* * * * * /home/username/every30second.sh)este archivo cron call .sh cada 1 minuto y en el comando del archivo .sh se ejecuta 2 veces en 1 minuto
si desea ejecutar el script durante 5 segundos, reemplace 30 por 5 y cambie el bucle de esta manera:
For (( i=1; i <= 12; i++ ))cuando selecciona por cualquier segundo, calcule 60 / su segundo y escriba en el bucle For
fuente
Acabo de hacer una tarea similar y utilizo el siguiente enfoque:
Necesitaba tener un kill -3 periódico (para obtener el seguimiento de la pila de un programa) cada 30 segundos durante varias horas.
Esto está aquí para asegurarse de que no pierdo la ejecución de watch si pierdo el shell (problema de red, bloqueo de Windows, etc.)
fuente
Eche un vistazo a frecuente-cron : es antiguo pero muy estable y puede reducirlo a microsegundos. En este momento, lo único que diría contra esto es que todavía estoy tratando de resolver cómo instalarlo fuera de init.d pero como un servicio systemd nativo, pero ciertamente hasta Ubuntu 18 se está ejecutando solo bien todavía usando init.d (la distancia puede variar en las últimas versiones). Tiene la ventaja adicional (?) De garantizar que no generará otra instancia del script PHP a menos que se haya completado una anterior, lo que reduce los posibles problemas de pérdida de memoria.
fuente
Ejecutar en un ciclo de shell, ejemplo:
fuente
60debería ser un30, es posible que desee mover esowgetdentro de laifdeclaración, de lo contrario, se ejecuta cada segundo. En cualquier caso, no estoy seguro de cómo esto es mejor que un simplesleep 30. Si estuviera monitoreando el tiempo real de UNIX en lugar de su contador, marcaría la diferencia.