Muszę wdrożyć zautomatyzowany proces (za pomocą skryptu cron 1 min), który szuka plików tar w określonym katalogu. Jeśli plik tar zostanie znaleziony, zostanie on rozpakowany do odpowiedniej lokalizacji, a następnie plik tar zostanie usunięty.
Pliki tar są automatycznie kopiowane na ten serwer przez SSH z innego serwera. W niektórych przypadkach pliki tar są bardzo duże i zawierają wiele plików.
Problem, na który mam się natknąć: jeśli skopiowanie pliku tar na serwer zajmie> 1 minutę, a skrypt cron będzie działał co minutę, zobaczy plik .tar.gz i spróbuje to zrobić rozpakuj go, mimo że plik tar nadal jest w trakcie zapisywania.
Czy jest jakiś sposób (za pomocą komend bash) przetestowania, czy plik jest obecnie zapisywany, czy jest to tylko plik częściowy itp.?
Jedną z możliwości, o której myślałem, było skopiowanie pliku jako innego rozszerzenia (jak .tar.gz.part
), a następnie zmiana nazwy na .tar.gz
po zakończeniu przesyłania. Ale pomyślałem, że spróbuję dowiedzieć się, czy istnieje prosty sposób, aby najpierw ustalić, czy plik jest cały w wierszu poleceń ... Jakieś wskazówki?
rsync
używa tymczasowej nazwy pliku podczas przesyłania (domyślnie) i dopiero po całkowitym przesłaniu pliku zmienia nazwę na rzeczywistą nazwę pliku.Odpowiedzi:
Jesteś na dobrej drodze, zmiana nazwy pliku jest operacją atomową, więc zmiana nazwy po przesłaniu jest prosta, elegancka i nie jest podatna na błędy. Innym podejściem, które mogę wymyślić, jest
lsof | grep filename.tar.gz
sprawdzenie, czy dostęp do pliku uzyskuje inny proces.źródło
lsof filename.tar.gz
jest bardziej wydajny i dokładniejszy niżlsof | grep filename.tar.gz
)Najlepszym rozwiązaniem jest
lsof
ustalenie, czy plik został otwarty w wyniku dowolnego procesu:Nie możesz łatwo stwierdzić, czy jest w trakcie pisania, ale jeśli jest zapisywane, MUSI być otwarte.
Edycja: rozwiążmy tutaj rzeczywisty problem, zamiast próbować wdrożyć proponowane rozwiązanie!
Użyj rsync do przesłania pliku:
W ten sposób plik nie zostanie skopiowany ponad istniejący, ale skopiowany do pliku tymczasowego (
.big.tar.gz.XXXXXX
) do czasu zakończenia przesyłania, a następnie przeniesiony na miejsce.źródło
Trochę stary, ale większość odpowiedzi całkowicie pomija sens pytania:
Ogólnie nie ma. Po prostu nie masz wystarczających informacji, aby to ustalić.
Ponieważ ustalenie, że plik jest zamknięty, nie jest tym samym, co ustalenie, czy plik jest cały . Na przykład plik zostanie „zamknięty”, jeśli połączenie zostanie utracone w trakcie przesyłania.
Tylko odpowiedź @ Alexa miała rację. I nawet on zakochał się w
lsof
jakimś użyciu .Aby ustalić, czy plik został w pełni przesłany, pomyślne przesłanie wymaga więcej danych. Jak na przykład:
To doskonały sposób na poinformowanie, że plik został w pełni i pomyślnie przesłany. Możesz także przenosić pliki z jednego katalogu do drugiego, o ile pozostajesz w tym samym systemie plików. Lub poproś nadawcę o przesłanie pustego
filename.done
pliku w celu zasygnalizowania zakończenia.Ale wszystkie metody muszą polegać na nadawcy, który w jakiś sposób sygnalizuje, że transfer został pomyślnie zakończony. Ponieważ tylko nadawca ma tę informację.
Niektóre formaty plików (takie jak pliki PDF) zawierają dane, które pozwalają ustalić, czy plik jest kompletny. Ale musisz się dowiedzieć i otworzyć prawie cały plik.
lsof
powie ci tylko, że plik nie jest już otwarty - nie powie ci, dlaczego nie jest już otwarty. Nie powie ci też, jak duży powinien być ten plik.źródło
Najlepszym sposobem na to jest użycie incron („system cot inotify”). Pozwala ustawić zegarek inotify w katalogu, który następnie powiadomi cię o operacjach na plikach. W takim przypadku powinieneś obejrzeć katalog w poszukiwaniu close_write. Umożliwi to uruchomienie polecenia po zamknięciu pliku po zapisie.
źródło
Wygląda na to, że lsof może wykryć, w jakim trybie plik jest otwarty:
Widzisz, gdzie jest napisane 1w? Oznacza to, że numerem deskryptora pliku jest 1, a tryb to w lub zapis.
źródło
FD
pokazy polowe3r
dla mnie, gdy plik jest otwarty do odczytu.Używanie
inotifywait
może osiągnąć to, czego szukasz - może poczekać, aż zapis pliku zakończy się przed wykonaniem polecenia.Następujące będą stale obserwować folder pod kątem nowych plików i wykonywać polecenie w pętli po zakończeniu zapisu do pliku.
Więcej opcji konfiguracji można znaleźć na stronie https://linux.die.net/man/1/inotifywatch
źródło