64 Detik, 4.496 File Hilang
“The first principle is that you must not fool yourself — and you are the easiest person to fool.”
“Prinsip pertama: jangan membodohi dirimu sendiri — dan kamu adalah orang yang paling gampang dibodohi.”
— Richard Feynman, Cargo Cult Science, Caltech, 1974
Sehari sebelumnya, NAS kantor ke-reset dan router-nya mati barengan. Gue ngerecover dari jam tujuh pagi sampai jam tujuh malam. Datanya selamat, tapi satu volume harus diformat ulang dan disusun balik dari nol.
Jam tujuh malam itu sistemnya udah jalan lagi. Yang belum kelar tinggal permission. Gue udah dua belas jam di depan layar, jadi bagian itu gue titipin dan gue tidur — dengan niat ngecek hasilnya sebelum jam kerja.
Jam 01:04, sebuah akun login ke VPN dari IP yang bukan IP kantor.
Jam 01:05, salah satu shared folder arsip mulai dihapus. Bukan lewat File Station, bukan drag-to-trash. Ini rm level root lewat SSH — 1.939 operasi hapus dalam rentang 64 detik, 4.496 file. Arsip bertahun-tahun, dan sebagian besarnya nggak ada salinannya di tempat lain.
Jam 01:08, akun itu logout.
Gue kebangun jam dua pagi. Buka share buat ngecek permission tadi. Permissionnya belum kelar dikerjain. Gue liat log dan disitu gue cuma bisa bengong.
Tiga Puluh Menit Sebelum Gue Ngetik Apa Pun
Gue nggak langsung ngapa-ngapain.
Gue duduk di depan laptop sekitar tiga puluh menit dan nggak ngetik satu perintah pun. Yang ada di kepala cuma isi folder itu, dan berapa banyak yang nggak bisa diminta ulang ke mana pun.
Tapi tiga puluh menit itu yang bikin gue nggak salah langkah.
Sehari sebelumnya gue masih bisa bilang ke diri sendiri bahwa NAS ke-reset dan router mati barengan itu kebetulan buruk. Perangkat rusak, listrik, apa aja. Malam itu penjelasan-penjelasan itu abis. Dua kejadian dalam tiga puluh jam, dan yang kedua lewat rm dari sesi VPN jam satu pagi.
Jadi masalahnya bukan “ada data hilang”. Masalahnya ada orang di dalam, dan gue nggak tau dia masih di dalam atau nggak.
Begitu itu jelas, urutan kerjanya jadi kebalik dari insting. Recovery nomor dua. Nomor satu mastiin nggak ada yang bisa nambah kerusakan sambil gue kerja.
/ppp active print # siapa yang lagi nyantol sekarang
/user active print
/log print where topics~"account" # siapa masuk kapanHabis itu semua akses dari luar gue matiin — VPN, port forward, sisa akses admin. Akunnya gue disable, sesinya gue putus.
Bukan karena gue udah paham kejadiannya. Justru sebaliknya. Selama gue belum paham, jumlah pintu yang kebuka harus nol.
Kalau gue langsung lompat ke recovery jam dua pagi itu, gue bakal ngerjain volume yang orangnya masih bisa masuk. Recovery-nya kepake atau nggak, gue nggak tau. Yang gue tau gue nggak akan pernah yakin hasilnya bersih.
Tiga Hal yang Gue Cek, dan Ketiganya Nggak Ada
sudo ls "/volume1/Backup01/#recycle/" # Recycle Bin -> kosong
sudo ls -d /volume1/@sharesnap* # snapshot -> nggak ada
# Hyper Backup ke destinasi luar # -> nggak pernah dijadwalinRecycle Bin kosong itu sebenernya wajar dan gue udah setengah nyangka. rm level root ngelewatin dia gitu aja — Recycle Bin ngelindungin dari orang yang salah klik, bukan dari orang yang punya shell.
Yang tersisa cuma satu jalan, dan untungnya jalan itu ada di sifat filesystem-nya sendiri. btrfs itu copy-on-write: tiap kali ada perubahan, blok lama nggak diedit di tempat, versi barunya ditulis di lokasi lain. Artinya kondisi filesystem sebelum penghapusan kemungkinan besar masih fisik ada di disk.
Rencana gue: cari kondisi itu, tarik isinya. Estimasi yang gue kasih besok paginya satu sore.
btrfs restore balikin 854 file. Dari 4.496.
Sisanya butuh tiga pendekatan lagi, dan salah satunya belum ada tool-nya.
Sebelum Nyentuh Apa-apa: Berhenti Nulis
File yang dihapus di btrfs nggak langsung ilang. Yang ilang referensinya. Blok datanya masih di disk, ditandain bebas, nunggu ditimpa. Tiap byte yang lo tulis ke volume itu setelah insiden adalah lotere.
Jadi urutannya: ambil log dulu ke mesin lain — nanti gue jelasin kenapa ini yang paling kebayar — terus stop semua paket, matiin SMB, unmount.
umount gue gagal: target is busy. Reflek pertama gue umount -l. Lazy unmount muncul paling atas di hasil pencarian, dan waktu itu kedengeran masuk akal — toh volume-nya "kelihatan" udah lepas.
Gue cek dulu sebelum ngejalanin, dan bagus gue cek. Lazy unmount cuma ngelepas volume dari namespace. File descriptor yang udah telanjur kebuka tetep valid, dan proses yang megang masih bisa terus nulis. Buat recovery lo butuh device beneran lepas, bukan pura-pura lepas.
Cara yang bener nggak canggih: baca output fuser -vm, matiin PID yang nyangkut satu-satu, ulangi umount biasa. Lima menit lebih lama, dan itu bukan lima menit yang bisa ditawar.
Jarak antara penghapusan dan gue nemuin sekitar satu jam, plus tiga puluh menit tadi, dan volume-nya lagi nggak sibuk. Itu jendela paling sempit yang mungkin gue dapet, dan sisanya tinggal nggak ngerusak jendela itu sendiri.
Dry-run Kosong Itu Bukan Berarti Generation-nya Salah
btrfs nyimpen nomor generation yang naik tiap kali transaksi commit, dan btrfs-find-root bisa nyisir disk buat ngasih daftar kondisi filesystem yang masih ketemu. Gue ambil kandidat yang jamnya sebelum penghapusan, terus dry-run.
sudo btrfs restore -v -D -t 3490770862080 \
--path-regex '^(|/@syno(|/Backup01(|/5\. ARSIP(|/.*))))$' \
/dev/mapper/cachedev_0 /volume2Hasilnya nol. Bukan error — kosong.
Tebakan pertama yang wajar: generation-nya salah, ini pasti udah post-delete. Gue coba beberapa kandidat lain, dan semuanya nol juga. Itu yang ngasih petunjuk — kalau lima generation berturut-turut hasilnya sama persis, variabel yang salah bukan generation-nya.
Yang salah --path-regex. btrfs restore nyusun path sambil nurunin direktori, dan nyocokin polanya di tiap tingkat — mulai dari string kosong, terus /@syno, terus /@syno/Backup01, dan seterusnya. Jadi polanya harus ikut cocok di semua tingkat, dan itu alasan bentuknya jadi kurung berlapis yang aneh itu.
Get Habie Purwokusumo Putrapandowo’s stories in your inbox
Join Medium for free to get updates from this writer.
Ini jebakan yang bikin banyak orang nyerah di titik ini, karena gejalanya identik: hasil kosong tanpa pesan error. Cara bedainnya cuma satu — kalau ganti generation nggak ngubah apa-apa, berhenti ngutak-atik generation.
Satu lagi yang gue verifikasi ulang belakangan: di btrfs restore, -s itu --snapshots, bukan symlink. Yang mulihin symbolic link -S kapital. Dua flag yang bedanya cuma besar-kecil huruf, dan salah satunya diem aja kalau lo keliru.
PhotoRec Balikin Isinya, Bukan Namanya
Lapisan berikutnya: file carving pakai PhotoRec. Carving ngabaikan filesystem sepenuhnya — nyisir disk mentah nyari pola byte pembuka tiap format, terus motong sampai penanda akhir.
Carving balikin isi. Carving nggak balikin nama.
Hasilnya ratusan ribu file bernama f12345678.xlsx. Tanpa folder, tanpa tanggal, tanpa urutan. Dan mayoritasnya salinan file yang nggak pernah kehapus — carving nggak bisa bedain mana yang mati mana yang hidup.
Jadi gue nulis penyaring sendiri: hash semua file yang masih hidup, buang kandidat yang identik, sisanya dibuka isinya dan diskor pakai daftar keyword yang khas isi folder itu. Tumpukannya langsung ketebang drastis sebelum kerjaan mahalnya mulai.
Pass pertama hasilnya penuh dokumen yang nggak ada hubungannya. Penyebabnya dua huruf: pt. Gue masukin sebagai keyword karena banyak dokumen yang nyebut nama perusahaan. Sebagai substring, pt juga cocok sama output, script, adapter, receipt — dan tiba-tiba separuh isi disk jadi kandidat.
# keyword pendek dicocokin word-boundary, bukan substring
KEYWORDS_WORD = ["pt", "cv", "sk", "rev"]Keyword panjang aman sebagai substring. Keyword pendek harus dibatesin batas kata. Perbaikannya satu karakter, dan itu yang misahin hasil yang bisa direview manusia dari hasil yang cuma bikin capek.
Bagian yang Belum Ada Tool-nya
Ini kunci semuanya, dan ini yang gue lewat di awal.
btrfs restore kerjanya spesifik: dia ambil satu kondisi filesystem, terus nurunin pohonnya dari situ. Dia cuma lihat metadata yang masih nyantol ke situ.
Tapi inget lagi sifat copy-on-write. Waktu sebuah folder berubah, metadata lamanya nggak ditimpa — dia ditinggal di tempatnya, bloknya cuma dilepas ke free space, dan dia bertahan sampai ada yang ngambil bloknya buat keperluan lain.
Dan di dalam metadata yatim itu ada persis yang gue butuh: nama file, nama folder induknya, dan alamat blok datanya. Persis bagian yang nggak bisa dikasih sama carving.
btrfs restore nggak akan pernah nyentuh itu, karena nggak ada jalur ke sana dari kondisi mana pun yang dia tau. Tool lain di ekosistem btrfs juga sama — semuanya berangkat dari asumsi ada satu kondisi utuh yang naungin.
Jadi gue nulis sendiri. Baca langsung dari disk, byte per byte, ngikutin spesifikasi on-disk btrfs.
Tiga hal yang bikin ini jauh lebih mungkin dari kelihatannya.
Yang pertama, nggak perlu nyisir 14 TB. btrfs misahin bloknya sesuai peruntukan, dan yang gue cari cuma ada di area metadata — puluhan GB, bukan belasan TB. Yang tadinya berhari-hari jadi hitungan jam.
Yang kedua, formatnya sendiri yang ngasih cara verifikasi. btrfs nyatet alamat sebuah blok di dalam blok itu sendiri. Cocok sama posisi tempat lo nemuin? Hampir pasti asli. Nggak cocok? Cuma byte yang kebetulan mirip. Satu perbandingan, dan salah tangkap praktis nol. Itu bukan trik gue — itu emang udah disiapin di formatnya, tinggal dipakai.
Yang ketiga, struktur foldernya bisa disusun ulang. Tiap potongan metadata nyimpen nama file plus nomor folder induknya, jadi tinggal naik terus ke induknya sampai mentok di akar. Yang induknya nggak ketemu nggak gue buang — gue pisahin ke folder sendiri. File tanpa folder tetep jauh lebih berguna daripada file yang nggak ada.
Gue nulis ini semalaman tanpa kesempatan ngetes duluan di image btrfs beneran, jadi validasi paling awal gue taro di baris pertama: kalau peta disk gue salah, dia gagal di detik pertama dengan pesan jelas. Bukan jalan enam jam terus muntahin file yang keliatan kayak dokumen.
Itu prinsip yang gue pegang buat semua tool recovery. Yang paling bahaya bukan tool yang error — yang paling bahaya tool yang ngeluarin hasil yang keliatan bener.
Karena itu juga laporan hasilnya gue bikin tiga tingkat, bukan cuma berhasil/gagal: utuh, sebagian, dan ketemu-namanya-tapi-datanya-habis. Yang ketiga kedengeran kayak kegagalan, tapi bukan. Tau sebuah file bernama persis ini pernah ada di folder persis ini itu modal buat minta salinan ulang ke pihak yang nerbitin dokumennya — dan itu jauh lebih berguna daripada folder kosong tanpa keterangan.
Kapan Mesin Boleh Mutusin Sendiri
Sisa kerjaannya nyocokin dua tumpukan: daftar 4.496 nama file yang hilang — direkonstruksi dari log yang gue amanin di menit pertama, dan itu bagian yang paling kebayar dari seluruh malam itu — sama ribuan file anonim hasil carving.
Yang paling lama gue pikirin bukan algoritma pencocokannya. Tapi kapan tool-nya boleh mutusin sendiri, dan kapan harus nyerah ke manusia.
Aturan yang gue pakai: skor tinggi doang nggak cukup. Kandidat teratas harus unggul cukup jauh dari kandidat kedua. Kalau dua-duanya nempel, tool-nya nggak boleh milih — dia nyajiin tiga opsi dan nyuruh orang buka satu-satu.
Itu bukan keputusan teknis, itu keputusan kebijakan. Salah ngasih nama satu dokumen terus nyerahinnya dengan percaya diri jauh lebih ngerugiin daripada maksa orang buka tiga file dan milih sendiri — apalagi kalau dokumennya bakal dipakai buat hal yang nggak bisa ditarik lagi. Threshold di tool recovery itu pernyataan soal seberapa besar kerusakan yang sanggup lo tanggung kalau lo salah.
Yang Gue Bawa dari Malam Itu
Recovery itu kerjaan yang tiap langkahnya nyediain jawaban permukaan yang masuk akal, dan sebagian besarnya salah. umount -l "berhasil". Dry-run yang kosong "berarti generation-nya salah". Laporan yang bilang OK ya berarti OK. Nggak satu pun dari itu keliatan salah dari luar, dan itu yang bikin bahaya.
Yang bikin beda bukan hafal internal filesystem — itu bisa dibaca semalem. Yang bikin beda kebiasaan nanya “gue tau ini dari mana” sebelum lanjut ke langkah berikutnya. Tiap kali gue nanya itu, gue nemu satu lapisan lagi di bawah yang gue kira udah dasar.
Pola yang sama ada di malam sebelumnya, dan itu yang paling mahal. Jam tujuh malam sistemnya udah jalan — itu lapisan yang keliatan, dan itu yang bikin gue ngerasa boleh tidur. Permission ada satu level di bawahnya. Enam jam kemudian bagian itu yang kepake.
“Sistemnya udah jalan” dan “sistemnya udah aman” itu dua status yang beda, dan jarak antara keduanya biasanya diisi sama orang yang capek. Sekarang tiap kali gue nutup pekerjaan recovery, yang gue cek bukan service-nya nyala atau nggak, tapi akses dan keamanannya udah balik ke tempatnya atau belum. Itu perubahan cara kerja yang gue bawa dari satu malam ini, dan sejauh ini itu yang paling sering nyelametin.
Sisanya lebih gampang: snapshot per jam bikin seluruh cerita ini selesai dalam lima menit. Recycle Bin bukan snapshot. Bukti diamanin sebelum recovery, karena log ilang pas reboot dan reboot pasti kejadian — dan tanpa log itu gue nggak akan punya daftar 4.496 nama buat dicocokin.
Referensi
Semua nama, tanggal, alamat IP, dan identitas organisasi udah disamarkan.








