Chcę przenieść duży plik utworzony przez proces zewnętrzny, jak tylko zostanie zamknięty.
Czy to polecenie testowe jest prawidłowe?
if lsof "/file/name"
then
# file is open, don't touch it!
else
if [ 1 -eq $? ]
then
# file is closed
mv /file/name /other/file/name
else
# lsof failed for some other reason
fi
fi
EDYCJA: plik reprezentuje zestaw danych i muszę czekać, aż zostanie ukończony, aby go przenieść, aby inny program mógł na nim działać. Dlatego muszę wiedzieć, czy proces zewnętrzny jest wykonywany z plikiem.
linux
shell-script
monitoring
open-files
lsof
Peter Kovac
źródło
źródło
lsof
wcale, muszę tylko sprawdzić, czy rozszerzenie pliku nie jest.tmp
. To sprawia, że jest to trywialne. Jednak cieszę się, że zapytałem moje pytanie, od kiedy dowiedział się trochę olsof
iinotify
i rzeczy.Odpowiedzi:
Od
lsof
strony manTo sugerowałoby, że twoja
lsof failed for some other reason
klauzula nigdy nie zostanie wykonana.Czy próbowałeś właśnie przenieść plik, gdy proces zewnętrzny ma go jeszcze otwarty? Jeśli katalog docelowy znajduje się w tym samym systemie plików, nie powinno być z tym żadnych problemów, chyba że musisz uzyskać dostęp do oryginalnej ścieżki z trzeciego procesu, ponieważ i-węzeł pozostanie taki sam. W przeciwnym razie myślę, że
mv
i tak się nie uda.Jeśli naprawdę musisz poczekać, aż proces zewnętrzny zakończy się plikiem, lepiej użyć polecenia blokującego zamiast wielokrotnego odpytywania. W systemie Linux możesz
inotifywait
do tego użyć . Na przykład:Jeśli musisz użyć
lsof
(być może do przenoszenia), możesz wypróbować coś takiego:Aktualizacja
Jak zauważył @JohnWHSmith poniżej, najbezpieczniejszy projekt zawsze używałby
lsof
pętli jak wyżej, ponieważ możliwe jest, że więcej niż jeden proces otworzyłby plik do zapisu (przykładowym przypadkiem może być źle napisany demon indeksujący, który otwiera pliki z odczytem / napisz flagę, kiedy powinna być tylko do odczytu).inotifywait
nadal można go używać zamiast snu, wystarczy wymienić linię snu nainotifywait -e close /path/to/file
.źródło
inotify
. Niestety nie jest zainstalowany na moim pudełku, ale jestem pewien, że gdzieś znajdę paczkę. Zobacz moją edycję z powodów, dla których muszę zamknąć plik: jest to zestaw danych i musi być kompletny przed dalszym przetwarzaniem.inotifywait
zapobiegnie to często „odpytywaniu” skryptu, OP nadal musi sprawdzaćlsof
w pętli: jeśli plik zostanie otwarty dwukrotnie, zamknięcie raz może wywołaćinotify
zdarzenie, nawet jeśli plik nie jest gotowy do zmanipulowane (na przykład w ostatnim fragmencie kodu twojesleep
wywołanie może zostać zastąpioneinotifywait
).close_write
powinien być w porządku, ponieważ tylko jeden proces może mieć otwarty plik do zapisu na raz. Zakłada się, że inny nie otworzy go zaraz po zamknięciu, ale wtedy ten sam problem występuje zlsof
odpytywaniem.CLOSE_WRITE
uruchamiane jest dwukrotnie).Jako alternatywne podejście jest to idealny przypadek dla potoku - drugi proces przetworzy dane wyjściowe z pierwszego procesu, gdy tylko będzie dostępny, zamiast czekać na zakończenie pełnego procesu:
Zalety:
Jeśli nie masz możliwości bezpośredniego utworzenia potoku, ale masz jądra GNU , możesz użyć tego:
Spowoduje to rozpoczęcie odczytu pliku wejściowego od początku, bez względu na to, jak daleko zajdzie pierwszy proces poprzez zapisanie pliku (nawet jeśli nie został jeszcze uruchomiony lub już zakończony).
źródło
cat
iprocess2
kończy przedprocess1
zakończeniem. Nie zablokowaliby się.