GNU/Linux >> Linux Esercitazione >  >> Linux

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

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.


Linux
  1. Trasferimenti di file più intelligenti rispetto a Rsync??

  2. Tail -f, Determina se un file non viene più scritto?

  3. Permessi dei file in Linux con esempio

  4. Guardare qualcosa che viene scritto su un file dal vivo con la coda

  5. Preservare i permessi di file e cartelle con rsync

Comando Linux WC con esempi

Iniziare con ls

Firme digitali con GnuPG

Sto ancora lavorando con le scatole degli gnomi

È sicuro aprire un file che viene scritto da uno script in esecuzione?

Determinare se il file è in fase di scrittura?