Pokud Apache zapisuje soubor nějakého druhu na jedno místo a nedokončil jeho zápis a pak rsync
začíná, rsync
zkopíruje vše, co tam je.
To znamená, že pokud Apache pracuje se souborem o velikosti 5 MB, jsou zapsány pouze 2 MB a rsync
se zkopíruje částečný 2 MB soubor. Tento soubor by tedy vypadal, že je na cílovém serveru „poškozený“.
V závislosti na velikosti souborů, které používáte, můžete použít --inplace
možnost v rsync
proveďte následující:
Tato možnost mění způsob, jakým rsync přenáší soubor, když je třeba aktualizovat data souboru:namísto výchozí metody vytvoření nové kopie souboru a jejího přesunutí na místo po dokončení zapíše rsyncinstead aktualizovaná data přímo do cílového souboru.
Výhodou toho je, že pokud má soubor o velikosti 5 MB při prvním spuštění zkopírovány pouze 2 MB, další spuštění bude mít velikost 2 MB a bude pokračovat v kopírování souboru, dokud nebude na místě celých 5 MB.
Negativní je, že by to mohlo vytvořit situaci, kdy někdo přistupuje na webový server během kopírování souboru a pak by viděl částečný soubor. Podle mého názoru rsync
funguje nejlépe ve výchozím chování ukládání „neviditelného“ souboru do mezipaměti a jeho okamžitého přesunutí na místo. Ale --inplace
je dobré pro scénáře, kde velké soubory a omezení šířky pásma mohou stát v cestě snadnému kopírování velkého souboru od druhého.
To znamená, že to uvádíte; důraz je můj:
Každých pět minut má cron spuštěný rsync…
Takže předpokládám, že máte nějaký bash skript pro správu této úlohy cron? Jde o rsync
je dostatečně chytrý, aby zkopíroval pouze soubory, které je třeba zkopírovat. A pokud máte skript, který se spouští každých 5 minut, zdá se, že se snažíte vyhnout tomu, abyste měli rsync
šlápnout na sebe, jde-li to rychleji. To znamená, že pokud jej spustíte každou minutu, existuje riziko, že jeden nebo více z rsync
procesy by stále běžely kvůli velikosti souboru nebo rychlosti sítě a další proces by jim jen konkuroval; závodní podmínky.
Jedním ze způsobů, jak se tomu vyhnout, je zabalit celý rsync
příkaz ve skriptu bash, který kontroluje zámek souboru; níže je standardní rámec bash skriptu, který používám pro případy, jako je tento.
Všimněte si, že někteří lidé doporučují používat flock
ale od flock
není nainstalován na některých systémech, které používám – a často skáču mezi Ubuntu (který jej má) a Mac OS X (který jej nemá) – používám tento jednoduchý rámec bez jakéhokoli skutečného problému:
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
Myšlenka je to obecné jádro – kde mám echo "Hello world!"
—tam je srdce vašeho skriptu. Zbytek je v podstatě zamykací mechanismus/logika založená na mkdir
. Dobré vysvětlení konceptu je v této odpovědi:
mkdir vytvoří adresář, pokud ještě neexistuje, a pokud ano, nastaví ukončovací kód. Ještě důležitější je, že to vše dělá v jednoatomové akci, takže je ideální pro tento scénář.
Tedy v případě vašeho rsync
doporučoval bych použít tento skript pouze změnou echo
příkaz na váš rsync
příkaz. Změňte také LOCK_NAME
na něco jako RSYNC_PROCESS
a pak můžete jít.
Nyní s vaším rsync
zabalený do tohoto skriptu můžete nastavit úlohu cron tak, aby se spouštěla každou minutu, aniž by hrozilo, že dojde k závodnímu stavu, kdy jsou dvě nebo více rsync
procesy bojují o totéž. To vám umožní zvýšit rychlost nebo rsync
aktualizace, které neodstraní problém s přenášením dílčích souborů, ale pomohou urychlit celkový proces, takže celý soubor bude možné v určitém okamžiku správně zkopírovat.
Ano – a soubor může být poškozen, pokud rsync čte soubor ve stejnou dobu, do které se do souboru zapisuje.
Můžete to zkusit:https://unix.stackexchange.com/a/2558
Můžete jej také naskriptovat pomocí lsof:
lsof /path/to file
Výstupní kód 0 znamená, že se soubor používá, a výstupní kód 1 znamená, že s tímto souborem neprobíhá žádná aktivita.