Se Apache sta scrivendo un file di qualche tipo in un posto e non ha completato la scrittura e poi rsync
entra in gioco, 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 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 utilizzare il --inplace
opzione in rsync
per fare quanto segue:
Questa opzione cambia il modo in cui rsync trasferisce un file quando i dati del file devono essere aggiornati:invece del metodo predefinito di creare una nuova copia del file e spostarla al suo posto quando è completo, rsyncin scrive invece i dati aggiornati direttamente nel file di destinazione.
Il vantaggio di questo è che se un file da 5 MB ha solo 2 MB copiati alla prima esecuzione, l'esecuzione successiva riprenderà a 2 MB e continuerà a copiare il file fino a quando non saranno presenti tutti i 5 MB.
Il negativo è che potrebbe creare una situazione in cui qualcuno accede al server Web mentre un file viene copiato e quindi vedrebbe un file parziale. Secondo me rsync
funziona meglio nel suo comportamento predefinito di memorizzare nella cache un file "invisibile" e quindi spostarlo immediatamente in posizione. Ma --inplace
è utile per scenari in cui file di grandi dimensioni e vincoli di larghezza di banda potrebbero ostacolare la copia semplice di un file di grandi dimensioni dal punto di partenza.
Detto questo, dichiari questo; l'enfasi è mia:
Ogni cinque minuti ha cron esegue rsync…
Quindi presumo che tu abbia uno script bash in atto per gestire questo cron job? Bene, la cosa è 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 avere rsync
calpestarsi l'un l'altro se va più veloce. Ciò significa che se lo esegui ogni minuto, c'è il rischio che uno o più dei rsync
i processi sarebbero ancora in esecuzione a causa delle dimensioni del file o della velocità della rete e il processo successivo sarebbe solo in competizione con esso; una condizione da corsa.
Un modo per evitarlo è avvolgere l'intero rsync
comando in uno script bash che verifica 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 usare flock
ma poiché flock
non è installato su alcuni sistemi che uso—e salto spesso tra Ubuntu (che ce l'ha) e Mac OS X (che non ce l'ha)—uso questo semplice framework senza alcun problema reale:
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 è quel nucleo generale, dove ho echo "Hello world!"
- è dove si trova il cuore della tua sceneggiatura. Il resto è fondamentalmente un meccanismo/logica di blocco basato su mkdir
. Una buona spiegazione del concetto è in questa risposta:
mkdir crea una directory se non esiste ancora e, se esiste, imposta un codice di uscita. Ancora più importante, fa tutto questo in una singola azione atomica che lo rende perfetto per questo scenario.
Quindi, nel caso del tuo rsync
processo, consiglierei di usare questo script semplicemente cambiando il echo
comando al tuo rsync
comando. Inoltre, cambia il LOCK_NAME
a qualcosa come RSYNC_PROCESS
e poi sei a posto.
Ora con il tuo rsync
avvolto 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
i processi stanno lottando per fare la stessa cosa. Questo ti permetterà di aumentare la velocità o rsync
aggiornamenti che non elimineranno il problema del trasferimento di file parziali, ma contribuiranno ad accelerare il processo complessivo in modo che l'intero file possa essere copiato correttamente a un certo punto.
Sì, e il file potrebbe essere danneggiato se rsync sta leggendo il file nello stesso momento in cui viene scritto.
Puoi provare questo:https://unix.stackexchange.com/a/2558
Puoi anche scriverlo con lsof:
lsof /path/to file
Un codice di uscita 0 indica che il file è in uso, mentre il codice di uscita 1 indica che non c'è attività su quel file.