Se Apache sta scrivendo un file di qualche tipo in un posto e non ha completato la scrittura e poi si rsync
avvia, rsync
copierà 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 rsync
avvia, 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' --inplace
opzione rsync
per 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 rsync
funziona 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 rsync
passo avanti se va più veloce. Ciò significa che se lo esegui ogni minuto, c'è il rischio che uno o più rsync
processi 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 rsync
comando 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 flock
ma dato che flock
non è 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 rsync
processo, consiglierei di usare questo script semplicemente cambiando il echo
comando in rsync
comando. Inoltre, cambia LOCK_NAME
in qualcosa di simile RSYNC_PROCESS
e poi sei a posto.
Ora con il tuo rsync
wrapping 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ù rsync
processi stanno combattendo per fare la stessa cosa. Ciò consentirà di aumentare la velocità o gli rsync
aggiornamenti 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.