Server Rumahan & Self-Hosting

Ruang Filesystem pada Home Server Debian - Diagnosis Block, Inode, dan File Terbuka Tersembunyi

Ruang Filesystem pada Home Server Debian - Diagnosis Block, Inode, dan File Terbuka Tersembunyi

Sebuah service tidak bisa menambahkan data ke database, proses backup berhenti di tengah jalan, atau aplikasi mencatat No space left on device. Penjelasan yang paling jelas adalah disk penuh. Itu mungkin benar, tetapi belum menjadi diagnosis yang berguna. Mounted filesystem mana yang bermasalah? Apakah data block atau inode-nya habis? Apakah proses yang masih berjalan tetap menahan file yang sudah dihapus? Atau kegagalan itu sebenarnya disebabkan oleh quota atau filesystem yang berubah menjadi read-only?

Respons yang baik perlu menjawab pertanyaan tersebut sebelum menghapus apa pun. Di home server, urutan paling aman lebih mirip memeriksa pipa bocor daripada mengosongkan lemari secara acak: temukan sumber tekanan, hentikan aliran yang masih berlangsung, identifikasi apa yang boleh dihapus berdasarkan kebijakan, lalu pastikan service yang bergantung padanya tetap bekerja.

“No space left” adalah gejala, bukan diagnosis lengkap

Pada tingkat system call, Linux dapat mengembalikan ENOSPC ketika device yang menyimpan sebuah file tidak memiliki ruang untuk data tambahan. Manual Linux write(2) juga membedakannya dari EDQUOT, yang berarti quota disk block untuk pengguna telah habis. Aplikasi kerap menyederhanakan error semacam ini di dalam log, jadi mulailah dari bukti pada host, bukan hanya dari kalimat error tersebut.

Capacity juga melekat pada sebuah filesystem, bukan sekadar pada “disk”. Sebuah server dapat memiliki ruang kosong di satu mounted filesystem, sementara /var, volume database, atau mount untuk backup sudah penuh. Karena itu, proses write dapat gagal meskipun device lain masih memiliki ratusan gigabyte ruang kosong.

Setidaknya ada tiga pertanyaan tentang capacity yang perlu dipisahkan:

  • Block: Apakah filesystem kehabisan ruang untuk data dan metadata file?
  • Inode: Apakah filesystem masih dapat membuat file atau directory entry baru?
  • Ruang yang masih direferensikan: Apakah sebuah file sudah dihapus dari direktorinya, tetapi masih dibuka oleh suatu proses?

Ketiga keadaan ini dapat terlihat serupa dari sisi aplikasi, tetapi membutuhkan penanganan yang berbeda.

Mulai dari filesystem yang terdampak

Dokumentasi GNU Coreutils untuk df mendefinisikan tool ini sebagai laporan ruang yang sudah digunakan dan masih tersedia pada filesystem. Berikan path yang gagal kepada perintah tersebut, alih-alih langsung menganggap root filesystem sebagai penyebabnya:

df -h /path/that/failed
df -T /path/that/failed
df -i /path/that/failed

Perintah pertama menampilkan block capacity dalam format yang mudah dibaca untuk filesystem yang memuat path tersebut. Perintah kedua menambahkan jenis filesystem. Perintah ketiga mengganti statistik block dengan statistik inode. Catat source device dan mount point-nya; investigasi berikutnya sebaiknya tetap berfokus pada filesystem itu.

Output yang mudah dibaca berguna bagi manusia, tetapi script sebaiknya meminta field eksplisit atau unit yang stabil. Lebih penting lagi, jangan menganggap persentase yang ditampilkan sebagai keseluruhan cerita. Ruang yang tersedia untuk service tanpa privilege dapat berbeda dari hitungan sederhana total dikurangi penggunaan, dan setiap implementasi filesystem memiliki detail alokasi serta reservasinya sendiri.

Periksa inode meskipun byte masih tersedia

Inode menyimpan informasi tentang sebuah objek filesystem, termasuk metadata dan lokasi datanya. Workload yang membuat sangat banyak file cache kecil, session, queue entry, atau file hasil ekstraksi package dapat kehabisan inode yang tersedia sebelum kehabisan byte. Dalam keadaan ini, menghapus satu archive besar mungkin membebaskan block, tetapi tidak menyelesaikan kekurangan yang sebenarnya.

Jika df -i menunjukkan tekanan pada inode, GNU du dapat memperkirakan directory tree mana yang memuat banyak objek filesystem:

sudo du --inodes -x --max-depth=1 /affected/mount
sudo du --inodes -x --max-depth=1 /affected/mount/suspect-directory

Menurut manual GNU du, --inodes melaporkan penggunaan inode sebagai pengganti penggunaan block, sedangkan -x menjaga traversal tetap berada pada satu filesystem. Ulangi perintah kedua hanya untuk direktori yang memang perlu diperiksa lebih dekat. Jumlah yang tinggi menunjukkan lokasi yang perlu ditelusuri; angka itu tidak menentukan file mana yang aman dihapus.

Gunakan du untuk mencari pertumbuhan, bukan menggantikan df

Ketika block mulai langka, periksa tingkat teratas dari mount yang terdampak:

sudo du -x -h --max-depth=1 /affected/mount
sudo du -x -h --max-depth=1 /affected/mount/suspect-directory

df dan du menjawab pertanyaan yang berbeda. df melaporkan alokasi pada tingkat filesystem. du memperkirakan ruang yang direpresentasikan oleh file yang dapat dijangkau di bawah directory tree terpilih. Total keduanya tidak harus selalu cocok secara sempurna.

Perbedaannya dapat bersifat wajar. Permission bisa menghalangi pengguna melihat sebagian tree. Hard link, sparse file, penyimpanan copy-on-write, compression, nested mount, dan metadata filesystem membuat accounting menjadi lebih rumit. Inilah alasan perintah di atas memakai sudo untuk visibilitas dan -x agar tidak diam-diam masuk ke mounted filesystem lain. Meski begitu, du tetap merupakan estimasi.

Selisih besar juga dapat menjadi petunjuk penting. Jika df menyatakan alokasi filesystem sangat tinggi, tetapi file yang dapat dijangkau dan dilaporkan du hanya menjelaskan sebagian kecilnya, periksa file yang sudah dihapus tetapi masih terbuka.

Temukan file terhapus yang masih dibuka oleh proses

Pada sistem serupa Unix, menghapus pathname belum tentu langsung melepaskan storage yang mendasarinya. Jika sebuah proses masih membuka file itu, proses tersebut dapat terus menggunakannya sampai file descriptor ditutup. Keadaan ini sering relevan ketika file log dihapus secara manual, sementara service-nya terus menulis ke file tersebut.

sudo lsof +L1

Manual lsof(8) menyatakan bahwa +L1 memilih file terbuka dengan link count kurang dari satu, yaitu file terbuka yang sudah di-unlink. Menjalankannya dengan privilege yang sesuai penting karena tampilan yang terbatas dapat melewatkan file milik proses lain.

Baca nama proses, PID, file descriptor, ukuran, dan pathname sebelum bertindak. Jangan menghentikan semua proses yang tercantum. Restart terkontrol terhadap service pemilik tertentu dapat menutup descriptor dan melepaskan ruang, tetapi restart itu juga memiliki konsekuensi operasional. Periksa dokumentasi service, pekerjaan yang sedang berlangsung, dan restart policy lebih dahulu. Untuk database atau service stateful lain, menjaga integritas lebih penting daripada merebut kembali ruang beberapa detik lebih cepat.

Periksa kemungkinan penghasil data sebelum membersihkannya

Ukuran direktori hanya awal dari pertanyaan. Pertanyaan berikutnya adalah mengapa ukurannya bertambah. Penghasil data yang umum mencakup application log, system journal, cache, temporary export, area staging upload, file database, container layer, dan backup. Masing-masing memiliki pemilik serta retention policy berbeda. Perintah rm generik tidak dapat mengetahui data mana yang boleh dibuang.

Untuk systemd journal, pemeriksaannya sederhana:

journalctl --disk-usage

Dokumentasi journalctl(1) menyatakan bahwa total ini mencakup file journal aktif dan archived. Operasi vacuum menghapus archived journal, bukan yang aktif, sehingga batas vacuum yang diminta tidak menjamin total yang ditampilkan akan turun tepat ke angka tersebut. Utamakan pengaturan retensi yang disengaja dan mekanisme cleanup resmi dari service dibanding penghapusan manual dalam keadaan darurat.

Sebelum cleanup, simpan konteks secukupnya agar insiden dapat dijelaskan kemudian: mount yang terdampak, ketersediaan block dan inode, direktori relevan terbesar, proses yang terus tumbuh, serta error service terbaru. Setelah itu, hentikan atau batasi producer jika masih terus bertambah. Membersihkan data ketika proses yang tidak terkendali masih menulis hanya memberi tambahan waktu yang tidak diketahui.

Urutan recovery yang hati-hati

  1. Pastikan path dan error yang gagal. Hindari mendiagnosis mount lain hanya karena lebih mudah diperiksa.
  2. Ukur block dan inode. Simpan output df yang relevan dan catat mount point.
  3. Temukan tree atau referensi tersembunyi yang bertanggung jawab. Gunakan pemeriksaan du yang dibatasi dan lsof +L1; jangan memulai dengan pencarian penghapusan untuk seluruh server.
  4. Hentikan pertumbuhan. Jeda job yang gagal, batasi pekerjaan masuk, atau lakukan tindakan terkontrol terhadap service jika sesuai.
  5. Bersihkan berdasarkan kepemilikan dan kebijakan. Gunakan perintah retensi aplikasi, log rotation, pengelolaan cache, atau kebijakan backup yang sudah ditetapkan.
  6. Ukur ulang dan uji. Periksa kembali ketersediaan block serta inode, lalu verifikasi service yang gagal dan setiap service yang di-restart.
  7. Cegah kejadian berulang. Sesuaikan retensi, capacity, perilaku workload, atau alerting berdasarkan penyebab yang ditemukan.

Urutan ini sengaja memisahkan diagnosis dari penghapusan. Jika file tersebut merupakan bukti runaway job atau insiden keamanan, menghapusnya lebih dahulu dapat menghilangkan penjelasan. Jika file itu adalah satu-satunya backup terbaru, membebaskan ruang justru dapat menciptakan risiko yang lebih besar daripada outage awal.

Monitor byte dan inode

Pemeriksaan berkala perlu mencakup kedua dimensi. Panduan Prometheus tentang Node Exporter, misalnya, mendokumentasikan metric filesystem termasuk ruang yang tersedia bagi pengguna non-root. Monitoring stack lain dapat mengumpulkan nilai yang setara.

Tidak ada persentase peringatan universal yang bisa disebut jujur. Archive yang tumbuh perlahan dan database yang sibuk membutuhkan headroom berbeda. Sepuluh persen dapat berarti waktu berbulan-bulan pada satu volume dan hanya beberapa menit pada volume lain. Kebijakan yang lebih baik setidaknya mempertimbangkan laju pertumbuhan, waktu yang dibutuhkan manusia untuk merespons, operasi terbesar yang diperkirakan, dan apakah cleanup otomatis dapat dipercaya.

Panduan Prometheus menyarankan alert yang tetap actionable, memberi kelonggaran untuk fluktuasi kecil, dan memperlakukan capacity yang mendekati batas sebagai keadaan yang mungkin memerlukan intervensi. Karena itu, sebuah alert sebaiknya menyebut instance dan mount, membedakan tekanan byte dari tekanan inode, serta menunjuk ke runbook singkat. Alarm yang hanya mengatakan “disk high” mengundang tebakan pada saat yang paling buruk.

Ketahui kapan runbook ini belum cukup

Capacity bukan satu-satunya alasan proses write gagal. Quota dapat habis meskipun filesystem masih memiliki ruang. Filesystem dapat di-remount menjadi read-only setelah terjadi error. Permission, batas ukuran file, kerusakan storage, dan perilaku network filesystem dapat menghasilkan pesan lain. Error yang tepat pada aplikasi dan system journal tetap penting.

Tool khusus filesystem juga dapat melaporkan detail yang tidak mampu dijelaskan oleh Coreutils generik. Jika df, du, dan pemeriksaan file terbuka belum dapat menyelaraskan hasil pengamatan, tahan godaan untuk memaksakan jawaban sederhana. Simpan bukti dan baca dokumentasi untuk filesystem serta storage layer tersebut.

Kesimpulan

“No space left” adalah awal investigasi. Pertama, temukan filesystem yang terdampak, lalu pisahkan tekanan block dari tekanan inode, bandingkan filesystem accounting dengan file tree yang dapat dijangkau, dan periksa apakah suatu proses masih menahan file yang sudah dihapus. Cleanup baru dimulai setelah pemiliknya teridentifikasi.

Pelajaran yang lebih dalam bukanlah satu perintah tertentu. Capacity management bekerja ketika observasi, kepemilikan, retensi, dan alerting membentuk satu loop. Pertanyaan yang berguna bukan sekadar “Apa yang dapat dihapus sekarang?”, tetapi “Apa yang tumbuh, mengapa tidak ada cukup waktu untuk bereaksi, dan bukti apa yang dapat membuat respons berikutnya lebih tenang?”

References