ls-Fehler beim Löschen des Verzeichnisses

13

Ich habe zwei Muscheln offen. Das erste befindet sich in Verzeichnis A. Im zweiten entferne ich Verzeichnis A und erstelle es dann neu. Wenn ich zur ersten Shell zurückkehre und tippe ls, ist die Ausgabe:

ls: cannot open directory .: Stale file handle

Warum? Ich dachte, die erste Shell (die in einem nicht existierenden Verzeichnis geöffnet blieb) würde "einfrieren", während sie auf den nächsten Befehl wartet, und hätte nicht "bemerkt", dass das Verzeichnis gelöscht und neu erstellt wurde. Enthält die Shell einen "tieferen" Verweis auf ihr aktuelles Arbeitsverzeichnis als die Zeichenfolge $PWD?

Fonini
quelle
2
Eine nicht beantwortete Frage, aber wenn Sie einfach möchten, dass Ihre Muschel auf die Beine fällt, können Sie rennen cd $PWD.
Dhag
Ich würde gerne verstehen, was los ist, ich weiß, es ist einfach, die Muschel zurück zu bekommen :)
fonini
Befindet sich dieses Verzeichnis auf einem NFS-Server? Ich denke, das ist die einzige Situation, in der Sie veraltete Dateihandles bekommen.
Barmar
Das Verzeichnis ist lokal. Wenn Sie dies in Ihrem System tun, ist das Ergebnis unterschiedlich?
Fonini

Antworten:

17

Ein Verzeichnis (wie jede Datei) wird nicht durch seinen Namen definiert. Stellen Sie sich den Namen als Adresse des Verzeichnisses vor . Wenn Sie das Verzeichnis verschieben, ist es immer noch dasselbe Verzeichnis, genau wie wenn Sie in ein anderes Haus umziehen, sind Sie immer noch dieselbe Person. Wenn Sie ein Verzeichnis entfernen und ein neues mit demselben Namen erstellen, ist es ein neues Verzeichnis, genau wie jemand, der in das Haus zieht, in dem Sie früher gewohnt haben, nicht wahr?

Jeder Prozess hat ein Arbeitsverzeichnis . Der cdBefehl in der Shell ändert das aktuelle Arbeitsverzeichnis der Shell. Der pwdBefehl gibt den Pfad zum aktuellen Arbeitsverzeichnis aus.

Als Sie das Verzeichnis A entfernt haben, wurde der Eintrag für A im übergeordneten Verzeichnis entfernt. Das Verzeichnis A selbst blieb im Dateisystem, jedoch ohne Namen. Es wurde noch nicht gelöscht, da es von einem Prozess verwendet wurde, nämlich der ersten Shell. Als Sie das Verzeichnis in der ersten Shell geändert haben, wurde das Verzeichnis endgültig gelöscht. Dasselbe passiert, wenn eine Datei gelöscht wird, während ein Prozess sie noch geöffnet hat: Der Verzeichniseintrag der Datei wird sofort entfernt, und die Datei selbst wird entfernt, wenn sie nicht mehr verwendet wird.

Beobachten Sie auch, was passiert, wenn Sie Verzeichnisse verschieben.

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

In einer anderen Shell:

mv one tmp
mv two one
mv tmp two

In der ersten Schale:

ls

Die Datei 1befindet sich in dem Verzeichnis, das ursprünglich aufgerufen wurde, oneund wird jetzt aufgerufen two. Die Datei 2befindet sich in dem Verzeichnis, das ursprünglich aufgerufen wurde, twound wird jetzt aufgerufen one.

¹ Genauer gesagt, ein Pfad, der möglicherweise nicht eindeutig ist, wenn symbolische Verknüpfungen oder andere Feinheiten beteiligt sind.

Gilles 'SO - hör auf böse zu sein'
quelle
Der entscheidende Punkt hier ist also, dass ein Prozess die Inode seines Arbeitsverzeichnisses enthält, nicht nur den Pfad?
Nacht - Wiedereinsetzung von Monica
1
@Nacht Der Prozess enthält einen Deskriptor, aber der Kernel führt die gesamte Zuordnung durch (Deskriptor / Dateitabelleneinträge / Inode). Und tatsächlich speichert der Kernel intern keine Pfade (weil das Interessante in der Inode ist, nicht der Pfad). Außerdem ist ein "Pfad" nur ein Link zu einer Datei ... es kann mehrere geben :)
John WH Smith
Oh, richtig, es enthält einen Deskriptor. so bash hält ständig ein fd des arbeitsverzeichnisses? mit sicherheit haben nicht alle prozesse fds des arbeitsverzeichnisses ... ich dachte, ich erinnere mich an fds ab dem wert 3 nach stdin / out / err
Nacht - Reinstate Monica
2
@Nacht Das aktuelle Verzeichnis ist kein Dateideskriptor, funktioniert aber ähnlich. Der Kernel behält das für jeden Prozess bei. Unter Linux kann man es sehen /proc/<pid>/cwd, was so funktioniert /proc/<pid>/fd/<number>. Es ist CWDin der Ausgabe von lsof.
Gilles 'SO- hör auf böse zu sein'
ist es möglich, cd - && cd -in einem solchen Fall automatisch zu machen ?
Vitaly Zdanevich
8

Das neue Verzeichnis A ist nicht dasselbe wie das Verzeichnis A. Es kann statvor dem Löschen des alten und nach dem Erstellen des neuen Verzeichnisses mit dem Befehl überprüft werden, und es werden verschiedene i-Node-Nummern angezeigt.
Und ich denke, das hängt damit zusammen, wie der Kernel funktioniert. Es verfolgt einfach die i-Nummer des aktuellen Verzeichnisses für jeden Prozess. Da es also unterschiedliche i-Nummern gibt, führt dies zu unterschiedlichen Kollisionen.

Taliezin
quelle
Es sollte beachtet werden, dass ein Inode eine Struktur ist, keine eindeutige Nummer. Es kann eindeutig identifiziert werden, enthält jedoch mehr Informationen als seine ID. Deshalb ist es wichtiger als Links.
John WH Smith
1
@JohnWHSmith Ich werde diese Antwort löschen, da Gilles eine bessere ist.
Taliezin
6
Das ist kein Grund, Ihren zu löschen! Wenn Sie so denken, können Sie Ihrer Antwort einfach einen Haftungsausschluss hinzufügen, der erklärt, dass Sie den anderen für besser halten.
terdon
7

Dies ist das erwartete Verhalten. Das neue Verzeichnis A ist nicht dasselbe wie das alte Verzeichnis A, es hat einfach den gleichen Namen. Die $ PWD des ersten Terminals ist also immer noch weg, sie ist nicht auf magische Weise wieder aufgetaucht, als Sie das getan haben mkdir A.

John
quelle
2
Könnten Sie näher erläutern, ob das neue Verzeichnis A nicht mit dem alten Verzeichnis A identisch ist? Welche Aspekte der Datei / des Verzeichnisses ändern sich? Hat es mit der Inode-Nummer zu tun? Tut mir leid, dass ich gefragt habe, aber ich lerne gerade davon.
Rahul
2
@rahul Was sich philosophisch ändert, ist seine Identität - ein neues Verzeichnis wurde aus dem Nichts am selben Ort erstellt. Ja, auf Implementierungsebene werden alle geöffneten Dateien durch den Inode identifiziert, und das alte und das neue Verzeichnis haben unterschiedliche Inodes mit unterschiedlichen Inode-Nummern.
Hobbs
0

Einem Verzeichnis ist wie einer Datei ein Inode zugeordnet:

307% mkdir ABC

308% ls -i 11997708 A 11997709 B 11997710 C

Ein Inode ist eine Datenstruktur, die Informationen über das Verzeichnis oder die Datei enthält. Jedes Verzeichnis und jede Datei hat eines. Stellen Sie es sich als Adresse vor (eine Indexnummer wirklich).

Wenn ich mich in A befinde , Inode-Nummer 11997708 und in einer anderen Shell (oder in derselben Shell, in der ich mich gerade befinde ), lösche Verzeichnis A, erstelle es neu und ls die Inode:

309% CD A

310% rmdir ../A

311% mkdir ../A

312% ls -i ..

11997720 A 11997709 B 11997710 C

Der i-Knoten ist anders. Wenn also versucht wird, eine Datei im gelöschten Verzeichnis A zu erstellen, gilt Folgendes:

313% berühren dies

touch: kann 'this' nicht berühren: Keine solche Datei oder kein solches Verzeichnis

da das Verzeichnis, in dem ich mich befinde, nicht mehr mit dem Inode 11997720 verknüpft ist, hat mein aktueller Standort also keine legitime Adresse / Index - Inode. Also der Fehler.

user2592248
quelle