Jeśli Apache pisze jakiś plik w jednym miejscu i nie ukończył go zapisywać, a następnie rsync uruchamia, rsyncskopiuje wszystko, co tam siedzi.
Oznacza to, że jeśli Apache ma do czynienia z plikiem 5 MB, zostanie zapisany tylko 2 MB i zostanie rsyncuruchomiony, częściowy plik 2 MB zostanie skopiowany. Wygląda więc na to, że plik jest „uszkodzony” na serwerze docelowym.
W zależności od rozmiaru używanych plików możesz użyć --inplaceopcji w, rsyncaby wykonać następujące czynności:
Ta opcja zmienia sposób, w jaki rsync przesyła plik, gdy dane pliku wymagają aktualizacji: zamiast domyślnej metody tworzenia nowej kopii pliku i przenoszenia go na miejsce po zakończeniu, rsync zapisuje zaktualizowane dane bezpośrednio do miejsca docelowego plik.
Zaletą tego jest to, że jeśli plik 5 MB ma tylko 2 MB skopiowane przy pierwszym uruchomieniu, następne uruchomienie pobierze 2 MB i będzie kontynuować kopiowanie pliku, aż pełne 5 MB będzie na swoim miejscu.
Negatywne jest to, że może stworzyć sytuację, w której ktoś uzyskuje dostęp do serwera WWW podczas kopiowania pliku, a następnie zobaczy plik częściowy. Moim zdaniem rsyncnajlepiej sprawdza się w domyślnym zachowaniu buforowania „niewidzialnego” pliku, a następnie natychmiastowego przeniesienia go na miejsce. Ale --inplacejest dobry w scenariuszach, w których duże pliki i ograniczenia przepustowości mogą przeszkadzać w łatwym kopiowaniu dużego pliku z pierwszego.
Powiedziałeś, że to stwierdzasz; nacisk jest mój:
Co pięć minut cron uruchamia rsync…
Więc zakładam, że masz jakiś skrypt bash do zarządzania tym zadaniem cron? Cóż, sprawa jest rsyncwystarczająco inteligentna, aby skopiować tylko pliki, które należy skopiować. A jeśli masz skrypt, który jest uruchamiany co 5 minut, wydaje się, że starasz się unikać rsyncna siebie nawzajem, jeśli idzie szybciej. Oznacza to, że jeśli uruchamiasz go co minutę, istnieje ryzyko, że jeden lub więcej rsyncprocesów będzie nadal działać z powodu rozmiaru pliku lub szybkości sieci, a następny proces będzie po prostu z nim konkurował; warunki wyścigowe.
Jednym ze sposobów uniknięcia tego jest zawinięcie całego rsyncpolecenia w skrypt bash, który sprawdza blokadę pliku; poniżej znajduje się szkielet skryptu bash, którego używam do takich przypadków.
Zauważ, że niektórzy ludzie zalecą używanie, flockale ponieważ flocknie jest zainstalowany na niektórych systemach, których używam - i często przeskakuję między Ubuntu (który ma) i Mac OS X (który nie ma) - używam tej prostej struktury bez żadnego poważnego problemu:
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
Chodzi o to, że ten rdzeń - tam, gdzie ja mam echo "Hello world!"- jest sercem twojego skryptu. Reszta jest w zasadzie mechanizmem blokującym / logiką opartą na mkdir. Dobre wyjaśnienie tego pojęcia znajduje się w tej odpowiedzi :
mkdir tworzy katalog, jeśli jeszcze nie istnieje, a jeśli tak, ustawia kod wyjścia. Co ważniejsze, robi to wszystko w jednej akcji atomowej, dzięki czemu idealnie nadaje się do tego scenariusza.
Tak więc w przypadku twojego rsyncprocesu poleciłbym użycie tego skryptu, po prostu zmieniając echopolecenie na twoje rsync. Zmień też LOCK_NAMEna coś takiego, RSYNC_PROCESSa wtedy możesz zacząć.
Teraz, gdy Twój rsyncskrypt jest zawinięty, możesz ustawić zadanie crona do uruchamiania co minutę bez ryzyka warunków wyścigowych, w których dwa lub więcej rsyncprocesów walczy o to samo. Umożliwi to zwiększenie prędkości lub rsyncaktualizacji, co nie wyeliminuje problemu przesyłania częściowych plików, ale pomoże przyspieszyć cały proces, aby w pewnym momencie można było poprawnie skopiować cały plik.