ディレクトリが削除されたときの「ls」エラー


13

2つのシェルを開いています。1つ目はディレクトリAにあります。2つ目では、ディレクトリAを削除してから再作成します。最初のシェルに戻って入力するlsと、出力は次のとおりです。

ls: cannot open directory .: Stale file handle

どうして?最初のシェル(存在しないディレクトリ内で開いたままのシェル)は、次のコマンドを待つ間「フリーズ」し、ディレクトリが削除されて再作成されたことを「認識」しなかったと思いました。シェルは、文字列以外の現在の作業ディレクトリへの「より深い」参照を保持しています$PWDか?


2
答えはありませんが、単にシェルを元に戻したい場合は、を実行できますcd $PWD
ダグ

何が起こっているのかを理解したいのですが、シェルを戻すのは簡単だとわかっています:)
fonini

このディレクトリはNFSサーバーにありますか?古いファイルハンドルを取得する唯一の状況だと思います。
バーマー

ディレクトリはローカルです。システムでこれを行うと、結果は異なりますか?
フォニーニ

回答:


17

ディレクトリ(他のファイルと同様)は名前で定義されません。名前をディレクトリのアドレスと考えてください。ディレクトリを移動しても、別の家に移動する場合と同じように、同じディレクトリのままです。ディレクトリを削除して同じ名前で新しいディレクトリを作成すると、それは新しいディレクトリになります。以前住んでいた家に引っ越した人はあなたではないようです。

各プロセスには作業ディレクトリがあります。cdシェル内のコマンドは、シェルの現在の作業ディレクトリを変更します。のpwdコマンドは、現在の作業ディレクトリへの¹パスを出力します。

ディレクトリAを削除したとき、これは親ディレクトリのAのエントリを削除することでした。ディレクトリA自体はファイルシステムに残りましたが、名前のない切り離された状態です。プロセス、つまり最初のシェルで使用されていたため、まだ削除されていません。最初のシェルでディレクトリを変更すると、ディレクトリは最終的に削除されました。プロセスが開いたままファイルを削除しても同じことが起こります。ファイルのディレクトリエントリはすぐに削除され、ファイル自体は使用を停止すると削除されます。

同様に、ディレクトリを移動するとどうなるかを観察します。

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

別のシェルで:

mv one tmp
mv two one
mv tmp two

最初のシェル:

ls

ファイル1は元々呼び出されていたディレクトリにあり、one現在はになっていtwoます。ファイル2は元々呼び出されていたディレクトリにあり、two現在はになっていoneます。

¹ より正確にはシンボリックリンクまたはその他の微妙な要素が関係している場合、一意ではないパス。


ここで重要なのは、プロセスがパスだけでなく、作業ディレクトリのiノードを保持しているということですか?
NACHT -復活モニカ

1
@Nachtプロセスは記述子を保持しますが、カーネルはすべてのマッピング(記述子/ファイルテーブルエントリ/ inode)を実行します。そして実際、内部的には、カーネルはパスを保存しません(興味深いものはパスではなくiノードにあるため)。その上、「パス」はファイルへの1つのリンクにすぎません...複数の可能性があります:)
ジョンWHスミス

ああ、それは記述子を保持しています。bashは常に作業ディレクトリのfdを保持していますか?確かにないすべてのプロセスは、私が標準入力/アウト/ ERRの後に値が3で始まるFDSを思い出したと思った...作業ディレクトリのFDSを持っている
元に戻すモニカ- NACHT

2
@Nacht現在のディレクトリはファイル記述子ではありませんが、よく似た働きをします。カーネルはすべてのプロセスでそれを維持します。Linuxでは、あなたはそれを見ることができる/proc/<pid>/cwdように働きます、/proc/<pid>/fd/<number>。それはだCWDの出力にlsof
ジル「SO-悪であるのをやめる」

そのcd - && cd -ような場合に自動化することは可能ですか?
ヴィタリーズダネビッチ

8

新しいディレクトリAは、ディレクトリAと同じではありません。stat古いディレクトリを削除する前と新しいディレクトリを作成した後、コマンドで確認できます。異なるiノード番号が表示されます。
そして、これはカーネルの仕組みに関係していると思います。各プロセスの現在のディレクトリのi番号を追跡するだけです。したがって、異なるi番号があるため、これは異なる衝突につながります。


iノードは構造体であり、一意の番号ではないことに注意してください。一意に識別できますが、IDよりも多くの情報を保持します。これがリンクよりも重要です。
ジョンWHスミス

1
@JohnWHSmith Gillesの方が優れているので、この回答を削除します。
タリエジン

6
それはあなたのものを削除する理由ではありません!そのように感じた場合は、回答に免責事項を追加するだけで、他の方をより適切に検討することを説明できます。
テルドン

7

これは予想される動作です。新しいディレクトリAは古いディレクトリAと同じではなく、たまたま同じ名前を持っています。したがって、最初の端末の$ PWDはまだなくなっており、それを行ったときに魔法のように再表示されませんでしたmkdir A


2
「新しいディレクトリAは古いディレクトリAと同じではありません」について詳しく説明してください。ファイル/ディレクトリのどの部分が変更されますか?iノード番号と関係がありますか?聞いて申し訳ありませんが、私はこれについて学んでいます。
ラーウル

2
@rahul哲学的には、何が変わるのかはそのアイデンティティです。同じ場所に何もないところから新しいディレクトリが作成されました。実装レベルでは、はい、開いているすべてのファイルはiノードによって識別され、古いディレクトリと新しいディレクトリには、異なるiノード番号を持つ異なるiノードがあります。
ホッブズ

0

ファイルのようなディレクトリには、それに関連付けられたiノードがあります。

307%mkdir ABC

308%ls -i 11997708 A 11997709 B 11997710 C

iノードは、ディレクトリまたはファイルに関する情報を含むデータ構造です。すべてのディレクトリとファイルには1つあります。アドレス(実際にはインデックス番号)と考えてください。

私がAにいる場合、iノード番号11997708、別のシェル(または、これから行うシェルと同じシェル)にいる場合、ディレクトリAを削除してから再作成し、iノードをlsします。

309%cd A

310%rmdir ../A

311%mkdir ../A

312%ls -i ..

11997720 A 11997709 B 11997710 C

iノードは異なるため、削除されたディレクトリAにファイルを作成しようとすると:

313%タッチする

touch:「this」に触れることはできません:そのようなファイルまたはディレクトリはありません

私がいるディレクトリは-iノード11997720に関連付けられていない ため-現在は正当なアドレス/インデックスを持たない-iノードです。したがって、エラー。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.