Cara Memulihkan File yang Terhapus dengan rm -rf
Salah menjalankan rm -rf di ext4? Hentikan penulisan dan unmount disk segera, lalu ikuti opsi pemulihan yang benar sebelum blok data tertimpa.
Yang harus dilakukan dalam enam puluh detik pertama
Dua hal menentukan apakah Anda dapat memulihkan file yang dihapus dengan rm -rf, dan keduanya harus dilakukan sebelum Anda membuka mesin pencari. Hentikan penulisan ke filesystem tersebut. Kemudian hentikan penggunaannya dengan melakukan unmount atau me-mount ulang dalam mode read-only.
rm tidak menghapus apa pun. Perintah ini menghapus entri direktori, lalu menandai inode dan blok data file sebagai bebas. Byte-nya masih berada di perangkat. Byte tersebut tetap ada sampai block allocator memberikan blok itu kepada sesuatu yang lain dan proses tersebut menimpanya. Setiap detik filesystem tetap ter-mount dan aktif, daemon dapat menulis satu baris log atau database dapat melakukan flush halaman, dan salah satu operasi tulis itu dapat menggunakan blok yang ingin Anda pulihkan.
Jadi, perintah pertama harus menghentikan penulisan, bukan memulihkan file.
sudo systemctl stop nginx postgresql
sudo umount /mnt/dataJika umount memberikan jawaban umount: /mnt/data: target is busy., cari proses yang membuat filesystem tetap terbuka.
sudo fuser -vm /mnt/data
sudo lsof +D /mnt/dataJika Anda tidak dapat membebaskannya, lakukan remount dalam mode read-only. Mount read-only menghentikan alokasi baru, dan itulah sebagian besar tindakan yang Anda perlukan.
sudo mount -o remount,ro /mnt/dataJika path yang dihapus berada pada root filesystem, prosesnya lebih sulit. sudo mount -o remount,ro / biasanya gagal dengan mount: /: cannot remount /dev/vda1 read-only. karena proses yang sedang berjalan membuka file untuk ditulis, dan kernel tidak akan memaksa proses tersebut menutup file. Pada VPS, solusi praktisnya adalah menggunakan mode rescue atau recovery dari provider. Mode ini melakukan boot ke live system terpisah dengan disk Anda terpasang tetapi tidak di-mount. Semua perintah di bawah ini kemudian dijalankan terhadap perangkat yang tidak sedang ditulisi oleh proses mana pun.
Satu aturan berlaku untuk seluruh panduan ini. Jangan pernah menulis file yang dipulihkan, disk image, atau tool yang baru diinstal ke filesystem yang sedang Anda pulihkan. Pasang volume kedua, atau kirim output ke mesin lain melalui SSH.
Mengapa pemulihan rm -rf pada ext4 hampir mustahil
Tetapkan ekspektasi sebelum memasang apa pun. Pastikan filesystem yang digunakan:
lsblk -fPada ext4, yang menjadi filesystem default pada hampir semua image VPS, lokasi data file disimpan dalam inode sebagai pohon extent. Extent adalah satu catatan yang menyatakan bahwa logical block N dari file ini dimulai pada physical block M dan menggunakan L block. File kecil menyimpan hingga empat catatan tersebut langsung di dalam inode. File yang lebih besar menunjuk ke block tambahan yang menyimpan bagian lain dari pohon tersebut.
Ketika link terakhir ke sebuah file dihapus, ext4 menelusuri pohon tersebut, mengembalikan setiap extent ke block allocator, lalu menghapus pohon itu dari inode. Setelah itu, inode ditandai sebagai free dan diberi waktu penghapusan. Data itu sendiri tidak disentuh. Satu-satunya catatan tentang lokasi data tersebut telah dihapus.
Inilah perbedaannya dari ext3, yang inode terhapusnya masih menyimpan informasi yang cukup bagi tool seperti ext3grep untuk menelusurinya. Anda masih dapat mencantumkan inode yang terhapus pada ext4:
sudo debugfs -R lsdel /dev/vdb1debugfs membuka device dalam mode read-only kecuali Anda meneruskan -w, sehingga tindakan ini aman pada device yang tidak di-mount dan tidak memerlukan biaya apa pun untuk dicoba. Inode akan tercantum. Masalahnya muncul saat Anda mencoba melakukan dump, karena block map yang sebelumnya disimpan inode tersebut telah dihapus. Akibatnya, dump tidak memiliki apa pun untuk ditelusuri.
Dua tool mencoba mengatasi masalah ini dengan membaca journal. Journal adalah ring berukuran tetap yang digunakan ext4 untuk menjaga konsistensi metadata setelah terjadi crash. Journal mungkin masih menyimpan salinan inode yang lebih lama, sebelum penghapusan. extundelete dan ext4magic sama-sama mencarinya. Periksa ukuran yang digunakan:
sudo dumpe2fs -h /dev/vdb1 | grep -i journalJournal hanya menyimpan metadata dan ukurannya kecil, sehingga aktivitas penulisan biasa dapat melewatinya secara berulang. Pada server yang sedang berjalan, jangka waktu ketika inode sebelum penghapusan masih tersedia hanya berlangsung selama beberapa menit. Kedua tool tersebut tidak lagi dipelihara secara aktif, dan tidak tersedia dalam paket pada setiap distribusi. Anggap keduanya sebagai upaya dengan peluang keberhasilan rendah. Jalankan keduanya pada device yang tidak di-mount atau pada disk image, dan jangan terkejut jika keduanya tidak mengembalikan hasil apa pun.
Jika lsblk -f melaporkan xfs, situasinya tidak lebih baik, karena XFS juga tidak memiliki fitur undelete yang didukung. Urutan opsi di bawah ini tidak berubah.
Apakah file masih terbuka dalam proses yang sedang berjalan?
Ini adalah satu-satunya metode pemulihan pada halaman ini yang memiliki peluang keberhasilan tinggi. Karena itu, jangan restart service yang menggunakan file tersebut.
File benar-benar hilang hanya setelah dua hitungan mencapai nol: jumlah entri direktori yang menunjuk ke inode, dan jumlah file descriptor yang terbuka. rm membuat hitungan pertama menjadi nol. Jika suatu proses masih membuka file tersebut, hitungan kedua belum nol. Karena itu, inode dan bloknya masih dialokasikan, dan datanya masih dapat dibaca.
Temukan file terbuka yang jumlah hard link-nya telah menjadi nol:
sudo lsof +L1+L1 berarti menampilkan file terbuka dengan jumlah hard link di bawah 1. Setiap hasil menampilkan proses, nomor file descriptor, sebuah NLINK dari 0, dan path yang diakhiri dengan (deleted). Gunakan PID dan nomor descriptor tersebut untuk /proc:
sudo ls -l /proc/1234/fdSalah satu entri akan terlihat seperti 3 -> /var/log/app/events.log (deleted). Link tersebut masih mengarah ke data. Salin data itu ke filesystem lain:
sudo cp /proc/1234/fd/3 /mnt/rescue/events.logGunakan cp, bukan mv. Membuka /proc/1234/fd/3 memberi Anda handle baru ke inode yang sama mulai dari offset nol. Dengan demikian, Anda mendapatkan seluruh file, bukan hanya bagian setelah posisi penulisan saat ini.
Ada dua batasan yang perlu diketahui. Struktur direktori yang dihapus tidak dapat dipulihkan dengan cara ini, karena hanya file individual yang masih terbuka oleh suatu proses yang tetap ditahan. Selain itu, file database yang disalin ketika engine sedang melakukan penulisan akan menjadi salinan yang konsisten terhadap crash. Karena itu, rencanakan untuk menjalankan pemulihan bawaan engine pada salinan tersebut, bukan menganggapnya sebagai salinan yang bersih. Entri yang ditampilkan oleh lsof dengan mem sebagai pengganti nomor descriptor adalah memory mapped. Entri tersebut tidak memiliki /proc/<pid>/fd yang dapat disalin.
Apakah Anda memiliki snapshot pada btrfs, ZFS, atau LVM?
Jika filesystem mendukung snapshot, file yang dihapus mungkin masih berada di dalam salah satunya tanpa perubahan. Ini hanya membantu jika snapshot telah dibuat sebelum penghapusan. Apa pun yang Anda buat sekarang tidak dapat memulihkan keadaan sebelumnya.
btrfs menyimpan snapshot sebagai subvolume:
sudo btrfs subvolume list /Telusuri snapshot tersebut dan salin path yang diperlukan dengan cp -a. Sebaiknya salin path satu per satu daripada mengembalikan seluruh subvolume, karena rollback juga membuang semua data yang ditulis sejak snapshot dibuat.
ZFS menampilkan setiap snapshot sebagai direktori hanya-baca:
zfs list -t snapshot
ls /tank/data/.zfs/snapshot/Direktori .zfs disembunyikan dan tidak akan muncul pada ls biasa terhadap root dataset, tetapi Anda dapat masuk ke dalamnya berdasarkan nama. Salin file dari sana. zfs rollback mengembalikan seluruh dataset ke snapshot yang ditentukan dan menghapus setiap snapshot yang lebih baru daripada snapshot tersebut, jadi gunakan perintah ini sebagai pilihan terakhir.
Snapshot LVM adalah volume copy-on-write dengan ukuran tetap:
sudo lvs
sudo mount -o ro /dev/vg0/data-snap /mnt/snapMount snapshot tersebut dalam mode hanya-baca, lalu salin datanya. Periksa lvs sebelum mengandalkannya, karena snapshot LVM yang memenuhi ruang alokasinya akan dibatalkan oleh kernel. Setelah itu terjadi, isinya hilang.
Snapshot bukan backup. Snapshot berada pada disk atau pool yang sama dengan data asli, sehingga menghadapi semua kegagalan yang sama. Snapshot sangat berguna untuk membatalkan kesalahan yang terjadi dua menit lalu. Itulah fungsi yang dibutuhkan di sini.
Carving dengan PhotoRec, gunakan image dan jangan pernah menggunakan disk aktif
Jika tidak ada metode di atas yang berlaku, pilihan yang tersisa adalah carving: memindai perangkat mentah untuk mencari pola byte yang menandai awal tipe file yang dikenal, lalu menulis data yang mengikutinya. Carving hanya membaca data file. Nama file, struktur direktori, timestamp, dan kepemilikan semuanya merupakan metadata filesystem. Metadata itulah yang dihancurkan oleh rm, sehingga tidak ada yang dapat dipulihkan. Anda akan mendapatkan file bernama f0384512.jpg dalam direktori keluaran bernomor, lalu harus mengurutkannya secara manual.
Dua aturan menentukan apakah metode ini dapat digunakan.
Pertama, buat image perangkat sebelum mengarahkan alat lain ke perangkat tersebut. Pada Debian dan Ubuntu, paketnya adalah gddrescue dan binary yang dipasangnya adalah 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 harus berada pada perangkat yang berbeda, dengan ruang kosong setidaknya sebesar kapasitas partisi. lsblk -b menampilkan ukuran persis dalam byte. File map memungkinkan penyalinan yang terhenti untuk dilanjutkan tanpa mengulang dari awal. Setelah memiliki image, Anda dapat mencoba alat kedua nanti pada byte yang sama persis. Hal ini tidak dapat dilakukan jika alat pertama menimpa disk.
Kedua, arahkan alat pemulihan ke file image.
sudo photorec /d /mnt/rescue/recup /mnt/rescue/vdb1.imgphotorec membuka menu teks. Pilih partisi, lalu tipe filesystem, kemudian signature file yang akan dicari, dan terakhir direktori tujuan. Batasi daftar signature tersebut hanya pada tipe file yang benar-benar hilang sebelum memulai, karena daftar bawaan akan mencari semua tipe file dan menghasilkan puluhan ribu fragmen untuk diseleksi.
testdisk, dari paket yang sama, memiliki fungsi undelete sendiri dan hanya mendukung FAT, exFAT, NTFS, serta ext2. Pada ext4, pilihan tersebut menyisakan photorec.
File yang terfragmentasi dapat dipulihkan dalam kondisi rusak. Carving mengasumsikan bahwa blok file bersebelahan. Karena itu, file yang bloknya dipisahkan oleh allocator di seluruh disk dapat dirangkai secara keliru atau tidak ditemukan sama sekali. File media biasanya dapat di-carve dengan cukup baik karena memiliki header yang kuat. File teks biasa, konfigurasi, dan kode sumber sulit di-carve karena tidak ada signature byte yang menandai awal shell script.
Spasi terselip: bagaimana path yang salah terhapus
Hampir setiap kecelakaan rm -rf disebabkan oleh masalah shell. rm menerima daftar path dan menghapusnya satu per satu. Perintah tersebut tidak mengetahui maksud Anda.
Kasus klasiknya adalah satu spasi:
rm -rf /home/deploy/app /old
rm -rf /home/deploy/app/oldBaris pertama memiliki dua argumen. Baris tersebut menghapus aplikasi, lalu menghapus /old. Jika /old tidak ada, rm tidak menampilkan apa pun karena -f menyembunyikan error file yang tidak ditemukan. Tidak adanya output bukan konfirmasi.
Bentuk kedua adalah variabel tanpa tanda kutip yang berisi spasi:
dir="/srv/my app"
rm -rf $dirShell memisahkan nilai tersebut berdasarkan spasi kosong. Akibatnya, rm menerima /srv/my dan app sebagai dua path terpisah. Jika ditulis sebagai rm -rf "$dir", nilainya menjadi satu path.
Bentuk ketiga adalah variabel kosong, biasanya karena perintah yang seharusnya mengisinya gagal:
rm -rf "$TARGET"/*Jika TARGET tidak ditetapkan, nilai tersebut diperluas menjadi rm -rf /*. GNU rm menolak bentuk kosong tersebut: rm -rf / menampilkan rm: it is dangerous to operate recursively on '/' lalu berhenti. Bentuk glob tidak mendapat perlindungan yang sama karena shell mengganti /* dengan daftar path tingkat teratas yang benar-benar ada sebelum rm dijalankan. / bukan salah satunya, sehingga pemeriksaan tersebut tidak pernah dijalankan.
Kebiasaan untuk mencegah kesalahan berikutnya
- Beri tanda kutip pada setiap variabel yang digunakan sebagai path. Selalu tulis
"$dir", termasuk di dalam test dan loop. - Hentikan proses jika nilainya kosong.
rm -rf "${TARGET:?TARGET is not set}"/*membuat shell berhenti dengan pesan Anda sebelumrmdijalankan, jikaTARGETtidak disetel atau kosong. Letakkanset -euo pipefaildi bagian paling atas setiap script yang menghapus file. - Tambahkan
--one-file-system. Opsi ini memberi tahurmagar melewati direktori yang berada pada filesystem berbeda dari argumen yang Anda berikan. Dengan demikian, penghapusan rekursif tidak akan masuk ke volume backup yang di-mount atau bind mount. - Jangan menghapus sebagai root. Akun service hanya dapat menghapus data yang dimilikinya. Inilah alasan utama untuk menjalankan setiap service sebagai user unprivileged-nya sendiri. Jika Anda tidak yakin direktori mana yang dapat diakses akun tertentu, membaca permission bit dalam output ls akan menjawabnya dengan satu perintah.
- Tampilkan daftarnya sebelum bertindak. Dalam script, buat path-nya, jalankan
printf '%s\n'terhadapnya, baca output tersebut, lalu hapus pada pass kedua. - Siapkan perintah trash agar mudah digunakan.
sudo apt install trash-climenyediakantrash-put,trash-list,trash-restore, dantrash-empty. File yang dihapus dipindahkan ke~/.local/share/Trash, sedangkantrash-empty 30menghapus semua file yang berusia lebih dari tiga puluh hari.
Membuat alias rm ke trash-put terdengar seperti langkah berikutnya yang wajar, tetapi itu jebakan. Alias tersebut membentuk refleks yang gagal pada server berikutnya jika alias itu tidak tersedia. Selain itu, alias tidak berlaku di dalam script, padahal kesalahan yang paling mahal biasanya terjadi di sana. Sebagai gantinya, ketik trash-put secara sengaja.
Satu-satunya pemulihan yang selalu berhasil
Semua hal di atas adalah kemungkinan. Backup bukan kemungkinan.
Dua hal membuat backup benar-benar dapat diandalkan. Backup berjalan sesuai jadwal tanpa perlu Anda ingat, dan Anda setidaknya pernah memulihkannya sekali. Repository yang belum pernah digunakan untuk pemulihan hanyalah keyakinan, karena hal-hal yang membuatnya tidak berguna—misalnya path yang salah dalam daftar include atau password repository yang tidak pernah dicatat—baru terlihat pada hari ketika Anda membutuhkannya.
Dengan restic, pemulihan dilakukan dengan 2 perintah.
restic -r /srv/restic-repo snapshots
restic -r /srv/restic-repo restore latest --target /mnt/rescue --include /srv/appdataPulihkan ke direktori kosong, bukan ke path aktif, agar Anda dapat membandingkan keduanya sebelum apa pun dipindahkan ke lokasi semula. Menyiapkan backup restic pada VPS membahas penyiapan repository dan timer systemd yang menjalankannya.
Dengan Borg:
borg list /srv/borg-repo
borg extract /srv/borg-repo::daily-2026-08-08 srv/appdataPath di dalam arsip Borg disimpan tanpa slash di awal, sehingga srv/appdata cocok dan /srv/appdata tidak cocok dengan apa pun. borg extract menulis ke direktori kerja saat ini, jadi gunakan cd terlebih dahulu untuk menulis ke direktori sementara.
Jika Anda belum memilih salah satunya, perbandingan restic dan Borg membahas deduplikasi dan repository append-only. Sifat ini mencegah server yang telah dibobol menghapus riwayat backup-nya sendiri. Keduanya dapat digunakan. Jawaban yang salah adalah tidak menjalankan satu pun.
Server baru adalah waktu termurah untuk menyiapkan ini, sebelum ada data penting yang berisiko hilang. Sepuluh menit pertama pada VPS baru adalah tempat pekerjaan tersebut dilakukan, bersama penyiapan SSH dan firewall.
Kemudian buat pengingat berulang di kalender: setiap bulan, pulihkan satu direktori dari repository ke /tmp dan baca file-file tersebut. Kebiasaan sederhana ini lebih berharga daripada semua tool di halaman ini.
FAQ
Bisakah saya membatalkan penghapusan file pada ext4?
Biasanya tidak. Saat link terakhir ke sebuah file dihapus, ext4 menghapus extent tree dari inode, sehingga tidak ada catatan pada disk tentang lokasi data tersebut. extundelete dan ext4magic mencari salinan inode yang lebih lama di journal ext4. Cara ini hanya membantu jika penghapusan terjadi beberapa menit sebelumnya dan tidak ada aktivitas pada filesystem sejak saat itu. Kedua proyek tersebut tidak lagi dipelihara secara aktif. Jalankan salah satunya pada device yang tidak di-mount atau disk image, bukan pada filesystem yang sedang di-mount. Periksa terlebih dahulu objek yang digunakan dengan sudo dumpe2fs -h /dev/vdb1 | grep -i journal.
Sebuah service masih membuka file yang telah dihapus. Apakah saya dapat memulihkannya?
Ya, dan ini adalah kondisi terbaik. Selama sebuah proses masih membuka file, inode dan blok datanya tetap dialokasikan, sehingga data masih dapat dibaca. Jangan me-restart service tersebut, karena menutup descriptor terakhir akan menyelesaikan penghapusan. Jalankan sudo lsof +L1 untuk menampilkan file terbuka dengan link count 0. Catat PID dan nomor file descriptor, lalu salin melalui /proc dengan sudo cp /proc/1234/fd/3 /mnt/rescue/events.log. Tulis salinan tersebut ke filesystem yang berbeda. Entri yang menampilkan mem, bukan nomor descriptor, dipetakan ke memori dan tidak memiliki path /proc/<pid>/fd yang dapat digunakan sebagai sumber penyalinan.
Mengapa saya harus membuat image disk, bukan menjalankan tool pemulihan langsung pada disk?
Karena setiap tool harus menulis output ke suatu tempat. Penulisan ke filesystem yang sedang dipulihkan dapat menimpa free block yang masih berisi data Anda. Salin partisi ke device lain terlebih dahulu dengan sudo ddrescue -n /dev/vdb1 /mnt/rescue/vdb1.img /mnt/rescue/vdb1.map, lalu arahkan photorec ke file image tersebut. Image juga memungkinkan Anda mencoba tool kedua nanti pada byte yang persis sama. Hal ini tidak mungkin dilakukan setelah sesuatu menimpa data pada disk asli.
Apakah rm -rf / masih dapat menghancurkan sistem Linux?
Perintah tanpa tambahan tersebut tidak dapat melakukannya. GNU rm menolaknya dan menampilkan rm: it is dangerous to operate recursively on '/'. Bentuk perintah yang berbahaya adalah yang masuk melalui jalur lain. rm -rf "$TARGET"/* dengan TARGET tidak disetel akan diekspansi menjadi rm -rf /*. Shell kemudian memberikan rm daftar direktori tingkat teratas yang benar-benar ada, dan tidak ada yang merupakan /, sehingga mekanisme perlindungan tidak pernah terpicu. Sebaliknya, tulis "${TARGET:?TARGET is not set}" agar shell berhenti sebelum rm dijalankan.
Apakah snapshot filesystem merupakan backup?
Tidak. Snapshot btrfs atau ZFS berada pada pool yang sama dengan data yang dilindunginya. Karena itu, disk yang rusak atau pool yang hancur akan menghilangkan keduanya sekaligus. Snapshot LVM memiliki masalah tambahan berupa ukuran tetap. Setelah snapshot penuh, kernel membatalkannya dan isinya hilang. Snapshot sangat baik untuk membatalkan penghapusan yang terjadi dua menit sebelumnya. Untuk kebutuhan lainnya, simpan repository pada hardware yang terpisah.