¿Comportamiento de rsync con el archivo que aún se está escribiendo?

12

Si Apache está escribiendo un archivo grande y se ejecuta un trabajo cron rsync en ese archivo, ¿intenta rsync copiar el archivo?

Ejemplo

  • Apache-1: se ha escrito un archivo grande /var/www.
  • Apache-2: Clon de Apache-1. Cada cinco minutos tiene cron run rsync para /var/wwwsincronizarse.
Louis Waweru
fuente

Respuestas:

20

Si Apache está escribiendo un archivo de algún tipo en un lugar y no ha terminado de escribirlo y luego lo rsync inicia, rsynccopiará lo que esté allí.

Es decir, si Apache está lidiando con un archivo de 5 MB, solo se escriben 2 MB y se rsyncactiva, se copiará el archivo parcial de 2 MB. Por lo tanto, parece que el archivo está "dañado" en el servidor de destino.

Dependiendo del tamaño de los archivos que esté utilizando, puede usar la --inplaceopción rsyncpara hacer lo siguiente:

Esta opción cambia la forma en que rsync transfiere un archivo cuando los datos del archivo deben actualizarse: en lugar del método predeterminado de crear una nueva copia del archivo y colocarlo en su lugar cuando está completo, rsync escribe los datos actualizados directamente en el destino archivo.

El beneficio de esto es que si un archivo de 5 MB solo tiene 2 MB copiados en la primera ejecución, la siguiente ejecución tomará 2 MB y continuará copiando el archivo hasta que los 5 MB completos estén en su lugar.

Lo negativo es que podría crear una situación en la que alguien está accediendo al servidor web mientras se copia un archivo y luego vería un archivo parcial. En mi opinión, rsyncfunciona mejor en su comportamiento predeterminado de almacenar en caché un archivo "invisible" y luego moverlo a su lugar de inmediato. Pero --inplacees bueno para escenarios en los que los archivos grandes y las restricciones de ancho de banda pueden interponerse en el camino de que un archivo grande se copie fácilmente desde el principio.

Dicho esto, declara esto; El énfasis es mío:

Cada cinco minutos tiene cron ejecutar rsync ...

Entonces, ¿supongo que tienes algún script bash para administrar este trabajo cron? Bueno, la cosa es rsynclo suficientemente inteligente como para copiar solo los archivos que necesitan ser copiados. Y si tiene un script que se ejecuta cada 5 minutos, parece que está tratando de evitar rsyncpisar el uno al otro si va más rápido. Es decir, si lo ejecuta cada minuto, existe el riesgo de que uno o más de los rsyncprocesos aún se estén ejecutando debido al tamaño del archivo o la velocidad de la red y el siguiente proceso simplemente competirá con él; Una condición de carrera.

Una forma de evitar esto es envolver todo el rsynccomando en un script bash que verifique si hay un bloqueo de archivo; a continuación se muestra un marco de secuencia de comandos bash repetitivo que uso para casos como este.

Tenga en cuenta que algunas personas recomendarán usar, flockpero como flockno está instalado en algunos sistemas que uso, y salto mucho entre Ubuntu (que lo tiene) y Mac OS X (que no), utilizo este marco simple sin ningún problema real:

LOCK_NAME="MY_GREAT_BASH_SCRIPT"
LOCK_DIR='/tmp/'${LOCK_NAME}.lock
PID_FILE=${LOCK_DIR}'/'${LOCK_NAME}'.pid'

if mkdir ${LOCK_DIR} 2>/dev/null; then
  # If the ${LOCK_DIR} doesn't exist, then start working & store the ${PID_FILE}
  echo $$ > ${PID_FILE}

  echo "Hello world!"

  rm -rf ${LOCK_DIR}
  exit
else
  if [ -f ${PID_FILE} ] && kill -0 $(cat ${PID_FILE}) 2>/dev/null; then
    # Confirm that the process file exists & a process
    # with that PID is truly running.
    echo "Running [PID "$(cat ${PID_FILE})"]" >&2
    exit
  else
    # If the process is not running, yet there is a PID file--like in the case
    # of a crash or sudden reboot--then get rid of the ${LOCK_DIR}
    rm -rf ${LOCK_DIR}
    exit
  fi
fi

La idea es ese núcleo general, donde yo tengo, echo "Hello world!"donde está el corazón de su guión. El resto es básicamente un mecanismo / lógica de bloqueo basado en mkdir. Una buena explicación del concepto está en esta respuesta :

mkdir crea un directorio si aún no existe, y si lo hace, establece un código de salida. Más importante aún, hace todo esto en una sola acción atómica que lo hace perfecto para este escenario.

Entonces, en el caso de su rsyncproceso, recomendaría usar este script simplemente cambiando el echocomando a su rsynccomando. Además, cambie LOCK_NAMEa algo así RSYNC_PROCESSy entonces estará listo para comenzar.

Ahora, rsyncenvuelto en este script, puede configurar el trabajo cron para que se ejecute cada minuto sin riesgo de una condición de carrera en la que dos o más rsyncprocesos luchan por hacer lo mismo. Esto le permitirá aumentar la velocidad o las rsyncactualizaciones, lo que no eliminará el problema de la transferencia parcial de archivos, pero ayudará a acelerar el proceso general para que el archivo completo se pueda copiar correctamente en algún momento.

JakeGould
fuente
1
Gracias por señalar la posibilidad de ejecutar múltiples rsyncs, no pensé en eso. El guión suena genial. Solo estaba tratando de comprender los trucos de sincronizar un sitio con equilibrio de carga con rsync, y esto parece aliviarlos. Maravillosa bonificación. Todavía siento que tal vez este es el enfoque equivocado ... pero veamos :)
Louis Waweru
@ Louis De nada! Además, si desea mantener las carpetas sincronizadas en función de los cambios inmediatos de archivos, le recomiendo que considere usar / adaptar lsyncd. Le permite tener "carpetas activas" que realmente prestan atención a la actividad en ellas y luego actuar sobre esos archivos cuando se realizan cambios. Uso rsyncmucho como se describe en mi respuesta, pero lo uso lsyncdpara casos que requieren una forma de acción no cron / más inmediata.
JakeGould
3

Sí, y el archivo podría estar dañado si rsync está leyendo el archivo al mismo tiempo que se está escribiendo el archivo.

Puedes probar esto: /unix//a/2558

También puedes escribirlo con lsof:

lsof /path/to file

Un código de salida de 0 significa que el archivo está en uso, y el código de salida de 1 significa que no hay actividad en ese archivo.

rebelde
fuente
No veo por qué el archivo se corromperá si rsync solo lo está leyendo
orestisf hace