Comportamento di rsync con il file che è ancora in fase di scrittura?


12

Se Apache sta scrivendo un file di grandi dimensioni e un processo cron rsync viene eseguito su quel file, rsync tenta di copiare il file?

Esempio

  • Apache-1: il file di grandi dimensioni è in fase di scrittura /var/www.
  • Apache-2: Clone of Apache-1. Ogni cinque minuti ha cron run rsync per /var/wwwsincronizzare.

Risposte:


20

Se Apache sta scrivendo un file di qualche tipo in un posto e non ha completato la scrittura e poi si rsync avvia, rsynccopierà tutto ciò che è seduto lì.

Significa che se Apache ha a che fare con un file da 5 MB, vengono scritti solo 2 MB e si rsyncavvia, il file parziale da 2 MB verrà copiato. Quindi quel file sembrerebbe "corrotto" sul server di destinazione.

A seconda della dimensione dei file che stai utilizzando, puoi usare l' --inplaceopzione rsyncper fare quanto segue:

Questa opzione cambia il modo in cui rsync trasferisce un file quando è necessario aggiornare i dati del file: invece del metodo predefinito per creare una nuova copia del file e spostarlo in posizione quando è completo, rsync invece scrive i dati aggiornati direttamente nella destinazione file.

Il vantaggio di questo è se un file da 5 MB ha solo 2 MB copiati alla prima esecuzione, l'esecuzione successiva prenderà a 2 MB e continuerà a copiare il file fino a quando non saranno a posto i 5 MB completi.

Il negativo è che potrebbe creare una situazione in cui qualcuno accede al server Web durante la copia di un file e quindi visualizzerebbe un file parziale. A mio avviso rsyncfunziona meglio nel suo comportamento predefinito di memorizzazione nella cache di un file "invisibile" e di spostarlo immediatamente in posizione. Ma --inplaceè utile per gli scenari in cui file di grandi dimensioni e vincoli di larghezza di banda potrebbero impedire a un file di grandi dimensioni di essere facilmente copiato da quello quadrato.

Detto questo lo affermi; l'enfasi è mia:

Ogni cinque minuti ha cron run rsync ...

Quindi suppongo che tu abbia qualche script bash in atto per gestire questo cron job? Bene, il fatto è che rsyncè abbastanza intelligente da copiare solo i file che devono essere copiati. E se hai uno script che viene eseguito ogni 5 minuti, sembra che tu stia cercando di evitare di fare un rsyncpasso avanti se va più veloce. Ciò significa che se lo esegui ogni minuto, c'è il rischio che uno o più rsyncprocessi siano ancora in esecuzione a causa delle dimensioni del file o della velocità della rete e il processo successivo sarebbe in concorrenza con esso; una condizione da corsa.

Un modo per evitarlo è avvolgere l'intero rsynccomando in uno script bash che controlla la presenza di un blocco di file; di seguito è riportato un framework di script bash boilerplate che utilizzo per casi come questo.

Nota che alcune persone consiglieranno di usarlo flockma dato che flocknon è installato su alcuni sistemi che uso - e salto tra Ubuntu (che ce l'ha) e Mac OS X (che non lo fa) molto - Uso questo semplice framework senza alcun vero problema:

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

L'idea è che il nucleo generale — dove ho echo "Hello world!"— è dove si trova il cuore della tua sceneggiatura. Il resto è fondamentalmente un meccanismo di blocco / logica basata su mkdir. Una buona spiegazione del concetto è in questa risposta :

mkdir crea una directory se non esiste ancora e, in tal caso, imposta un codice di uscita. Ancora più importante, fa tutto questo in una singola azione atomica rendendolo perfetto per questo scenario.

Quindi, nel caso del tuo rsyncprocesso, consiglierei di usare questo script semplicemente cambiando il echocomando in rsynccomando. Inoltre, cambia LOCK_NAMEin qualcosa di simile RSYNC_PROCESSe poi sei a posto.

Ora con il tuo rsyncwrapping in questo script, puoi impostare il cron job in modo che venga eseguito ogni minuto senza alcun rischio di una condizione di competizione in cui due o più rsyncprocessi stanno combattendo per fare la stessa cosa. Ciò consentirà di aumentare la velocità o gli rsyncaggiornamenti che non elimineranno il problema dei file parziali trasferiti, ma contribuirà ad accelerare il processo complessivo in modo che il file completo possa essere copiato correttamente a un certo punto.


1
Grazie per aver sottolineato la possibilità di eseguire più rsync, non ci ho pensato. La sceneggiatura suona alla grande. Stavo solo cercando di capire i trucchi per sincronizzare un sito con carico bilanciato con rsync, e questo sembra alleviarli. Bonus meraviglioso. Sento ancora che forse questo è l'approccio sbagliato ... ma vediamo :)
Louis Waweru il

@Louis Prego! Inoltre, se si desidera mantenere le cartelle sincronizzate in base alle modifiche immediate dei file, consiglio vivamente di esaminare l'utilizzo / adattamento lsyncd. Ti consente di avere "hot folder" che prestano davvero attenzione alle attività in esse contenute e quindi agire su quei file quando vengono apportate modifiche. Uso rsyncmolto come indicato nella mia risposta, ma lsyncdper casi che richiedono una forma di azione non cron / immediata.
JakeGould

3

Sì - e il file potrebbe essere danneggiato se rsync sta leggendo il file contemporaneamente alla scrittura del file.

Puoi provare questo: /unix//a/2558

Puoi anche copiarlo con lsof:

lsof /path/to file

Un codice di uscita pari a 0 indica che il file è in uso e il codice di uscita pari a 1 indica che non esiste alcuna attività su quel file.


Non vedo perché il file verrà danneggiato se rsync lo sta leggendo
orestisf
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.