Ошибка `ls` при удалении каталога


13

У меня есть две открытые оболочки. Первый находится в каталоге A. Во втором я удаляю каталог 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.

¹ Точнее, путь, который не может быть уникальным , если символические ссылки или другие тонкости участвуют.


Таким образом, ключевой момент здесь заключается в том, что процесс содержит индекс своего рабочего каталога, а не только путь?
Nacht - Восстановить Монику

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

о, верно, он содержит дескриптор. так bash постоянно держит fd рабочего каталога? конечно, не у всех процессов есть fds рабочего каталога ... я думал, что вспомнил fds, начинающийся со значения 3 после stdin / out / err
Nacht - Reinstate Monica

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

можно сделать автомат cd - && cd -в таком случае?
Виталий Зданевич

8

Новый каталог A отличается от каталога A. Его можно проверить с помощью statкоманды перед удалением старого и после создания нового, и вы увидите разные номера i-узлов.
И я думаю, что это связано с тем, как работает ядро. Он просто отслеживает i-номер текущего каталога для каждого процесса. Так как есть разные i-числа, это приведет к различным столкновениям.


Следует отметить, что индекс является структурой, а не уникальным числом. Он может быть однозначно идентифицирован, но содержит больше информации, чем его идентификатор. Это то, что делает его более важным, чем ссылки.
Джон У. С. Смит,

1
@JohnWHSmith Я собираюсь удалить этот ответ, так как Жиль один лучше.
Тализин

6
Это не причина, чтобы удалить ваш! Если вы чувствуете, что так, вы можете просто добавить отказ от ответственности в свой ответ, объясняя, что вы считаете другой лучше.
Terdon

7

Это ожидаемое поведение. Новый каталог A не совпадает со старым каталогом A, просто он имеет то же имя. Таким образом, $ PWD первого терминала все еще не существует, он волшебным образом не появился, когда вы сделали mkdir A.


2
Не могли бы вы уточнить, что «новый каталог A не совпадает со старым каталогом A». Какие аспекты файла / каталога меняются? Это связано с номером инода? Извините, что спросил, но я только учусь об этом.
Рахул

2
@rahul Философски, что меняет его личность - новый каталог был создан из ничего в том же месте. На уровне реализации, да, все открытые файлы идентифицируются inode, а старые и новые каталоги будут иметь разные inode с разными номерами inode.
Хоббс

0

С каталогом, как и с файлом, связан индекс:

307% мкдр азбуки

308% ls -i 11997708 A 11997709 B 11997710 C

Inode - это структура данных, которая содержит информацию о каталоге или файле. Каждый каталог и файл имеет один. Думайте об этом как адрес (индексный номер действительно).

Если я нахожусь в A, инод номер 11997708 и в другой оболочке (или в той же оболочке, что и собираюсь) удалить каталог A, затем воссоздать его и ls индекс:

309% кд А

310% рмдир ../A

311% мкдир ../A

312% ls -i ..

11997720 A 11997709 B 11997710 C

Узел i отличается, поэтому, если он попытается создать файл в удаленном каталоге A:

313% касаются этого

Touch: не может коснуться «это»: нет такого файла или каталога

потому что каталог, в котором я нахожусь, больше не связан с индексом 11997720, поэтому там, где я в данный момент больше не имею допустимого адреса / индекса - индекс. Таким образом, ошибка.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.