Błąd `ls` po usunięciu katalogu

13

Mam dwie otwarte muszle. Pierwszy znajduje się w katalogu A. W drugim usuwam katalog A, a następnie tworzę go ponownie. Kiedy wracam do pierwszej powłoki i piszę ls, dane wyjściowe są następujące:

ls: cannot open directory .: Stale file handle

Dlaczego? Myślałem, że pierwsza powłoka (ta, która pozostała otwarta w nieistniejącym katalogu) „zawiesiłaby się” podczas oczekiwania na następne polecenie i nie „uświadomiłaby sobie”, że katalog został usunięty i ponownie utworzony. Czy powłoka zawiera „głębsze” odwołanie do bieżącego katalogu roboczego innego niż ciąg $PWD?

fonini
źródło
2
Brak odpowiedzi, ale jeśli po prostu chcesz, aby twoja skorupa upadła na nogi, możesz biegać cd $PWD.
dhag
Chciałbym zrozumieć, co się dzieje, wiem, że łatwo jest odzyskać muszlę :)
fonini
Czy ten katalog jest na serwerze NFS? Myślę, że to jedyna sytuacja, w której dostajesz przestarzałe uchwyty plików.
Barmar
Katalog jest lokalny. Kiedy robisz to w swoim systemie, wynik jest inny?
fonini,

Odpowiedzi:

17

Katalog (jak każdy plik) nie jest zdefiniowany przez swoją nazwę. Pomyśl o nazwie jak o adresie katalogu . Gdy przenosisz katalog, pozostaje to ten sam katalog, tak jak w przypadku przeprowadzki do innego domu, nadal jesteś tą samą osobą. Jeśli usuniesz katalog i utworzysz nowy o tej samej nazwie, będzie to nowy katalog, podobnie jak ktoś, kto wprowadza się do domu, w którym mieszkałeś, to nie ty.

Każdy proces ma katalog roboczy . cdPolecenie w powłoce zmienia aktualny katalog roboczy powłoki. pwdKomenda drukuje the¹ ścieżkę do bieżącego katalogu roboczego.

Po usunięciu katalogu A dokonano usunięcia wpisu A w katalogu nadrzędnym. Sam katalog A pozostał w systemie plików, ale w stanie odłączonym, bez nazwy. Nie został jeszcze usunięty, ponieważ był używany przez proces, a mianowicie pierwszą powłokę. Kiedy zmieniłeś katalog w pierwszej powłoce, katalog został ostatecznie usunięty. To samo dzieje się, gdy plik jest usuwany, gdy proces ma go jeszcze otwarty: pozycja katalogu pliku jest usuwana natychmiast, a sam plik jest usuwany, gdy przestaje być używany.

Podobnie obserwuj, co się dzieje, gdy przenosisz katalogi.

mkdir one two
touch one/1 two/2
cd one
ls

W innej powłoce:

mv one tmp
mv two one
mv tmp two

W pierwszej powłoce:

ls

Plik 1znajduje się w katalogu, który był pierwotnie wywoływany onei teraz jest wywoływany two. Plik 2znajduje się w katalogu, który był pierwotnie wywoływany twoi teraz jest wywoływany one.

Đ Dokładniej drogę, która nie może być unikalny jeśli obejmuje linki lub innych symbolicznych subtelności.

Gilles „SO- przestań być zły”
źródło
Kluczową kwestią jest tutaj to, że proces przechowuje i-węzeł swojego katalogu roboczego, a nie tylko ścieżkę?
Nacht - Przywróć Monikę
1
@Nacht Proces posiada deskryptor, ale jądro wykonuje całe mapowanie (deskryptor / wpisy tabel plików / i-węzeł). I rzeczywiście wewnętrznie jądro nie przechowuje ścieżek (ponieważ interesujące rzeczy znajdują się w i-węźle, a nie ścieżce). Poza tym „ścieżka” to tylko jeden link do pliku ... może być ich kilka :)
John WH Smith
och racja ma deskryptor. więc bash stale przechowuje fd katalogu roboczego? na pewno nie wszystkie procesy mają fds z katalogu roboczego ... myślałem, że pamiętam fds zaczynający się od wartości 3 po stdin / out / err
Nacht - Przywróć Monikę
2
@Nacht Bieżący katalog nie jest deskryptorem pliku, ale działa podobnie jak jeden. Jądro utrzymuje to dla każdego procesu. W systemie Linux możesz to zobaczyć /proc/<pid>/cwd, co działa podobnie /proc/<pid>/fd/<number>. Jest CWDw wyniku lsof.
Gilles „SO- przestań być zły”
czy cd - && cd -w takim przypadku można zrobić automatyczne ?
Witalij Zdanevich,
8

Nowy katalog A nie jest taki sam jak katalog A. Można go sprawdzić statpoleceniem przed usunięciem starego i po utworzeniu nowego, a zobaczysz różne numery i-węzłów.
Myślę, że jest to związane z działaniem jądra. Po prostu śledzi numer i bieżącego katalogu dla każdego procesu. Ponieważ istnieją różne liczby i, doprowadzi to do różnych kolizji.

taliezin
źródło
Należy zauważyć, że i-węzeł jest strukturą, a nie unikalną liczbą. Można go jednoznacznie zidentyfikować, ale zawiera więcej informacji niż jego identyfikator. To czyni go ważniejszym niż linki.
John WH Smith,
1
@JohnWHSmith Mam zamiar usunąć tę odpowiedź, ponieważ Gilles jest lepszy.
taliezin
6
To nie jest powód, aby usunąć swój! Jeśli czujesz się w ten sposób, możesz po prostu dodać do swojej odpowiedzi wyłączenie odpowiedzialności wyjaśniające, że uważasz drugą za lepszą.
terdon
7

Jest to oczekiwane zachowanie. Nowy katalog A nie jest taki sam jak stary katalog A, po prostu ma taką samą nazwę. Więc $ PWD z pierwszego terminala wciąż nie ma, nie pojawił się magicznie, kiedy to zrobiłeś mkdir A.

Jan
źródło
2
czy mógłbyś rozwinąć „nowy katalog A nie jest taki sam jak stary katalog A”. Jakie aspekty zmiany pliku / katalogu zmieniają się? Czy ma to związek z numerem i-węzła? Przepraszam, że pytam, ale dopiero się uczę.
rahul
2
@rahul Filozoficznie zmienia się jego tożsamość - nowy katalog został utworzony z niczego w tym samym miejscu. Na poziomie implementacji tak, wszystkie otwarte pliki są identyfikowane przez i-węzeł, a stare i nowe katalogi będą miały odrębne i-węzły o różnych numerach i-węzłów.
hobbs
0

Z katalogiem, takim jak plik, związana jest i-węzła:

307% mkdir ABC

308% ls -i 11997708 A 11997709 B 11997710 C.

I-węzeł to struktura danych, która zawiera informacje o katalogu lub pliku. Każdy katalog i plik ma jeden. Pomyśl o tym jak o adresie (naprawdę numer indeksu).

Jeśli jestem w A, i-węzeł o numerze 11997708 i w innej powłoce (lub w tej samej powłoce, co zamierzam zrobić), usuń katalog A, a następnie utwórz go ponownie i jest to i-węzeł:

309% cd A

310% rmdir ../A

311% mkdir ../A

312% ls -i ..

11997720 A 11997709 B 11997710 C.

Węzeł i jest inny, więc jeśli spróbuje utworzyć plik w usuniętym katalogu A:

313% dotknie tego

touch: nie można dotknąć „this”: brak takiego pliku lub katalogu

ponieważ katalog, w którym się znajduję - nie jest już powiązany z i-węzłem 11997720 - więc tam, gdzie obecnie nie ma już prawidłowego adresu / indeksu - i-węzeł. Zatem błąd.

użytkownik2592248
źródło