ข้อผิดพลาด `ls` เมื่อลบไดเรกทอรี


13

ฉันมีกระสุนสองนัดที่เปิดอยู่ สิ่งแรกคือในไดเรกทอรี A. ในวินาทีฉันลบไดเรกทอรี A แล้วสร้างใหม่ เมื่อฉันกลับไปที่เชลล์ตัวแรกและพิมพ์lsเอาต์พุตคือ:

ls: cannot open directory .: Stale file handle

ทำไม? ฉันคิดว่าเชลล์แรก (อันที่ยังคงเปิดอยู่ในไดเรกทอรีที่ไม่มีอยู่) จะ "หยุด" ในขณะที่รอคำสั่งถัดไปและจะไม่ "รู้" ว่าไดเรกทอรีนั้นถูกลบและสร้างใหม่ เชลล์เก็บการอ้างอิง "ที่ลึกกว่า" ไปยังไดเร็กทอรีการทำงานปัจจุบันนอกเหนือจากสตริง$PWDหรือไม่?


2
ไม่ใช่คำตอบ แต่ถ้าคุณต้องการให้เปลือกของคุณหล่นลงมาคุณสามารถวิ่งcd $PWDได้
dhag

ฉันต้องการที่จะเข้าใจสิ่งที่เกิดขึ้นผมรู้ว่ามันเป็นเรื่องง่ายที่จะได้รับเปลือกกลับ :)
fonini

ไดเร็กทอรีนี้อยู่บนเซิร์ฟเวอร์ NFS หรือไม่? ฉันคิดว่าเป็นสถานการณ์เดียวที่คุณได้รับการจัดการไฟล์เก่า
Barmar

ไดเรกทอรีเป็นท้องถิ่น เมื่อคุณทำสิ่งนี้ในระบบของคุณผลลัพธ์จะแตกต่างกันอย่างไร
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อยู่ในไดเรกทอรีที่ แต่เดิมเรียกว่าและถูกเรียกว่าตอนนี้twoone

¹ อย่างแม่นยำมากขึ้นเส้นทางซึ่งอาจจะไม่ซ้ำกันถ้าการเชื่อมโยงสัญลักษณ์หรือรายละเอียดปลีกย่อยอื่น ๆ ที่เกี่ยวข้อง


ดังนั้นจุดสำคัญที่นี่คือกระบวนการเก็บ inode ของไดเรกทอรีการทำงานไม่ใช่แค่เส้นทาง?
Nacht - Reinstate Monica

1
@Nacht กระบวนการเก็บ descriptor แต่เคอร์เนลทำการแม็พทั้งหมด (descriptor / file tables entry / inode) และที่จริงแล้วภายในเคอร์เนลไม่ได้จัดเก็บเส้นทาง (เพราะสิ่งที่น่าสนใจอยู่ในไอโหนดไม่ใช่เส้นทาง) นอกจากนี้ยังมี"เส้นทาง"เป็นเพียงการเชื่อมโยงไปยังแฟ้ม ... อาจจะมีหลาย :)
จอห์นสมิ ธ WH

โอ้ถูกต้องมันมี descriptor ดังนั้นทุบตีอย่างต่อเนื่องถือ fd ของไดเรกทอรีทำงานหรือไม่ กระบวนการทั้งหมดไม่แน่นอนมี fds ของไดเรกทอรีการทำงาน ... ฉันคิดว่าฉันจำ fds เริ่มต้นที่ค่า 3 หลังจาก stdin / out / err
Nacht - Reinstate Monica

2
@Nacht ไดเรกทอรีปัจจุบันไม่ใช่ตัวให้คำอธิบายไฟล์ แต่มันทำงานได้เหมือนหนึ่งอย่างมาก เคอร์เนลรักษาไว้สำหรับทุกกระบวนการ บน Linux คุณสามารถเห็นมันในที่ทำงานเช่น/proc/<pid>/cwd /proc/<pid>/fd/<number>มันเป็นในการส่งออกของCWD lsof
Gilles 'หยุดความชั่วร้าย'

เป็นไปได้ไหมที่จะสร้างอัตโนมัติcd - && cd -ในกรณีเช่นนี้?
Vitaly Zdanevich

8

ไดเร็กทอรีใหม่ A ไม่เหมือนกับไดเร็กทอรี A สามารถตรวจสอบได้ด้วยstatคำสั่งก่อนลบอันเก่าและหลังการสร้างใหม่และคุณจะเห็นหมายเลข i-node ที่แตกต่างกัน
และฉันคิดว่านี่เกี่ยวข้องกับการทำงานของเคอร์เนล มันเพียงแค่ติดตาม i-number ของไดเรกทอรีปัจจุบันสำหรับแต่ละกระบวนการ ดังนั้นเนื่องจากมีหมายเลข i ที่แตกต่างกันสิ่งนี้จะนำไปสู่การชนที่แตกต่างกัน


ควรสังเกตว่า inode เป็นโครงสร้างไม่ใช่จำนวนเฉพาะ สามารถระบุได้โดยไม่ซ้ำกัน แต่มีข้อมูลมากกว่า ID ของมัน นี่คือสิ่งที่ทำให้สำคัญกว่าลิงก์
John WH Smith

1
@JohnWHS ฉันกำลังจะลบคำตอบนี้เนื่องจาก Gilles one ดีกว่า
taliezin

6
นั่นคือเหตุผลที่จะลบของคุณไม่มี! หากคุณรู้สึกเช่นนั้นคุณสามารถเพิ่มข้อจำกัดความรับผิดชอบในคำตอบของคุณเพื่ออธิบายว่าคุณพิจารณาอีกข้อหนึ่งได้ดีกว่า
terdon

7

นี่เป็นพฤติกรรมที่คาดหวัง ไดเรกทอรีใหม่ A นั้นไม่เหมือนกับไดเรกทอรีเก่า แต่เกิดขึ้นกับชื่อเดียวกัน ดังนั้นสถานีแรกของ $ PWD mkdir Aจะหายไปก็ยังไม่ได้เกิดขึ้นอีกครั้งอย่างน่าอัศจรรย์เมื่อคุณทำ


2
คุณสามารถอธิบายรายละเอียดใน 'ไดเรกทอรีใหม่ A ไม่เหมือนกับไดเรกทอรีเก่า A' หรือไม่ ไฟล์ / ไดเรกทอรีเปลี่ยนแปลงด้านใดบ้าง? มันเกี่ยวข้องกับหมายเลขไอโหนดหรือไม่? ขออภัยที่จะถาม แต่ฉันเพิ่งเรียนรู้เกี่ยวกับเรื่องนี้
ราหุล

2
@hahul ในเชิงปรัชญาสิ่งที่เปลี่ยนแปลงคือตัวตนของมัน- ไดเรกทอรีใหม่ได้ถูกสร้างขึ้นจากสิ่งใดในสถานที่เดียวกัน ที่ระดับการนำไปปฏิบัติใช่ไฟล์ที่เปิดทั้งหมดจะถูกระบุโดย inode และไดเรกทอรีเก่าและใหม่จะมี inode ที่แตกต่างกันและมีหมายเลข inode ที่แตกต่างกัน
ฮอบส์

0

ไดเรกทอรีเช่นเดียวกับไฟล์มี inode ที่เกี่ยวข้อง:

ABC 307%

308% ls -i 11997708 A 11997709 B 11997710 C

inode เป็นโครงสร้างข้อมูลที่มีข้อมูลเกี่ยวกับไดเรกทอรีหรือไฟล์ ทุกไดเรกทอรีและไฟล์มีหนึ่ง คิดว่าเป็นที่อยู่ (หมายเลขดัชนีจริง ๆ )

หากฉันอยู่ใน A หมายเลข inode 11997708และในเชลล์อื่น (หรือในเชลล์เดียวกันกับที่กำลังจะทำ) ลบไดเร็กทอรี A จากนั้นสร้างใหม่และ ls inode:

309% cd A

310% rmdir ../A

311% mkdir ../A

312% ls -i ..

11997720 A 11997709 B 11997710 C

โหนด i แตกต่างกันดังนั้นหากพยายามสร้างไฟล์ในไดเรกทอรีที่ลบ A:

313% แตะสิ่งนี้

touch: ไม่สามารถแตะ 'this': ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว

เพราะไดเรกทอรีที่ฉันเข้า - ไม่มีความเกี่ยวข้องกับ inode 11997720อีกต่อไป ดังนั้นที่ปัจจุบันฉันไม่มีที่อยู่ / ดัชนีที่ถูกต้อง - inode ดังนั้นข้อผิดพลาด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.