Lỗi `ls` khi thư mục bị xóa


13

Tôi có hai vỏ mở. Đầu tiên là trong thư mục A. Trong lần thứ hai, tôi xóa thư mục A, và sau đó tạo lại nó. Khi tôi quay lại shell đầu tiên và gõ ls, đầu ra là:

ls: cannot open directory .: Stale file handle

Tại sao? Tôi nghĩ shell đầu tiên (cái vẫn mở trong thư mục không tồn tại) sẽ "đóng băng" trong khi chờ lệnh tiếp theo, và sẽ không "nhận ra" rằng thư mục đã bị xóa và được tạo lại. Shell có giữ một tham chiếu "sâu hơn" đến thư mục làm việc hiện tại của nó ngoài chuỗi $PWDkhông?


2
Không trả lời, nhưng nếu bạn chỉ đơn giản muốn chiếc vỏ của mình rơi lại trên đôi chân của nó, bạn có thể chạy cd $PWD.
dhag

Tôi muốn hiểu chuyện gì đang xảy ra, tôi biết thật dễ dàng để lấy lại vỏ :)
fonini

Là thư mục này trên một máy chủ NFS? Tôi nghĩ đó là tình huống duy nhất mà bạn có xử lý tập tin cũ.
Barmar

Thư mục là cục bộ. Khi bạn làm điều này trong hệ thống của bạn, kết quả là khác nhau?
fonini

Câu trả lời:


17

Một thư mục (giống như bất kỳ tệp nào) không được xác định bởi tên của nó. Hãy nghĩ về tên như địa chỉ của thư mục . Khi bạn di chuyển thư mục, nó vẫn là cùng một thư mục, giống như nếu bạn chuyển đến một ngôi nhà khác, bạn vẫn là cùng một người. Nếu bạn xóa một thư mục và tạo một thư mục mới cùng tên, thì đó là một thư mục mới, giống như một người nào đó chuyển đến ngôi nhà nơi bạn từng sống không phải là bạn.

Mỗi quá trình có một thư mục làm việc . Các cdlệnh trong shell thay đổi thư mục làm việc hiện hành của vỏ. Các pwdlệnh in the¹ đường dẫn đến thư mục làm việc hiện hành.

Khi bạn xóa thư mục A, điều này đã làm là xóa mục nhập cho A trong thư mục mẹ của nó. Bản thân thư mục A vẫn ở trong hệ thống tập tin, nhưng ở trạng thái tách rời, không có tên. Nó chưa bị xóa vì nó được sử dụng bởi một quá trình, cụ thể là lớp vỏ đầu tiên. Khi bạn thay đổi thư mục trong shell đầu tiên, thư mục cuối cùng đã bị xóa. Điều tương tự cũng xảy ra khi một tệp bị xóa trong khi một quá trình vẫn mở: mục nhập thư mục của tệp bị xóa ngay lập tức và chính tệp đó sẽ bị xóa khi ngừng sử dụng.

Tương tự, quan sát những gì xảy ra khi bạn di chuyển các thư mục xung quanh.

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

Trong một vỏ khác:

mv one tmp
mv two one
mv tmp two

Trong vỏ đầu tiên:

ls

Các tập tin 1trong thư mục ban đầu được gọi onevà bây giờ được gọi two. Các tập tin 2trong thư mục ban đầu được gọi twovà bây giờ được gọi one.

¹ Chính xác hơn, một con đường, mà có thể không phải là duy nhất nếu liên kết tượng trưng hoặc sự tinh tế khác có liên quan.


Vì vậy, điểm quan trọng ở đây là một quá trình giữ nút inode của thư mục làm việc của nó, không chỉ là đường dẫn?
Nacht - Phục hồi Monica

1
@Nacht Quá trình giữ một bộ mô tả, nhưng hạt nhân thực hiện tất cả ánh xạ (mô tả / mục nhập bảng tệp / inode). Và thực tế, bên trong, kernel không lưu trữ các đường dẫn (bởi vì những thứ thú vị nằm trong inode chứ không phải đường dẫn). Ngoài ra, một "đường dẫn" chỉ là một liên kết đến một tệp ... có thể có một số :)
John WH Smith

oh phải nó giữ một mô tả. vì vậy bash liên tục giữ một fd của thư mục làm việc? chắc chắn không phải tất cả các tiến trình đều có fds của thư mục làm việc ... tôi nghĩ rằng tôi đã nhớ fds bắt đầu từ giá trị 3 sau stdin / out / err
Nacht - Rebstate Monica

2
@Nacht Thư mục hiện tại không phải là một mô tả tập tin, nhưng nó hoạt động rất giống như một. Hạt nhân duy trì điều đó cho mọi quá trình. Trên Linux, bạn có thể thấy nó /proc/<pid>/cwdhoạt động như thế nào /proc/<pid>/fd/<number>. Đó là CWDtrong đầu ra của lsof.
Gilles 'SO- ngừng trở nên xấu xa'

Có thể làm tự động cd - && cd -trong trường hợp như vậy?
Vitaly Zdanevich

8

Thư mục mới A không giống với thư mục A. Nó có thể được kiểm tra bằng statlệnh trước khi xóa thư mục cũ và sau khi tạo thư mục mới và bạn sẽ thấy các số nút i khác nhau.
Và tôi nghĩ điều này có liên quan đến cách thức hoạt động của kernel. Nó chỉ đơn giản là theo dõi số i của thư mục hiện tại cho mỗi quá trình. Vì vậy, khi có các số i khác nhau, điều này sẽ dẫn đến các va chạm khác nhau.


Cần lưu ý rằng một nút là một cấu trúc, không phải là một số duy nhất. Nó có thể được xác định duy nhất, nhưng nó chứa nhiều thông tin hơn ID của nó. Đây là những gì làm cho nó quan trọng hơn các liên kết.
John WH Smith

1
@JohnWHSmith Tôi sẽ xóa câu trả lời này vì Gilles là tốt hơn.
Taliezin

6
Đó không phải là lý do để xóa của bạn! Nếu bạn cảm thấy như vậy, bạn có thể thêm từ chối trách nhiệm vào câu trả lời của bạn giải thích rằng bạn xem xét người khác tốt hơn.
terdon

7

Đây là hành vi dự kiến. Thư mục mới A không giống với thư mục A cũ, nó chỉ có cùng tên. Vì vậy, $ PWD của thiết bị đầu cuối vẫn không còn, nó không xuất hiện lại một cách kỳ diệu khi bạn thực hiện mkdir A.


2
bạn có thể giải thích về 'thư mục mới A không giống với thư mục cũ A'. Những khía cạnh của các tập tin / thư mục thay đổi? Nó có phải làm với số inode không? Xin lỗi để hỏi, nhưng tôi chỉ học về điều này.
rahul

2
@rahul Về mặt triết học, những gì thay đổi là danh tính của nó - một thư mục mới đã được tạo từ không có gì ở cùng một vị trí. Ở cấp độ triển khai, có, tất cả các tệp đang mở được xác định bằng inode và các thư mục cũ và mới sẽ có các nút riêng biệt với các số inode khác nhau.
hobbs 15/05/2015

0

Một thư mục, giống như một tập tin, có một nút liên kết với nó:

307% mkdir ABC

308% ls -i 11997708 A 11997709 B 11997710 C

Inode là cấu trúc dữ liệu chứa thông tin về thư mục hoặc tệp. Mỗi thư mục và tập tin có một. Hãy nghĩ về nó như một địa chỉ (một số chỉ số thực sự).

Nếu tôi ở A, số inode 11997708 và trong một shell khác (hoặc trong cùng một shell như tôi sẽ làm) xóa thư mục A sau đó tạo lại nó và lode inode:

309% cd A

310% rmdir ../A

311% mkdir ../A

312% ls -i ..

11997720 A 11997709 B 11997710 C

Nút i là khác nhau, vì vậy nếu nó cố gắng tạo một tệp trong thư mục đã xóa A:

313% chạm vào cái này

chạm: không thể chạm vào 'this': Không có tệp hoặc thư mục như vậy

bởi vì thư mục tôi đang ở - không còn được liên kết với inode 11997720 - vì vậy nơi tôi hiện không còn có địa chỉ / chỉ mục hợp pháp - inode. Như vậy là lỗi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.