Dizin silindiğinde `ls` hatası


13

Açık iki kabuğum var. Birincisi A dizinindedir. İkincisi, A dizinini kaldırırım ve sonra yeniden oluştururum. İlk kabuğa geri döndüğümde ve yazdığımda lsçıktı:

ls: cannot open directory .: Stale file handle

Neden? İlk kabuğu (var olmayan bir dizin içinde açık kalan) bir sonraki komutu beklerken "donacak" ve dizinin silinip yeniden yaratıldığını "fark etmez" diye düşündüm. Kabuk, geçerli çalışma dizinine dize dışında "daha derin" bir başvuru içeriyor $PWDmu?


2
Cevap değil, ama kabuğunun ayağının üzerine düşmesini istiyorsanız, koşabilirsiniz cd $PWD.
dhag

Neler olduğunu anlamak istiyorum, kabuğu geri almanın kolay olduğunu biliyorum :)
fonini

Bu dizin bir NFS sunucusunda mı? Sanırım bayat dosya tutamaçlarını alabileceğiniz tek durum bu.
Barmar

Dizin yereldir. Bunu sisteminizde yaptığınızda sonuç farklı mı?
fonini

Yanıtlar:


17

Bir dizin (herhangi bir dosya gibi) adıyla tanımlanmaz. Adı yönetmenin adresi olarak düşünün . Dizini taşıdığınızda, yine aynı dizin, tıpkı farklı bir eve taşınırsanız, hala aynı kişisiniz. Bir dizini kaldırır ve aynı adla yeni bir dizin oluşturursanız, yeni bir dizindir, tıpkı yaşamakta olduğunuz eve taşınan birisi gibi değil.

Her işlemin bir çalışma dizini vardır . Kabuktaki cdkomut kabuğun geçerli çalışma dizinini değiştirir. pwdKomut geçerli çalışma dizininin the¹ yolunu yazdırır.

A dizinini kaldırdığınızda, bunun yaptığı şey A dizininin ana dizinindeki girişini kaldırmaktı. A dizininin kendisi dosya sisteminde kaldı, ancak adı olmayan bağımsız bir durumda. Bir işlem, yani ilk kabuk tarafından kullanıldığı için henüz silinmedi. İlk kabuktaki dizini değiştirdiğinizde, dizin sonunda silindi. Bir işlem hala açıkken dosya silindiğinde de aynı şey olur: dosyanın dizin girdisi hemen kaldırılır ve kullanılmadığı zaman dosyanın kendisi kaldırılır.

Benzer şekilde, dizinleri hareket ettirdiğinizde neler olduğunu gözlemleyin.

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

Başka bir kabukta:

mv one tmp
mv two one
mv tmp two

İlk kabukta:

ls

Dosya 1başlangıçta çağrılan dizinde oneve şimdi çağrılıyor two. Dosya 2başlangıçta çağrılan dizinde twove şimdi çağrılıyor one.

¹ Daha doğrusu, sembolik bağlantılar veya diğer incelikler söz konusu olduğunda benzersiz olmayan bir yol.


Yani buradaki kilit nokta, bir sürecin sadece yolun değil çalışma dizininin inode'unu tutmasıdır.
Nacht - Monica'yı

1
@Nacht İşlem bir tanımlayıcı içerir, ancak çekirdek tüm eşlemeyi yapar (tanımlayıcı / dosya tabloları girişleri / inode). Ve aslında, dahili olarak, çekirdek yolları saklamaz (çünkü ilginç şeyler yolun değil, inode'dadır). Ayrıca, bir "yol" bir dosyaya sadece bir bağlantıdır ... birkaç tane olabilir :)
John WH Smith

oh doğru bir tanımlayıcı var. yani bash sürekli çalışma dizini bir fd tutar? elbette tüm süreçlerin çalışma dizinin fds var ... i stdin / out / err sonra 3 değerinden başlayan fds hatırladı düşündüm
Nacht - Reastate Monica

2
@Nacht Geçerli dizin bir dosya tanımlayıcı değil, birine çok benzer. Çekirdek her işlem için bunu korur. Linux'ta, bunu da görebileceğiniz /proc/<pid>/cwdgibi çalışır, hangi /proc/<pid>/fd/<number>. Bu CWDçıktı lsof.
Gilles 'SO- kötü olmayı bırak'

cd - && cd -böyle bir durumda otomatik yapmak mümkün mü?
Vitaly Zdanevich

8

Yeni dizin A, dizin A ile aynı değildir. statEskisini silmeden önce ve yenisini oluşturduktan sonra komutla kontrol edilebilir ve farklı i-düğüm numaraları göreceksiniz.
Bence bu çekirdeğin nasıl çalıştığıyla ilgili. Her işlem için geçerli dizinin i numarasını izler. Farklı i-sayıları olduğundan, bu farklı çarpışmalara yol açacaktır.


Bir inodeun benzersiz bir sayı değil, bir yapı olduğu unutulmamalıdır. Benzersiz bir şekilde tanımlanabilir, ancak kimliğinden daha fazla bilgi tutar. Bağlantılardan daha önemli kılan da budur.
John WH Smith

1
@JohnWHSmith Gilles daha iyi olduğu için bu cevabı sileceğim.
taliezin

6
Sizinkini silmek için hiçbir sebep yok! Bu şekilde hissediyorsanız, yanıtınıza diğerini daha iyi düşündüğünüzü açıklayan bir sorumluluk reddi beyanı ekleyebilirsiniz.
terdon

7

Bu beklenen davranıştır. Yeni A dizini, eski A dizini ile aynı değildir, sadece aynı ada sahip olur. Yani ilk terminalin $ PWD hala gitti, bunu yaptığınızda sihirli bir şekilde yeniden görünmedi mkdir A.


2
'yeni A dizini' eski dizin A ile aynı değildir 'hakkında ayrıntılı bilgi verebilir misiniz? Dosyanın / dizinin hangi yönleri değişir? İnode numarası ile ilgisi var mı? Sormak için üzgünüm, ama sadece bunu öğreniyorum.
rahul

2
@rahul Felsefi olarak kimliğinin değişmesi - aynı konumda hiçbir şeyden yeni bir dizin yaratıldı. Uygulama düzeyinde, evet, tüm açık dosyalar inode ile tanımlanır ve eski ve yeni dizinlerin farklı inode numaralarına sahip farklı inodeları olacaktır.
ocaklar

0

Bir dizinde, bir dosya gibi, onunla ilişkilendirilmiş bir inode vardır:

307% mkdir ABC

308% ls -i 11997708 A 11997709 B 11997710 C

Bir inode, dizin veya dosya hakkında bilgi içeren bir veri yapısıdır. Her dizinde ve dosyada bir tane vardır. Bir adres olarak düşünün (gerçekten bir dizin numarası).

A, 11997708 inode numarası ve başka bir kabuk (veya ben yapacağım gibi aynı kabukta) iseniz ben A dizinini silin sonra yeniden oluşturun ve inot:

% 309 cd A

% 310 rmdir ../A

% 311 mkdir ../A

% 312 ls -i ..

11997720 A 11997709 B 11997710 C

İ düğümü farklıdır, bu nedenle silinen A dizininde bir dosya oluşturmaya çalışırsa:

% 313 buna dokun

dokunma: 'buna' dokunamaz: Böyle bir dosya veya dizin yok

çünkü ben - içinde bulunduğum dizin artık 11997720 inode ile ilişkili değil - bu yüzden şu anda nerede olduğum artık meşru bir adres / dizin - inode. Böylece hata.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.