помилка `ls` при видаленні каталогу


13

У мене відкриті дві снаряди. Перший знаходиться в каталозі А. У другому я видаляю каталог А, а потім відтворюю його. Коли я повертаюся до першої оболонки та ввожу ls, вихід:

ls: cannot open directory .: Stale file handle

Чому? Я думав, що перша оболонка (та, яка залишилася відкритою всередині неіснуючого каталогу) "заморозиться" під час очікування наступної команди, і не зрозуміла б, що каталог видалено та відтворено. Чи містить оболонка "глибше" посилання на її поточний робочий каталог, відмінний від рядка $PWD?


2
Невідповідь, але якщо ви просто хочете, щоб ваша оболонка опустилася на ноги, можете бігти cd $PWD.
даг

Я хотів би зрозуміти, що відбувається, я знаю, що легко повернути шкаралупу :)
fonini

Це каталог на сервері NFS? Я думаю, що це єдина ситуація, коли ви отримуєте застарілі ручки файлів.
Бармар

Каталог локальний. Коли ви робите це у своїй системі, результат відрізняється?
fonini

Відповіді:


17

Каталог (як і будь-який файл) не визначається його іменем. Подумайте про те , як ім'я самого каталогу адреса . Коли ви переміщуєте каталог, це все той же каталог, як і якщо ви переїжджаєте в інший будинок, ви все одно та сама людина. Якщо ви видалите каталог і створите новий з тим же ім’ям, це новий каталог, як і хтось, хто переселяється в будинок, де ви жили раніше, чи не ви.

Кожен процес має робочий каталог . cdКоманди в оболонці змінює поточний робочий каталог оболонки. pwdКоманда друкує the¹ шлях до поточного робочого каталогу.

Коли ви видалили каталог 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.

¹ Точніше, шлях, який не може бути унікальним , якщо символічні посилання або інші тонкощі беруть участь.


Отже, ключовим моментом тут є те, що процес утримує inode свого робочого каталогу, а не лише шлях?
Нахт - Відновіть Моніку

1
@Nacht Процес містить дескриптор, але ядро ​​виконує всі відображення (записи дескриптора / файлових таблиць / inode). І справді, внутрішньо ядро ​​не зберігає шляхи (адже цікавий матеріал знаходиться в inode, а не в шляху). Крім того, "шлях" - це лише одне посилання на файл ... їх може бути декілька :)
Джон У. Сміт

ой правильно, він містить дескриптор. так що bash постійно містить FD робочого каталогу? напевно, не всі процеси мають FDS робочого каталогу ... Я думав, що я запам'ятав FDS, починаючи зі значення 3 після stdin / out / err
Nacht - Відновити Моніку

2
@Nacht Поточний каталог не є дескриптором файлів, але він працює дуже схоже на один. Ядро стверджує, що для кожного процесу. У Linux ви можете побачити його в /proc/<pid>/cwd, який працює як /proc/<pid>/fd/<number>. Це CWDна виході lsof.
Жил "ТАК - перестань бути злим"

cd - && cd -в такому випадку можна зробити автоматичну ?
Віталій Зданевич

8

Нова директорія A не є такою, як каталог А. Його можна перевірити за допомогою statкоманди перед видаленням старого та після створення нового, і ви побачите різні номери i-вузла.
І я думаю, це пов’язано з тим, як працює ядро. Він просто відстежує i-номер поточного каталогу для кожного процесу. Так як існують різні i-числа, це призведе до різних зіткнень.


Слід зазначити, що inode - це структура, а не унікальне число. Його можна однозначно ідентифікувати, але він містить більше інформації, ніж його ідентифікатор. Саме це робить його більш важливим, ніж посилання.
Джон У. Сміт

1
@JohnWHSmith Я хочу видалити цю відповідь, оскільки Гілз краще.
taliezin

6
Це не привід видаляти ваше! Якщо ви відчуваєте це так, можете просто додати відповідь на відмову у своїй відповіді, пояснюючи, що ви вважаєте інший кращим.
тердон

7

Це очікувана поведінка. Новий каталог A не є таким же, як старий каталог A, він просто має те ж ім’я. Таким чином, $ PWD першого терміналу все ще немає, він не чарівно з’явився, коли ви зробили це mkdir A.


2
Ви можете розробити "новий каталог A - це не те саме, що старий каталог A". Які аспекти файлу / каталогу змінюються? Це має відношення до числа inode? Вибачте, питаю, але я просто дізнаюся про це.
rahul

2
@rahul По-філософськи, зміна його ідентичності - новий каталог створений з нічого з того самого місця. На рівні реалізації, так, всі відкриті файли ідентифікуються за допомогою inode, і старий і новий каталоги матимуть різні вставки з різними номерами inode.
варення

0

У каталозі, як у файлі, з ним пов'язаний inode:

307% mkdir ABC

308% ls -i 11997708 A 11997709 B 11997710 C

Інода - це структура даних, яка містить інформацію про каталог або файл. Кожен каталог і файл має його. Подумайте про це як адресу (дійсно номер індексу).

Якщо я перебуваю в A, номер індексу 11997708 і в іншій оболонці (або в тій же оболонці, що я збираюся зробити), видаліть каталог A, то відтворіть його та позначте inode:

309% cd A

310% rmdir ../A

311% mkdir ../A

312% ls -i ..

11997720 А 11997709 Б 11997710 С

Вузол i інший, тому якщо він спробує створити файл у видаленому каталозі A:

313% торкаються цього

touch: не можна торкатися "цього": Немає такого файлу чи каталогу

тому що каталог, в якому я перебуваю - більше не асоціюється з inode 11997720 - тож там, де я зараз перебуваю, більше немає законної адреси / індексу - inode. Таким чином помилка.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.