Kesalahan `ls` saat direktori dihapus

13

Saya memiliki dua cangkang terbuka. Yang pertama adalah di direktori A. Di yang kedua, saya menghapus direktori A, dan kemudian membuatnya kembali. Ketika saya kembali ke shell pertama, dan ketik ls, outputnya adalah:

ls: cannot open directory .: Stale file handle

Mengapa? Saya pikir shell pertama (yang tetap terbuka di dalam direktori yang tidak ada) akan "membeku" sambil menunggu perintah berikutnya, dan tidak akan "menyadari" bahwa direktori itu dihapus dan diciptakan kembali. Apakah shell menyimpan referensi "lebih dalam" ke direktori kerjanya saat ini selain string $PWD?

fonini
sumber
2
Sebuah jawaban, tetapi jika Anda hanya ingin shell Anda jatuh kembali, Anda dapat berlari cd $PWD.
Dhag
Saya ingin memahami apa yang terjadi, saya tahu mudah untuk mendapatkan kembali shell :)
fonini
Apakah direktori ini di server NFS? Saya pikir itu satu-satunya situasi di mana Anda mendapatkan file basi.
Barmar
Direktori ini bersifat lokal. Ketika Anda melakukan ini di sistem Anda, hasilnya berbeda?
fonini

Jawaban:

17

Direktori (seperti file apa pun) tidak ditentukan oleh namanya. Pikirkan nama tersebut sebagai alamat direktori . Ketika Anda memindahkan direktori, itu masih direktori yang sama, seperti jika Anda pindah ke rumah yang berbeda, Anda masih orang yang sama. Jika Anda menghapus direktori dan membuat yang baru dengan nama yang sama, itu adalah direktori baru, sama seperti seseorang yang pindah ke rumah tempat Anda dulu tinggal bukan.

Setiap proses memiliki direktori yang berfungsi . The cdperintah di shell mengubah direktori kerja shell saat ini. The pwdperintah mencetak the¹ path ke direktori kerja saat ini.

Ketika Anda menghapus direktori A, yang dilakukan adalah menghapus entri untuk A di direktori induknya. Direktori A sendiri tetap berada di sistem file, tetapi dalam keadaan terpisah, tanpa nama. Itu belum dihapus karena sedang digunakan oleh suatu proses, yaitu shell pertama. Ketika Anda mengubah direktori di shell pertama, direktori itu akhirnya dihapus. Hal yang sama terjadi ketika file dihapus saat proses masih terbuka: entri direktori file segera dihapus, dan file itu sendiri dihapus ketika berhenti digunakan.

Demikian pula, amati apa yang terjadi ketika Anda memindahkan direktori.

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

Di shell lain:

mv one tmp
mv two one
mv tmp two

Di shell pertama:

ls

File 1ada di direktori yang awalnya dipanggil onedan sekarang dipanggil two. File 2ada di direktori yang awalnya dipanggil twodan sekarang dipanggil one.

¹ Lebih tepatnya, sebuah jalan, yang mungkin tidak unik jika link simbolik atau kehalusan lain yang terlibat.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
Jadi titik kunci di sini adalah bahwa suatu proses menyimpan inode dari direktori kerjanya, bukan hanya path?
Nacht - Pasang kembali Monica
1
@Nacht Proses ini memiliki deskriptor, tetapi kernel melakukan semua pemetaan (deskriptor / entri tabel file / inode). Dan memang, secara internal, kernel tidak menyimpan path (karena hal-hal menarik ada di inode, bukan path). Selain itu, "jalan" hanyalah satu tautan ke sebuah file ... mungkin ada beberapa :)
John WH Smith
oh benar itu memegang deskriptor. jadi bash terus memegang fd dari direktori kerja? pasti tidak semua proses memiliki fds dari direktori kerja ... saya pikir saya ingat fds mulai dari nilai 3 setelah stdin / out / err
Nacht - Reinstate Monica
2
@ Kapal Direktori saat ini bukan deskriptor file, tetapi berfungsi seperti ini. Kernel mempertahankannya untuk setiap proses. Di Linux, Anda bisa melihatnya di /proc/<pid>/cwd, yang berfungsi seperti /proc/<pid>/fd/<number>. Ada CWDdalam output dari lsof.
Gilles 'SANGAT berhenti menjadi jahat'
mungkin membuat otomatis cd - && cd -dalam kasus seperti itu?
Vitaly Zdanevich
8

Direktori baru A tidak sama dengan direktori A. Ini dapat diperiksa dengan statperintah sebelum menghapus yang lama dan setelah membuat yang baru dan Anda akan melihat nomor i-simpul yang berbeda.
Dan saya pikir ini terkait dengan cara kerja kernel. Itu hanya melacak nomor-i dari direktori saat ini untuk setiap proses. Jadi karena ada nomor-i yang berbeda, ini akan menyebabkan tabrakan yang berbeda.

taliezin
sumber
Perlu dicatat bahwa inode adalah struktur, bukan angka unik. Ini dapat diidentifikasi secara unik, tetapi memiliki lebih banyak informasi daripada ID-nya. Inilah yang membuatnya lebih penting daripada tautan.
John WH Smith
1
@ JohnWHSmith Saya akan menghapus jawaban ini karena Gilles satu lebih baik.
taliezin
6
Itu bukan alasan untuk menghapus milikmu! Jika Anda merasa seperti itu, Anda bisa menambahkan sanggahan untuk jawaban Anda yang menjelaskan bahwa Anda menganggap yang lain lebih baik.
terdon
7

Ini adalah perilaku yang diharapkan. Direktori baru A tidak sama dengan direktori lama A, kebetulan saja memiliki nama yang sama. Jadi $ PWD terminal pertama masih hilang, itu tidak secara ajaib muncul kembali ketika Anda melakukannya mkdir A.

John
sumber
2
dapatkah Anda menguraikan 'direktori baru A tidak sama dengan direktori lama A'. Aspek apa dari perubahan file / direktori? Apakah ini ada hubungannya dengan nomor inode? Maaf untuk bertanya, tapi saya baru belajar tentang ini.
rahul
2
@rahul Secara filosofis, perubahan apa itu identitasnya - direktori baru telah dibuat dari ketiadaan di lokasi yang sama. Pada tingkat implementasi, ya, semua file terbuka diidentifikasi oleh inode, dan direktori lama dan baru akan memiliki inode yang berbeda dengan nomor inode yang berbeda.
hobbs
0

Direktori, seperti file, memiliki inode yang terkait dengannya:

307% mkdir ABC

308% ls -i 11997708 A 11997709 B 11997710 C

Inode adalah struktur data yang berisi informasi tentang direktori atau file. Setiap direktori dan file memiliki satu. Anggap saja sebagai alamat (nomor indeks benar-benar).

Jika saya berada di A, nomor inode 11997708 dan di shell lain (atau di shell yang sama seperti yang akan saya lakukan) hapus direktori A kemudian buat kembali dan ls inode:

309% cd A

310% rmdir ../A

311% mkdir ../A

312% ls -i ..

11997720 A 11997709 B 11997710 C

Node saya berbeda, jadi jika mencoba membuat file di direktori yang dihapus A:

313% sentuh ini

sentuh: tidak dapat menyentuh 'ini': Tidak ada file atau direktori tersebut

karena direktori saya di - tidak lagi terkait dengan inode 11997720 - jadi di mana saya saat ini tidak lagi memiliki alamat / indeks - inode yang sah. Demikianlah kesalahannya.

pengguna2592248
sumber