Bagaimana cara menemukan file besar yang telah dihapus tetapi masih terbuka di aplikasi? Bagaimana seseorang dapat menghapus file seperti itu, meskipun suatu proses membuatnya terbuka?
Situasinya adalah bahwa kami menjalankan proses yang mengisi file log pada tingkat yang luar biasa. Saya tahu alasannya, dan saya bisa memperbaikinya. Sampai saat itu, saya ingin rm atau mengosongkan file log tanpa mematikan proses.
Cukup melakukan rm output.log
hanya menghapus referensi ke file, tetapi terus menempati ruang pada disk hingga proses dihentikan. Lebih buruk lagi: setelah rm
ing saya sekarang tidak punya cara untuk menemukan di mana file itu atau seberapa besar itu! Apakah ada cara untuk menemukan file, dan mungkin mengosongkannya, meskipun masih terbuka dalam proses lain?
Saya secara khusus merujuk ke sistem operasi berbasis Linux seperti Debian atau RHEL.
sumber
lsof -p <pid>
untuk daftar file yang terbuka dan ukurannya. File yang dihapus akan memiliki di(deleted)
sebelahnya. File yang dihapus mungkin ditautkan pada/proc/<pid>/fd/1
. Saya tidak tahu bagaimana membuat proses berhenti menulis ke deskriptor file tanpa menghentikannya. Saya pikir itu akan tergantung pada prosesnya.rm
file ed yang masih terbuka?lsof | grep "(deleted)"
. Ketika tidak ada lagi proses menahan file yang dihapus terbuka, kernel akan membebaskan blok inode dan disk. Proses tidak memiliki "penangan" di mana mereka dapat diberitahu bahwa file yang terbuka, pada dasarnya terkunci, telah dihapus dari disk.lsof | grep '(deleted)'
bekerja di Linux juga. Di Linux, Anda dapat diberitahu tentang penghapusan file (bahkan file yang sudah tidak memiliki entri di direktori apa pun selain / proc / some-pid / fd lagi) dengan mekanisme inotify (acara IN_DELETE_SELF)somefile
dan membukanya di VIM, lalurm
mengeditnya di proses bash lain. Saya kemudian jalankanlsof | grep somefile
dan tidak ada di sana, meskipun file terbuka di VIM.Jawaban:
Jika Anda tidak dapat mematikan aplikasi Anda, Anda dapat memotong alih-alih menghapus file log untuk mendapatkan kembali ruang tersebut. Jika file tidak terbuka dalam mode append (with
O_APPEND
), maka file akan muncul sebesar sebelum waktu berikutnya aplikasi menulis ke sana (meskipun dengan bagian terkemuka jarang dan tampak seolah-olah berisi NUL byte), tetapi ruang akan telah direklamasi (yang tidak berlaku untuk sistem file HFS + di Apple OS / X yang tidak mendukung file jarang).Untuk memotongnya:
Jika sudah dihapus, di Linux, Anda masih dapat memotongnya dengan melakukan:
Di mana
$pid
id proses dari proses yang memiliki file dibuka, dan$fd
satu deskriptor file itu dibuka di bawah (yang dapat Anda periksa denganlsof -p "$pid"
.Jika Anda tidak tahu pid, dan sedang mencari file yang dihapus, Anda dapat melakukan:
lsof -nP +L1
, seperti yang disebutkan oleh @ user75021 adalah opsi yang lebih baik (lebih dapat diandalkan dan lebih portabel) (daftar file yang memiliki kurang dari 1 tautan).Atau (di Linux):
Atau untuk menemukan yang besar dengan
zsh
:Alternatif, jika aplikasi terhubung secara dinamis adalah melampirkan debugger ke sana dan membuatnya memanggil
close(fd)
diikuti oleh yang baruopen("the-file", ....)
.sumber
truncate
perintah yang melakukan hal yang sama secara lebih eksplisit.lsof
mungkin akan menjadi yang paling dekat dengan solusi portabel yang bisa Anda dapatkan dari daftar file yang terbuka. pendekatan debugger untuk menutup fd di bawah kaki aplikasi juga harus cukup portabel.df -k | awk 'NR>1 { print $NF }' | xargs fuser -Vud
(dan kemudian mudah mengirim sinyal kepada pelanggar untuk memaksa mereka melepaskan fd)lsof +L1
. Dari halaman manual lsof: "Spesifikasi formulir+L1
akan memilih file terbuka yang telah dibatalkan tautannya. Spesifikasi formulir+aL1 <file_system>
akan memilih file terbuka yang tidak terkait pada sistem file yang ditentukan.". Itu seharusnya sedikit lebih dapat diandalkan daripada grepping.Lihat mulai cepat di sini:
lsof
Mulai cepatSaya terkejut tidak ada yang menyebutkan file quickstart lsof (termasuk dengan lsof). Bagian "3.a" menunjukkan cara menemukan file yang terbuka dan tidak ditautkan:
Misalnya:
Pada sistem Red Hat untuk menemukan salinan lokal dari file mulai cepat, saya biasanya melakukan ini:
... atau ini:
sumber
Terserah driver sistem file untuk benar-benar membebaskan ruang yang dialokasikan, dan itu biasanya akan terjadi hanya setelah semua deskriptor file yang merujuk ke file tersebut dirilis. Jadi Anda tidak dapat benar-benar mendapatkan kembali ruang, kecuali jika Anda membuat aplikasi menutup file. Yang berarti mengakhiri atau bermain dengannya "sedikit" dalam debugger (mis. Menutup file dan memastikan itu tidak dibuka / ditulis lagi, atau dibuka
/dev/null
sebagai gantinya). Atau Anda bisa meretas kernel, tetapi saya menyarankan untuk tidak melakukannya.Memotong file seperti yang disarankan Stephane mungkin membantu, tetapi hasil sebenarnya juga akan bergantung pada sistem file Anda (misalnya blok pra-alokasi kemungkinan akan dibebaskan hanya setelah Anda menutup file dalam kasus apa pun).
Alasan di balik perilaku ini adalah bahwa kernel tidak akan tahu apa yang harus dilakukan dengan permintaan data (baik membaca dan menulis, tetapi membaca sebenarnya lebih penting) menargetkan file seperti itu.
sumber
fallocate
di Linux 4.9. Bisakah Anda mengklarifikasi di bawah sistem file apa dan kondisi pemotongan file tidak merebut kembali ruang?