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
*/30
el especificador de minutos , eso significa cada minuto pero con un paso de 30 (en otras palabras, cada media hora). Comocron
no 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
cron
trabajos realmente se ejecutan cada minuto, pero el último esperará medio minuto antes de ejecutar la "carne" del trabajo/path/to/executable
.Para otras
cron
opciones (no basadas), vea las otras respuestas aquí, particularmente las que mencionanfcron
ysystemd
. Probablemente sean preferibles suponiendo que su sistema tenga la capacidad de usarlos (como instalarfcron
o tener una distribuciónsystemd
dentro).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 30
pero para iniciarlo en segundo plano antes de que se ejecute su carga útil. Luego, una vez finalizada la carga útil, solo esperesleep
a que termine el fondo .Si la carga útil tarda
n
segundos (donden <= 30
), la espera después de la carga útil será30 - n
segundos. 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
cron
trabajo (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
x
segundo 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 $remainingTime
donde 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
sleep
requieren 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/user
para una configuración específica del usuario), debe habilitar el temporizador (no el servicio) ejecutandosystemctl enable --now helloworld.timer
(el--now
indicador 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. El1ms
ejemplo 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
OnBootSec
yOnUnitActiveSec
los campos y en su lugar establecer unaOnCalendar
regla 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.timer
unidad inicia lahelloworld.service
unidad porque tienen el mismo nombre (menos el sufijo del tipo de unidad). Este es el valor predeterminado, pero puede anularlo configurando elUnit
campo para la[Timer]
sección.Se pueden encontrar más detalles sangrientos en:
man systemd.timer
man systemd.time
man systemd.service
man system.exec
fuente
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.sh
fuente
Usar reloj:
fuente
$ watch --interval .10 php some_file.php
? owatch
solo funciona con archivos .sh?--interval .30
lo que no se ejecutará dos veces por minuto. Es decirwatch -n 2 "sleep 1 && date +%s"
, se incrementará cada 3s.watch
se diseñó para uso de terminal, por lo que, si bien puede funcionar sin un terminal (ejecutar connohup
luego 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 5
comando 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
nohup
como 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.sh
tarda 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_30s
ejecutará 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_COMMANDS
aYOUR_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 -c
parte (incluidas las comillas de argumento), el script solo se ejecuta cada minuto, ignorando la iteración (en mi casoX=12
yY=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 -e
y 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
60
debería ser un30
, es posible que desee mover esowget
dentro de laif
declaració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.