Cara Pulihkan Fail Terpadam rm -rf di Linux
Terlanjur jalankan rm -rf pada direktori yang salah? Hentikan penulisan ke cakera serta-merta dan ikuti langkah pemulihan data ext4 yang selamat untuk mengelakkan data tertindih.
Apa yang perlu dilakukan dalam enam puluh saat pertama
Dua perkara menentukan sama ada anda boleh mendapatkan semula fail yang dipadam dengan rm -rf, dan kedua-duanya berlaku sebelum anda membuka enjin carian. Berhenti menulis ke sistem fail tersebut. Kemudian, hentikan penggunaannya dengan menyahlekap (unmount) atau memasang semula (remount) dalam mod baca sahaja (read-only).
rm tidak memadam apa-apa. Ia membuang entri direktori, kemudian menandakan inode dan blok data fail tersebut sebagai bebas. Bait-bait data masih berada pada peranti. Ia kekal di sana sehingga pengumpuk blok (block allocator) memberikan blok tersebut kepada proses lain dan proses itu menulis data baharu di atasnya. Setiap saat sistem fail kekal dipasang dan sibuk, daemon akan menulis baris log atau pangkalan data akan membuang halaman, dan mana-mana penulisan boleh menimpa blok yang anda ingin dapatkan semula.
Oleh itu, arahan pertama yang perlu dijalankan adalah arahan yang menghentikan penulisan, bukan arahan yang memulihkan fail.
sudo systemctl stop nginx postgresql
sudo umount /mnt/dataJika umount menjawab umount: /mnt/data: target is busy., cari proses yang memegang sistem fail tersebut.
sudo fuser -vm /mnt/data
sudo lsof +D /mnt/dataJika anda tidak dapat membebaskannya, pasang semula dalam mod baca sahaja. Pemasangan baca sahaja menghentikan peruntukan baharu, yang merupakan perkara utama yang anda perlukan.
sudo mount -o remount,ro /mnt/dataJika laluan yang dipadam berada pada sistem fail root, ini lebih sukar. sudo mount -o remount,ro / biasanya akan gagal dengan mount: /: cannot remount /dev/vda1 read-only., kerana proses yang sedang berjalan memegang fail untuk penulisan dan kernel tidak akan memaksa proses tersebut ditutup. Pada VPS, jawapan praktikalnya ialah mod penyelamat atau pemulihan pembekal anda: ia memulakan sistem live berasingan dengan cakera anda dilampirkan tetapi tidak dipasang. Setiap arahan di bawah kemudiannya dijalankan terhadap peranti yang tidak ditulis oleh sesiapa.
Satu peraturan terpakai untuk keseluruhan panduan ini. Jangan sekali-kali menulis fail yang dipulihkan, imej cakera, atau alat yang baru dipasang ke dalam sistem fail yang anda sedang pulihkan. Lampirkan volum kedua, atau hantar output ke mesin lain melalui SSH.
Mengapa pemulihan rm -rf pada ext4 kebanyakannya sia-sia
Tetapkan jangkaan anda sebelum memasang apa-apa. Sahkan sistem fail yang anda gunakan:
lsblk -fPada ext4, yang merupakan lalai bagi hampir setiap imej VPS, lokasi data fail disimpan dalam inode sebagai pokok extent. Satu extent ialah rekod yang menyatakan bahawa blok logik N bagi fail ini bermula pada blok fizikal M dan berlanjutan selama L blok. Fail kecil menyimpan sehingga empat rekod tersebut di dalam inode itu sendiri. Fail yang lebih besar menunjuk kepada blok tambahan yang memegang baki pokok tersebut.
Apabila pautan terakhir kepada sesuatu fail hilang, ext4 akan menyusuri pokok tersebut, memulangkan setiap extent kepada penguntuk blok (block allocator), dan mengosongkan pokok daripada inode. Inode tersebut kemudian ditandakan sebagai bebas dan dicap dengan masa pemadaman. Data itu sendiri tidak disentuh. Satu-satunya rekod tentang di mana data itu berada telah dipadamkan.
Itulah perbezaannya dengan ext3, di mana inode yang dipadamkan menyimpan maklumat yang mencukupi untuk alat seperti ext3grep menjejakinya. Anda masih boleh menyenaraikan inode yang dipadamkan pada ext4:
sudo debugfs -R lsdel /dev/vdb1debugfs membuka peranti dalam mod baca sahaja melainkan anda memberikan -w, jadi ini selamat dilakukan pada peranti yang tidak dilekapkan (unmounted) dan tiada kos untuk mencubanya. Inode akan disenaraikan. Proses berakhir setakat memaparkan kandungan inode, kerana peta blok yang pernah dipegang oleh inode tersebut telah dikosongkan, jadi dump tidak mempunyai maklumat untuk dijejaki.
Dua alat cuba mengatasi masalah ini dengan membaca jurnal. Jurnal ialah gelang bersaiz tetap yang digunakan oleh ext4 untuk memastikan metadata konsisten sekiranya berlaku kerosakan, dan ia mungkin masih menyimpan salinan inode yang lama sebelum pemadaman berlaku. extundelete dan ext4magic kedua-duanya mencari di dalamnya. Semak saiz yang anda sedang gunakan:
sudo dumpe2fs -h /dev/vdb1 | grep -i journalJurnal hanya menyimpan metadata dan saiznya kecil, jadi aktiviti penulisan biasa akan melaluinya dengan pantas. Pada pelayan yang sedang berjalan, tempoh masa di mana inode sebelum pemadaman masih wujud diukur dalam beberapa minit sahaja. Kedua-dua alat ini tidak diselenggara secara aktif, dan kedua-duanya tidak dipakejkan dalam setiap pengedaran. Anggap kedua-duanya sebagai usaha terakhir, jalankannya pada peranti yang tidak dilekapkan atau pada imej cakera, dan jangan terkejut jika ia tidak menemui apa-apa.
Jika lsblk -f melaporkan xfs, keadaannya tidak lebih baik, kerana tiada fungsi nyahpadam (undelete) yang disokong untuk XFS juga. Urutan pilihan di bawah tidak berubah.
Adakah fail masih dibuka dalam proses yang sedang berjalan?
Ini merupakan satu-satunya kaedah pemulihan pada halaman ini yang mempunyai peluang kejayaan tinggi, dan inilah sebab mengapa anda tidak seharusnya memulakan semula servis yang sedang menggunakan fail tersebut.
Sesuatu fail hanya benar-benar hilang apabila dua kiraan mencapai sifar: bilangan entri direktori yang menghala ke inode fail tersebut, dan bilangan deskriptor fail yang terbuka. rm menjadikan kiraan pertama kepada sifar. Jika sesuatu proses masih memegang fail tersebut dalam keadaan terbuka, kiraan kedua tidak menjadi sifar, maka inode dan blok datanya masih diperuntukkan dan data tersebut masih boleh dibaca.
Cari fail terbuka yang kiraan pautannya telah jatuh kepada sifar:
sudo lsof +L1+L1 bermaksud senaraikan fail terbuka dengan kiraan pautan di bawah 1. Setiap padanan menunjukkan proses, nombor deskriptor fail, NLINK bagi 0, dan laluan yang berakhir dengan (deleted). Ambil PID dan nombor deskriptor tersebut untuk /proc:
sudo ls -l /proc/1234/fdSatu entri kelihatan seperti 3 -> /var/log/app/events.log (deleted). Pautan tersebut masih mencapai data berkenaan. Salin data itu keluar ke sistem fail yang berbeza:
sudo cp /proc/1234/fd/3 /mnt/rescue/events.logGunakan cp, bukan mv. Membuka /proc/1234/fd/3 memberikan anda pemegang (handle) baharu pada inode yang sama bermula dari offset sifar, jadi anda mendapat keseluruhan fail dan bukannya bahagian selepas kedudukan semasa penulis.
Terdapat dua had yang perlu diketahui. Pepohon direktori yang dipadam tidak boleh dikembalikan melalui cara ini, kerana hanya fail individu yang dibuka oleh sesuatu proses sahaja yang masih dipegang. Selain itu, fail pangkalan data yang disalin semasa enjin sedang dalam proses menulis merupakan salinan yang konsisten dengan ranap (crash-consistent), jadi rancang untuk menjalankan pemulihan enjin itu sendiri ke atasnya dan bukannya menganggap ia sebagai salinan yang bersih. Entri yang ditunjukkan oleh lsof dengan mem menggantikan nombor deskriptor adalah dipetakan ke memori (memory mapped), dan entri tersebut tidak mempunyai entri /proc/<pid>/fd untuk disalin.
Adakah anda mempunyai snapshot pada btrfs, ZFS atau LVM?
Jika sistem fail mengambil snapshot, fail yang dipadam sudah pun berada di dalam salah satu snapshot tersebut tanpa sebarang perubahan. Ini hanya membantu jika snapshot wujud sebelum pemadaman berlaku. Tiada apa-apa yang anda cipta sekarang boleh mengundur masa.
btrfs menyimpan snapshot sebagai subvolume:
sudo btrfs subvolume list /Layari snapshot tersebut dan salin laluan yang anda perlukan dengan cp -a. Utamakan penyalinan laluan tunggal berbanding melakukan rollback pada keseluruhan subvolume, kerana rollback juga akan membuang semua data yang ditulis sejak snapshot diambil.
ZFS mendedahkan setiap snapshot sebagai direktori baca-sahaja (read-only):
zfs list -t snapshot
ls /tank/data/.zfs/snapshot/Direktori .zfs adalah tersembunyi dan tidak akan muncul dalam ls biasa pada root dataset, tetapi anda boleh memasukinya dengan menaip namanya. Salin fail keluar dari situ. zfs rollback akan mengembalikan keseluruhan dataset dan memusnahkan setiap snapshot yang lebih baharu daripada snapshot yang anda namakan, jadi jadikan ia sebagai langkah terakhir.
Snapshot LVM adalah volum copy-on-write dengan saiz tetap:
sudo lvs
sudo mount -o ro /dev/vg0/data-snap /mnt/snapLekapkan (mount) ia sebagai baca-sahaja dan salin fail keluar. Periksa lvs sebelum anda mempercayainya, kerana snapshot LVM yang memenuhi ruang yang diperuntukkan akan dibatalkan oleh kernel, dan sebaik sahaja itu berlaku, kandungannya akan hilang.
Snapshot bukanlah sandaran (backup). Ia berada pada cakera atau pool yang sama dengan data asal, jadi ia berkongsi setiap kegagalan yang dialami oleh data asal. Ia sangat berkesan untuk membatalkan kesilapan yang berlaku dua minit yang lalu, yang sememangnya merupakan tujuan utama dalam situasi ini.
Pemulihan data dengan PhotoRec, gunakan imej dan jangan sekali-kali gunakan cakera sebenar
Jika tiada langkah di atas yang berkesan, pilihan terakhir ialah carving: mengimbas peranti mentah untuk mencari corak bait yang menandakan permulaan jenis fail yang diketahui, kemudian menulis keluar apa sahaja yang mengikutinya. Carving hanya membaca data fail. Nama fail, struktur direktori, cap masa dan pemilikan adalah metadata sistem fail, dan metadata itulah yang telah dimusnahkan oleh rm, jadi tiada satu pun daripadanya akan kembali. Anda akan mendapat fail yang dinamakan f0384512.jpg di dalam direktori output bernombor, dan anda perlu menyusunnya secara manual.
Dua peraturan menentukan sama ada kaedah ini berkesan.
Pertama, buat imej peranti tersebut sebelum anda melakukan apa-apa tindakan lain ke atasnya. Pada Debian dan Ubuntu, pakejnya ialah gddrescue dan binari yang dipasangnya ialah ddrescue.
sudo apt update && sudo apt install -y gddrescue testdisk
sudo ddrescue -n /dev/vdb1 /mnt/rescue/vdb1.img /mnt/rescue/vdb1.map/mnt/rescue mestilah berada pada peranti yang berbeza, dengan ruang kosong sekurang-kurangnya sama besar dengan saiz partition tersebut. lsblk -b memaparkan saiz tepat dalam bait. Fail peta membolehkan salinan yang terganggu disambung semula dan bukannya bermula dari awal. Sebaik sahaja anda mempunyai imej tersebut, anda boleh mencuba alat kedua kemudian terhadap bait yang sama, perkara yang tidak boleh dilakukan jika alat pertama menulis terus ke atas cakera.
Kedua, halakan alat pemulihan kepada fail imej tersebut.
sudo photorec /d /mnt/rescue/recup /mnt/rescue/vdb1.imgphotorec membuka menu teks. Pilih partition, kemudian jenis sistem fail, seterusnya tandatangan fail yang ingin dicari, dan akhir sekali direktori destinasi. Kecilkan senarai tandatangan tersebut kepada jenis fail yang benar-benar hilang sebelum anda bermula, kerana senarai lalai akan mencari segala-galanya dan memberikan anda puluhan ribu serpihan untuk ditapis.
testdisk, daripada pakej yang sama, mempunyai fungsi pemulihan failnya sendiri, dan ia hanya meliputi FAT, exFAT, NTFS dan ext2. Pada ext4, pilihan yang tinggal ialah photorec.
Jangkakan fail yang berpecah-pecah akan kembali dalam keadaan rosak. Carving mengandaikan blok fail adalah bersebelahan, jadi fail yang dipecahkan oleh penguntuk (allocator) di seluruh cakera sama ada akan dipasang semula dengan salah atau tidak dijumpai langsung. Fail media biasanya boleh dipulihkan dengan baik kerana ia mempunyai pengepala yang jelas. Teks biasa, konfigurasi dan kod sumber sukar dipulihkan dengan carving, kerana tiada tandatangan bait yang menandakan permulaan skrip shell.
Ruang kosong yang tersilap: bagaimana laluan yang salah dipadamkan
Hampir setiap kemalangan rm -rf berpunca daripada masalah shell. rm menerima senarai laluan dan memadamkan setiap satu secara bergilir-gilir. Ia tidak pernah mengetahui niat anda.
Kes klasik ialah satu ruang kosong:
rm -rf /home/deploy/app /old
rm -rf /home/deploy/app/oldBaris pertama mengandungi dua argumen. Ia memadamkan aplikasi tersebut, kemudian ia memadamkan /old. Jika /old tidak wujud, rm tidak mencetak apa-apa langsung, kerana -f menyekat ralat fail yang hilang. Keadaan senyap bukanlah pengesahan.
Bentuk kedua ialah pemboleh ubah tanpa tanda petik yang mengandungi ruang kosong:
dir="/srv/my app"
rm -rf $dirShell memisahkan nilai tersebut berdasarkan ruang putih, jadi rm menerima /srv/my dan app sebagai dua laluan yang berasingan. Jika ditulis sebagai rm -rf "$dir", ia dianggap sebagai satu laluan.
Bentuk ketiga ialah pemboleh ubah kosong, biasanya kerana arahan yang sepatutnya mengisinya telah gagal:
rm -rf "$TARGET"/*Dengan TARGET tidak ditetapkan (unset), ia dikembangkan menjadi rm -rf /*. GNU rm menolak bentuk kosong: rm -rf / mencetak rm: it is dangerous to operate recursively on '/' dan berhenti. Bentuk glob tidak mendapat perlindungan sedemikian, kerana shell menggantikan /* dengan senarai laluan peringkat atas yang sebenar sebelum rm sempat dijalankan, dan / bukanlah salah satu daripadanya, jadi mekanisme perlindungan tersebut tidak pernah diaktifkan.
Tabiat yang mencegah kesilapan seterusnya
- Petik setiap pemboleh ubah yang digunakan sebagai laluan. Tulis
"$dir"setiap kali, termasuk di dalam ujian dan gelung. - Gagal jika kosong.
rm -rf "${TARGET:?TARGET is not set}"/*menyebabkan shell berhenti dengan mesej anda sebelumrmbermula, apabilaTARGETtidak ditetapkan atau kosong. Letakkanset -euo pipefaildi bahagian atas mana-mana skrip yang melakukan pemadaman. - Tambahkan
--one-file-system. Ia memberitahurmuntuk melangkau mana-mana direktori yang berada pada sistem fail yang berbeza daripada argumen yang anda berikan, supaya pemadaman rekursif tidak boleh masuk ke dalam volum sandaran yang dilekapkan atau bind mount. - Jangan padam sebagai root. Akaun servis hanya boleh memusnahkan apa yang dimilikinya, yang merupakan hujah utama untuk menjalankan setiap servis sebagai pengguna tanpa keistimewaan sendiri. Jika anda tidak pasti apa yang boleh dicapai oleh akaun tertentu, membaca bit kebenaran dalam senarai ls menjawabnya dalam satu arahan.
- Cetak senarai sebelum anda bertindak ke atasnya. Dalam skrip, bina laluan,
printf '%s\n'laluan tersebut, baca output, kemudian padam pada pas kedua. - Pastikan arahan trash dalam capaian.
sudo apt install trash-climemberikan andatrash-put,trash-list,trash-restoredantrash-empty. Fail yang dipadam berpindah ke~/.local/share/Trash, dantrash-empty 30mengosongkan apa-apa yang lebih lama daripada tiga puluh hari.
Mengaliaskan rm kepada trash-put kedengaran seperti langkah seterusnya yang jelas, namun ia adalah satu perangkap. Alias tersebut melatih refleks yang gagal pada pelayan seterusnya yang tidak mempunyainya, dan alias tidak terpakai di dalam skrip, iaitu tempat berlakunya kesilapan yang mahal. Taip trash-put dengan sengaja sebaliknya.
Satu-satunya pemulihan yang sentiasa berkesan
Segala perkara di atas hanyalah satu kemungkinan. Sandaran (backup) bukanlah satu kemungkinan.
Dua perkara menjadikan sandaran itu nyata. Ia berjalan mengikut jadual tanpa perlu anda mengingatinya, dan anda pernah melakukan pemulihan daripadanya sekurang-kurangnya sekali. Repositori yang tidak pernah dipulihkan hanyalah satu kepercayaan, kerana faktor yang menjadikannya tidak berguna (laluan yang salah dalam senarai sertaan, atau kata laluan repositori yang tidak dicatat oleh sesiapa) hanya akan muncul pada hari anda memerlukannya.
Dengan restic, pemulihan hanya memerlukan dua arahan.
restic -r /srv/restic-repo snapshots
restic -r /srv/restic-repo restore latest --target /mnt/rescue --include /srv/appdataLakukan pemulihan ke dalam direktori kosong dan bukannya menimpa laluan asal, supaya anda boleh membandingkan kedua-duanya sebelum sebarang fail dipindahkan ke tempatnya. Menyediakan sandaran restic pada VPS merangkumi penyediaan repositori dan pemasa systemd yang menjalankannya.
Dengan Borg:
borg list /srv/borg-repo
borg extract /srv/borg-repo::daily-2026-08-08 srv/appdataLaluan di dalam arkib Borg disimpan tanpa garis miring (slash) di hadapan, jadi srv/appdata sepadan dan /srv/appdata tidak sepadan dengan apa-apa. borg extract menulis ke dalam direktori kerja semasa, jadi cd ke direktori sementara terlebih dahulu.
Jika anda masih belum memilih antara kedua-duanya, perbandingan restic dan Borg merangkumi penyahduplikasian (deduplication) dan repositori jenis append-only, iaitu ciri yang menghalang pelayan yang telah diceroboh daripada memadam sejarah sandarannya sendiri. Mana-mana alat adalah memadai. Jawapan yang salah ialah tidak menjalankan kedua-duanya.
Pelayan baharu adalah saat paling murah untuk menyediakan perkara ini, sebelum terdapat sebarang data yang berharga untuk hilang. Sepuluh minit pertama pada VPS baharu adalah tempat yang sesuai untuk tugasan ini, bersama-sama dengan penyediaan SSH dan firewall.
Kemudian, letakkan entri berulang dalam kalendar anda: pulihkan satu direktori daripada repositori ke dalam /tmp setiap bulan dan baca fail-fail tersebut. Tabiat tunggal itu lebih bernilai daripada setiap alat yang ada pada halaman ini.
FAQ
Bolehkah saya menyahpadam fail pada ext4?
Biasanya tidak. Apabila pautan terakhir kepada sesuatu fail hilang, ext4 akan mengosongkan extent tree daripada inode, jadi tiada rekod pada cakera yang menunjukkan di mana data tersebut disimpan. extundelete dan ext4magic mencari jurnal ext4 untuk salinan inode yang lebih lama, yang hanya membantu jika pemadaman berlaku beberapa minit yang lalu dan sistem fail tidak aktif sejak itu. Kedua-dua projek tersebut tidak lagi diselenggara secara aktif. Jalankan salah satu daripadanya terhadap peranti yang tidak dilekap (unmounted) atau imej cakera, jangan sekali-kali terhadap sistem fail yang sedang dilekap, dan periksa dahulu apa yang anda sedang kerjakan menggunakan sudo dumpe2fs -h /dev/vdb1 | grep -i journal.
Sesuatu servis masih membuka fail yang telah dipadam. Bolehkah saya mendapatkannya semula?
Ya, dan ini adalah senario terbaik. Selagi sesuatu proses memegang fail tersebut dalam keadaan terbuka, inode dan blok datanya kekal diperuntukkan, jadi data tersebut masih boleh dibaca. Jangan mulakan semula servis tersebut, kerana menutup deskriptor terakhir akan melengkapkan proses pemadaman. Jalankan sudo lsof +L1 untuk menyenaraikan fail terbuka dengan kiraan pautan 0, catatkan PID dan nombor deskriptor fail, kemudian salin melalui /proc dengan sudo cp /proc/1234/fd/3 /mnt/rescue/events.log. Tulis salinan tersebut ke sistem fail yang berbeza. Entri yang ditunjukkan dengan mem dan bukannya nombor deskriptor adalah dipetakan ke memori (memory mapped) dan tidak mempunyai laluan /proc/<pid>/fd untuk disalin.
Mengapa saya perlu membuat imej cakera dan bukannya menjalankan alat pemulihan terus padanya?
Kerana setiap alat perlu menulis outputnya di suatu tempat, dan penulisan ke sistem fail yang sedang anda pulihkan boleh menimpa blok bebas yang masih menyimpan data anda. Salin partition ke peranti berbeza terlebih dahulu dengan sudo ddrescue -n /dev/vdb1 /mnt/rescue/vdb1.img /mnt/rescue/vdb1.map, kemudian halakan photorec kepada fail imej tersebut. Imej itu juga membolehkan anda mencuba alat kedua kemudian pada bait yang sama persis, yang mustahil dilakukan sebaik sahaja sesuatu telah menulis ganti data asal.
Adakah rm -rf / masih memusnahkan sistem Linux?
Perintah asas tersebut tidak melakukannya. GNU rm menolaknya dan mencetak rm: it is dangerous to operate recursively on '/'. Bentuk yang berbahaya adalah yang datang melalui laluan lain. rm -rf "$TARGET"/* dengan TARGET yang tidak ditetapkan (unset) akan berkembang menjadi rm -rf /*, dan shell akan menyerahkan rm senarai direktori peringkat atas yang sebenar, yang mana tiada satu pun adalah /, jadi pelindung tersebut tidak pernah dicetuskan. Tulis "${TARGET:?TARGET is not set}" sebaliknya dan shell akan berhenti sebelum rm dijalankan.
Adakah snapshot sistem fail merupakan sandaran (backup)?
Tidak. Snapshot btrfs atau ZFS berada pada pool yang sama dengan data yang dilindunginya, jadi cakera yang gagal atau pool yang musnah akan menjejaskan kedua-duanya sekali gus. Snapshot LVM mempunyai masalah tambahan iaitu saiz yang tetap: sebaik sahaja ia penuh, kernel akan membatalkannya dan kandungannya hilang. Snapshot sangat baik untuk membatalkan pemadaman yang berlaku dua minit yang lalu. Untuk perkara lain, simpan repositori pada perkakasan yang berasingan.