2012-02-22 11 views
17

He buscado una solución aquí pero parece que no puedo encontrarla. Estoy tratando con una conexión wan muy lenta de 300kb/sec. Para mis descargas estoy usando una caja remota, y luego las estoy descargando en mi casa. Estoy intentando ejecutar un cronjob que sincronizará dos directorios en mi servidor remoto y local cada hora. Tengo todo funcionando, pero si hay una gran cantidad de datos para transferir la superposición de rsyncs y termino creando dos instancias del mismo archivo, se duplican los datos enviados.cronjob Rsync que solo se ejecutará si rsync no se está ejecutando

En su lugar, quiero llamar a un script que ejecute mi comando rsync pero solo si rsync no se está ejecutando?

+0

Aquí hay una respuesta similar sobre una única instancia de script de shell, pero toma la respuesta que seleccionó y la hace más robusta. http://stackoverflow.com/questions/185451/quick-and-dirty-way-to-ensure-only-one-instance-of-a-shell-script-is-running-at – physicsmichael

Respuesta

7

A través de la secuencia de comandos puede crear un archivo de "bloqueo". Si el archivo existe, el cronjob debe omitir la ejecución; de lo contrario, debería continuar. Una vez que la secuencia de comandos finaliza, debe eliminar el archivo de bloqueo.

 
if [ -e /home/myhomedir/rsyncjob.lock ] 
then 
    echo "Rsync job already running...exiting" 
    exit 
fi 

touch /home/myhomedir/rsyncjob.lock 

#your code in here 

#delete lock file at end of your job 

rm /home/myhomedir/rsyncjob.lock 
+0

ok, soy realmente nuevo en todo el asunto del script, encontró esto: 'code'if (set -o noclobber; echo" locked ">" $ lockfile ") 2>/dev/null; luego trap 'rm -f "$ lockfile"; salir $?'INT PLAZO DE SALIDA eco "Bloqueo tuvo éxito"> & 2 rm -f "$ fichero de bloqueo" demás echo "Error de bloqueo - salida"> & 2 salida 1 fi '\ code' – mfpockets

+0

No tiene por qué ser complejo . Simplemente crea un archivo de bloqueo. Use if -e para verificar la existencia del archivo y, si existe, exit; else proceder – bubbly

+0

Gracias, esto ayudará una vez que sepa cómo hacer los archivos de bloqueo correctamente. :(no es útil para un novato. – mfpockets

73

El problema con la creación de un archivo de "bloqueo" como se sugiere en una solución anterior, es que ya exista el archivo de bloqueo si el script responsable de retirar, termina de forma anormal. Esto podría suceder, por ejemplo, si el usuario finaliza el proceso de sincronización rs, o debido a un corte de energía. En su lugar, uno debe usar flock, que no sufre este problema.

Como sucede rebaño también es fácil de usar, por lo que la solución sería simplemente tener este aspecto:

flock -n lock_file -c "rsync ..."

El comando después de la opción -c sólo se ejecuta si no hay otro bloqueo proceso en el lock_file. Si el proceso de bloqueo por cualquier razón finaliza, el bloqueo se liberará en el archivo lock_file. Las opciones -n dicen que el lote debe ser no bloqueante, por lo que si hay otro proceso bloqueando el archivo, no pasará nada.

+1

Esto es absolutamente correcto. Otra solución es usar arrendamientos, en lugar de cerraduras, para que el bloqueo agote el tiempo después de un período de tiempo, a menos que se renueve el contrato. Un arrendamiento es básicamente un archivo de bloqueo con una marca de tiempo. – cha0site

+6

Funcionó perfectamente. Esta debería ser la respuesta aceptada. – chovy

+1

Debe tenerse en cuenta que esto no funcionará en NFS – WarmWaffles

4

Una solución sencilla sin necesidad de utilizar un archivo de bloqueo es simplemente hacer esto:

pgrep rsync > /dev/null || rsync -avz ... 

Esto funcionará siempre y cuando sea el único trabajo rsync se ejecuta en el servidor y, a continuación, puede ejecutar este directamente en cron, pero deberá redirigir el resultado a un archivo de registro.

Si lo hace ejecutar varias tareas rsync, puede obtener pgrep para que coincida en contra de la línea de comandos completa con un patrón de esta manera:

pgrep -f rsync.*/data > /dev/null || rsync -avz --delete /data/ otherhost:/data/ 
pgrep -f rsync.*/www > /dev/null || rsync -avz --delete /var/www/ otherhost:/var/www/ 
2

Para usar el ejemplo dado por el archivo de bloqueo @user anteriormente, una trampa se debe usar para verificar que el archivo de bloqueo se elimine cuando el script se cierra por algún motivo.

if [ -e /home/myhomedir/rsyncjob.lock ] 
then 
    echo "Rsync job already running...exiting" 
    exit 
fi 

touch /home/myhomedir/rsyncjob.lock 

#delete lock file at end of your job 

trap 'rm /home/myhomedir/rsyncjob.lock' EXIT 

#your code in here 

De esta forma, el archivo de bloqueo se eliminará incluso si el script se cierra antes del final del script.

+0

Esta es en realidad la mejor solución – berezovskyi