Jak „cp” obsługuje otwarte pliki?

15

Mam dwa osobne katalogi. Użytkownik ładuje plik do pierwszego. W tle działa cronjob, który co 5 minut kopiuje pliki do drugiego katalogu.

Co się stanie, jeśli użytkownik nie ukończy przesyłania, a osoba wykonująca kopiowanie skopiuje pliki? Zauważ, że oba katalogi są własnością różnych użytkowników, cronjob jest wykonywany jako root.

Nadąsany
źródło
przeczytaj ten post, aby zobaczyć, co się stanie w takim przypadku: unix.stackexchange.com/questions/49299/…
Serge
Dzięki, dobry post, który napisałeś. Ale moje pytanie dotyczyło bardziej cp, a nie obsługi plików w systemie Linux. Myślałem, że może CP sprawdza, czy plik jest nadal otwarty i czeka, aż zostanie zamknięty lub coś.
Stuffy
Nie. Nie cpbędzie czekać, aż plik zostanie całkowicie przesłany. Ponieważ oczekujemy, że szybkość transferu w sieci jest niższa niż tylko kopiowanie pliku z jednej lokalizacji do drugiej w tym samym hoście, w pewnym momencie cposiągnie bieżący koniec pliku i przestanie kopiować. Rozwiązanie problemu może być proste: najpierw użytkownik przesyła plik z jakąś specjalnie zniekształconą nazwą pliku (na przykład poprzedzony .znakiem (kropka). Po zakończeniu przesyłania użytkownik zmienia nazwę na pierwotną nazwę. Następnie zadanie cron wygląda tylko dla plików, które nie są zaczynając ..
Serge

Odpowiedzi:

17

cpnie wie o otwartych plikach. Więc jeśli pierwszy użytkownik prześle duży plik i cronjob (lub jakikolwiek inny proces) rozpocznie kopiowanie tego pliku, skopiuje tylko tyle, ile zostało już zapisane. Możesz o tym pomyśleć w ten sposób - cptworzy kopię tego, co aktualnie znajduje się na dysku, bez względu na to, czy plik jest kompletny. W przeciwnym razie nie można na przykład skopiować plików dziennika.

Krzysztof Adamski
źródło
Dzięki, to właśnie chciałem wiedzieć! Czy istnieje prosty sposób, aby tego uniknąć? Sprawdziłem stronę podręcznika użytkownika cp, ale nie znalazłem nic przydatnego.
Stuffy
Co robić dokładnie? Czy skopiować wszystkie pliki oprócz otwartych? Nie wydaje mi się, żeby można to zrobić w prosty sposób (poza napisaniem własnego skryptu, który używa fuser+ cp. Taka kopia byłaby bardzo niewiarygodna. Nie skopiuje na przykład żadnego pliku, który zostanie otwarty w edytorze tekstu.
Krzysztof Adamski
@Stuffy, może w twojej koleżance mógłbyś wyświetlić listę otwartych plików lsof? Wynik tego ma być łatwy do przetworzenia. Możesz filtrować otwierane pliki (powiedzmy, według instancji cp) do zapisu.
Wojtek Rzepala
@WojtekRzepala, przyjrzę się temu, dzięki. Może będę napisać mały skrypt, który zostanie wykonany przez cron
duszno
@Stuffy: Należy pamiętać, że może nie być naprawdę niezawodny, jeśli nie jest uruchamiany przez użytkownika root (ten sam problem występuje fuseroczywiście), ponieważ to narzędzie może nie wyświetlać wszystkich plików.
Krzysztof Adamski
7

cpnie wie, jakie inne programy mogą mieć otwarte pliki. Nie ma w tym magii cp. Konstrukcja unixa celowo zapobiega nakładaniu jakichkolwiek blokad na pliki, chyba że istnieje ważny powód (przekonujący, co oznacza, że ​​jądro go potrzebuje). W tym temacie zobacz Czy przekierowywanie danych wyjściowych do pliku powoduje zablokowanie pliku?

Takie sytuacje, w których plik jest wytwarzany przez producenta i po skompletowaniu, konsumowany przez konsumenta, są powszechne. Zwykłym sposobem na poradzenie sobie z tym jest zapisanie przez producenta pliku tymczasowego, którego konsument nie będzie szukał, a następnie, gdy producent skończy, przenieś plik w miejsce, w którym konsument go znajdzie. Przenoszenie pliku (w tym samym systemie plików) jest operacją atomową: w pewnym momencie dla konsumenta plik zmienia się z nieobecności na bycie tam.

Więc zorganizuj zadanie przesyłania, aby przenieść pliki do innego katalogu po zakończeniu przesyłania. Skieruj zadanie crona na ten inny katalog.

Gilles „SO- przestań być zły”
źródło
6

Wygląda na to, że chcesz wykonać zadanie synchronizacji katalogu.

Ponieważ opcja -u, --updatecp

kopiuj tylko wtedy, gdy plik SOURCE jest nowszy niż plik docelowy lub gdy brakuje pliku docelowego

Możesz więc dodać cronjob, na przykład, cp -auv SOURCEDIR/* DESTDIRktóry skopiuje pliki, których czas modyfikacji się zmienił. Oznacza to, DESTDIRże w końcu otrzymasz pełną kopię po zakończeniu przesyłania.

rsyncmogę wykonać tę samą pracę. np rsync -av SOURCEDIR/ DESTDIR.

Chociaż zastosowano opcję -a, niektóre określone atrybuty (np. Własność) mogą być zachowane tylko przez superużytkownika.

Zobacz man cp, man rsyncaby poznać szczegóły.

Edw4rd
źródło
Uważaj tylko na ostatnie wpisy w folderze docelowym - mogą to nie być pełne pliki.
dubiousjim