una script respaldo respaldar rango para manualmente horas hora ejecutar con comando cada archivos sql queue cron

sql - respaldo - script cron para actuar como una cola O una cola para cron?



script backup linux (3)

Apuesto a que alguien ya ha resuelto esto y que estoy usando los términos de búsqueda incorrectos para que Google me diga la respuesta, pero esta es mi situación.

Tengo un script que quiero ejecutar, pero quiero que se ejecute solo cuando esté programado y solo uno a la vez. (no se puede ejecutar el script simultáneamente)

Ahora la parte más difícil es decir que tengo una tabla llamada "myhappyschedule" que tiene los datos que necesito y la hora programada. Esta tabla puede tener múltiples horarios programados, incluso al mismo tiempo, cada uno ejecutaría este script. Entonces, esencialmente, necesito una cola cada vez que el script se activa y todos deben esperar cada uno antes de que termine. (a veces, esto puede tomar solo un minuto para que el script se ejecute, a veces, durante muchos minutos)

Lo que estoy pensando hacer es hacer un script que compruebe myhappyschedule cada 5 minutos y reúna los que están programados, los pone en una cola donde otro script puede ejecutar cada ''trabajo'' u ocurrencia en la cola en orden. Que todo esto suena desordenado.

Para hacer esto más largo, debería decir que les estoy permitiendo a los usuarios programar cosas en myhappyschedule y no editar crontab.

¿Qué se puede hacer con esto? ¿Bloqueos de archivos y scripts que invocan scripts?


Puede usar el comando at (1) dentro de su script para programar su próxima ejecución. Antes de que finalice, puede verificar myhappyschedule para el próximo tiempo de ejecución. No necesitas cron en absoluto, realmente.


agregue una columna exec_status a myhappytable (quizás también time_started y time_finished , vea pseudocódigo)

ejecuta el siguiente script cron cada x minutos

pseudocódigo de script cron:

[create/check pid lock (optional, but see "A potential pitfall" below)] get number of rows from myhappytable where (exec_status == executing_now) if it is > 0, exit begin loop get one row from myhappytable where (exec_status == not_yet_run) and (scheduled_time <= now) order by scheduled_time asc if no such row, exit set row exec_status to executing_now (maybe set time_started to now) execute whatever command the row contains set row exec_status to completed (maybe also store the command output/return as well, set time_finished to now) end loop [delete pid lock file (complementary to the starting pid lock check)]

De esta forma, el script comprueba primero si ninguno de los comandos se está ejecutando, luego ejecuta el primer comando que aún no ejecuta, hasta que no haya más comandos para ejecutar en el momento dado. Además, puede ver qué comando se está ejecutando al consultar la base de datos.

Una posible trampa: si se cancela la secuencia de comandos cron, una tarea programada permanecerá en el estado de "ejecución_now". Para eso sirve el bloqueo pid al principio y al final: para ver si el script cron terminó correctamente. pseudocódigo de crear / verificar pidlock:

if exists pidlockfile then check if process id given in file exists if not exists then update myhappytable set exec_status = error_cronscript_died_while_executing_this where exec_status == executing_now delete pidlockfile else (previous instance still running) exit endif endif create pidlockfile containing cron script process id


Me encontré con esta pregunta mientras buscaba una solución al problema de las colas. Para beneficio de cualquier otra persona que busque aquí, está mi solución.

Combine esto con un cron que inicia trabajos tal como están programados (incluso si están programados para ejecutarse al mismo tiempo) y eso resuelve el problema que usted describió también.

Problema

  • Como máximo, se debe ejecutar una instancia del script.
  • Queremos seguir las solicitudes para procesarlas lo más rápido posible.

es decir. Necesitamos una tubería para el guión.

Solución:

Crea una canalización a cualquier script. Hecho usando un pequeño script bash (más abajo).

El script se puede llamar como
./pipeline "<any command and arguments go here>"

Ejemplo:

./pipeline sleep 10 & ./pipeline shabugabu & ./pipeline single_instance_script some arguments & ./pipeline single_instance_script some other_argumnts & ./pipeline "single_instance_script some yet_other_arguments > output.txt" & ..etc

La secuencia de comandos crea una nueva tubería con nombre para cada comando. Por lo tanto, lo anterior creará canalizaciones con nombre: sleep , shabugabu y single_instance_script

En este caso, la llamada inicial iniciará un lector y ejecutar single_instance_script con some arguments como argumentos. Una vez que se completa la llamada, el lector tomará la siguiente solicitud de la tubería y la ejecutará con some other_arguments , completará, some other_arguments el próximo etc ...

Este script bloqueará los procesos solicitantes, así que llámalo como un trabajo en segundo plano (y al final) o como un proceso separado con at ( at now <<< "./pipeline some_script" )

#!/bin/bash -Eue # Using command name as the pipeline name pipeline=$(basename $(expr "$1" : ''/(^[^[:space:]]*/)'')).pipe is_reader=false function _pipeline_cleanup { if $is_reader; then rm -f $pipeline fi rm -f $pipeline.lock exit } trap _pipeline_cleanup INT TERM EXIT # Dispatch/initialization section, critical lockfile $pipeline.lock if [[ -p $pipeline ]] then echo "$*" > $pipeline exit fi is_reader=true mkfifo $pipeline echo "$*" > $pipeline & rm -f $pipeline.lock # Reader section while read command < $pipeline do echo "$(date) - Executing $command" ($command) &> /dev/null done