Wykonywanie operacji zapisu atomowego w pliku bash


13

Po przejrzeniu dokumentacji bash , to pytanie i to wciąż nie jest dla mnie jasne, w jaki sposób mogę wykonać operacje zapisu atomowego (dołączyć) do pliku w bash. Mam skrypt uruchamiany w wielu instancjach, który w pewnym momencie musi zapisać dane do pliku:

echo "$RESULT" >> `pwd`/$TEMP_DIR/$OUT_FILE

Jak to możliwe, aby wszystkie operacje zapisu ze wszystkich jednocześnie działających skryptów do tego pliku były atomowe (aby dane z jednej instancji nie nakładały się na dane z innej)?


1
Do twojej wiadomości nie potrzebujesz `pwd`; możesz po prostu użyć kropki ( .). Powinieneś także zacytować całą nazwę pliku, ponieważ zawiera on zmienne .
Wildcard,

1
Możesz także rozważyć możliwość korzystania z FIFO .
Wildcard,

@Wildcard Thanks. Użyłem pwdwcześniej w skrypcie, aby powiadomić użytkownika o bieżącym katalogu roboczym, a także zapisywać wpisy w pliku dziennika. patrząc teraz na FIFO.
Sebi,

1
Właściwie na tej stronie jest lepsze wprowadzenie do FIFO ; link, który podałem kilka minut temu, jest specyfikacją POSIX mkfifoi nie jest dokładnie poziomem wprowadzającym.
Wildcard,

Niezależnie od tego, czy jest to plik FIFO, czy plik, nadal istnieje ryzyko, że dwie instancje będą zapisywać w tym samym czasie i nawzajem wymieszać dane wyjściowe.
clacke

Odpowiedzi:


10

Wydaje się, że musisz użyć flockjak w przykładzie z man ( http://linux.die.net/man/1/flock )

(
flock -x 200

# Put here your commands that must do some writes atomically

) 200>/var/lock/mylockfile 

I umieść wszystkie swoje polecenia, które muszą być atomowe w ().


Operacja zapisu będzie miała charakter atomowy, mimo że (flock -s 200 # Umieścić tutaj swoje polecenia, które muszą wykonywać niektóre zapisy atomowe) 200> / var / lock / mylockfile działa w wielu równolegle działających skryptach? Lub odwrotnie, czy blokada dotyczy tylko / var / lock / mylockfile?
Sebi,

1
Twój skrypt blokuje / var / lock / mylockfile, ale tylko jedna instancja skryptu może uzyskać na nim blokadę zapisu. Inne instancje będą czekać, aż /var/lock/mylockfilebędzie dostępna blokada.

-s jest blokadą współdzieloną - odpowiednią do odczytu, do blokady zapisu należy użyć opcji -x / -e. Znajduje się on na stronie podręcznika, do której linkowałeś.
Evan Benn,

W którym momencie następuje odblokowanie w tym kodzie? Jak tylko coś zostanie zapisane /var/lock/mylockfilew procesie, który zadzwonił flock -x?
Chris Stryczyński

@ChrisStryczynski Możesz uruchomić ten przykład (flock -x 200; date; sleep 10; date;) 200>/var/lock/mylockfilew dwóch powłokach i zobaczyć, że odblokowanie nastąpi dopiero po wykonaniu wszystkich poleceń in () (czyli w podpowłoce)

4

flockjest jednym ze sposobów blokowania operacji. Narzędzie to jest częścią zestawu narzędzi util-linux i jest dostępne tylko dla systemu Linux. Inne narzędzia, dostępne na szerokiej gamie platform, są oparte na setlockużyteczności Daniela J. Bernsteina z jego pakietu daemontools:

Narzędzia te działają z nieco innym paradygmatem niż ten zastosowany w odpowiedzi M. Kurenkowa (taki, który flockmoże również zastosować, ale nie ma w tej odpowiedzi). Wywołuje się setlockprogram, aby powiązać obciążenie z poleceniem, które musi być zablokowane. setlocksam się otwiera i blokuje plik blokady i pozostawia deskryptor pliku dla niego otwarty w trakcie procesu. Blokada trwa tak długo, jak trwa ten proces (chyba że kolejne polecenie powiązane w celu jawnego zwolnienia blokady przez znalezienie i zamknięcie deskryptora otwartego pliku).

W tym przypadku należy zablokować polecenie, które tworzy linię wyjściową, mając świadomość, że wywołuje to polecenie zewnętrzne echo zamiast wbudowanego echopolecenia powłoki :

echo pliku blokującego setlock „$ RESULT” >> ./$TEMP_DIR/$OUT_FILE

W takim przypadku nie jest konieczne blokowanie otwierania pliku wyjściowego w trybie dołączania. Gdyby tak było, należałoby otworzyć ten plik w zamku, co wymaga użycia programów takich jak fdredir/ redirfd:

setlock mylockfile fdredir --append 1 "./$TEMP_DIR/$OUT_FILE" echo "$ RESULT"
który można zmienić w funkcję powłoki, jeśli chce się:

outfile () {setlock mylockfile fdredir --append 1 "./$TEMP_DIR/$OUT_FILE" "$ @"; } 
[…]
Echo wyjściowe „$ RESULT”
lub trzymanie się składni powłoki i interpretowanie jej przez drugą powłokę działającą pod blokadą, wymagającą nietrywialnego cytowania, jeśli zmienne powłoki nie są eksportowane jako zmienne środowiskowe:

setlock mylockfile sh -c 'echo' "$ RESULT" '>> "./'$TEMP_DIR'/'$OUT_FILE'"

To oczywiście uogólnia na rzeczy inne niż pisanie do plików wyjściowych:

setlock mylockfile sh -c '… zablokowane; rzeczy…

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.