Jawaban singkat: pada host uji Ubuntu 24.04.5, shell biasa membuka berkas dengan batas lunak 1.024 dan batas keras 1.048.576, sementara proses Node.js yang berjalan di mesin ini terukur memakai batas lunak 1.024 meski batas kerasnya 524.288. Proses Caddy di mesin yang sama memakai 1.048.576 untuk keduanya. Artinya batas 1.024 bukan bawaan kernel, melainkan nilai yang diwariskan, dan proses web dengan banyak koneksi bersamaan bisa menabraknya jauh sebelum CPU atau RAM menjadi masalah.
- TL;DR batas lunak shell 1.024, batas keras 1.048.576, dan nilai kernel nr_open juga 1.048.576.
- Proses Node.js terukur dengan batas lunak 1.024 dan keras 524.288, sementara Caddy mendapat 1.048.576 di keduanya.
- Konfigurasi systemd di host ini masih mengomentari DefaultLimitNOFILE, jadi nilai bawaan 1.024 yang berlaku.
- Total entri berkas terbuka di seluruh proses saat pengukuran: sekitar 854, jauh di bawah batas sistem.
- EMFILE adalah gejala, bukan penyakit: naikkan batas sambil tetap mencari sumber kebocoran descriptor.
Kesalahan EMFILE, kependekan dari "too many open files", adalah salah satu gangguan produksi yang paling sering disalahartikan sebagai masalah kapasitas. Kenyataannya, batas per proses di Linux biasanya masih jauh dari angka yang membuat sistem kehabisan descriptor, dan yang menabrak justru batas lunak yang diwariskan dari shell atau unit systemd. Angka di bawah ini diambil langsung dari host, bukan dari nilai bawaan dokumentasi.
Asal nilai 1.024 di Ubuntu 24.04
Karena nilai itu diwariskan dari dua tempat: konfigurasi systemd dan nilai bawaan untuk sesi login. Berkas /etc/systemd/system.conf di host ini memuat baris DefaultLimitNOFILE yang diawali tanda pagar, artinya tidak aktif, sehingga systemd memakai nilai bawaannya sendiri. Untuk sesi shell biasa, batas lunak 1.024 sudah menjadi standar sejak lama karena dinilai cukup untuk proses interaktif, dan nilai itu diwariskan ke proses anak kecuali ada yang menaikkannya secara eksplisit.
Kekeliruan yang umum adalah mengira batas keras juga 1.024. Pada host ini batas keras shell adalah 1.048.576, sama dengan nilai nr_open di kernel. Sebuah proses boleh menaikkan batas lunaknya sendiri sampai batas keras tanpa hak istimewa tambahan, dan hanya butuh hak istimewa bila ingin melewati batas keras. Jadi masalahnya bukan izin, melainkan tidak ada yang meminta kenaikan itu.
Berapa angka sebenarnya di host ini?
Pengukuran dilakukan dengan membaca /proc untuk nilai per proses dan berkas sistem untuk nilai kernel. Tidak ada perubahan konfigurasi yang dilakukan selama pengukuran, jadi angka ini menggambarkan kondisi host apa adanya.
| Sumber | Nilai | Arti |
|---|---|---|
| ulimit -n di shell | 1.024 | batas lunak yang diwariskan ke proses anak |
| /proc/self/limits | 1.024 lunak, 1.048.576 keras | batas per proses untuk shell uji |
| Proses Caddy | 1.048.576 lunak dan keras | unit systemd menaikkan batasnya |
| Proses Node.js | 1.024 lunak, 524.288 keras | batas lunak tidak dinaikkan |
| fs.nr_open | 1.048.576 | batas maksimum per proses di kernel |
| fs.file-nr | 3.072 terpakai dari batas sangat besar | pemakaian descriptor tingkat sistem |
| Entri di /proc/*/fd | sekitar 854 | deskriptor terbuka yang terlihat saat pengukuran |
Dua baris yang paling penting adalah Caddy dan Node.js. Keduanya berjalan di mesin yang sama, dengan kernel yang sama, tetapi menerima batas yang berbeda jauh. Perbedaannya bukan pada jenis proses, melainkan pada unit systemd yang menjalankannya. Proses yang batasnya dinaikkan oleh unit akan mendapat 1.048.576, sedangkan proses yang dijalankan langsung dari shell atau oleh unit tanpa pengaturan khusus akan mewarisi 1.024.
Berapa batas yang wajar untuk server web?
Tidak ada satu angka yang benar, dan memilih berdasarkan kebiasaan orang lain adalah cara cepat mendapat masalah lain. Yang bisa dihitung adalah kebutuhan minimum: jumlah koneksi bersamaan dikali jumlah deskriptor per koneksi, ditambah berkas konfigurasi dan log yang dibuka proses itu. Server web yang melayani 1.000 koneksi bersamaan dengan dua deskriptor per koneksi sudah butuh lebih dari 2.000, jadi batas 1.024 pasti terlampaui sebelum bebannya besar.
Untuk sebagian besar server web modern, batas lunak di kisaran 65.536 sudah sangat longgar, dan batas keras bisa dibiarkan di 1.048.576 sesuai nr_open. Angka besar tidak berbahaya dengan sendirinya karena batas hanyalah izin, bukan alokasi: kernel tidak menyiapkan 65.536 slot descriptor untuk setiap proses yang diizinkan memakainya.
Cara menaikkan batas per layanan
Cara yang paling rapi adalah menaikkan batas pada unit systemd milik layanan yang membutuhkan, bukan mengubah nilai global. systemd menyediakan pengaturan LimitNOFILE pada bagian Service, dan nilai itu diterapkan saat unit dijalankan ulang. Pada host ini, Caddy sudah memakai pendekatan tersebut dan hasilnya terlihat sebagai 1.048.576 pada kedua batas.
Untuk layanan yang dijalankan langsung dari shell, batas bisa dinaikkan pada sesi itu dengan perintah ulimit sebelum proses dijalankan, dan proses anak akan mewarisinya. Perlu diingat bahwa batas lunak hanya bisa dinaikkan sampai batas keras, jadi bila batas keras juga 1.024, yang perlu diubah lebih dulu adalah nilai kerasnya.
Setelah perubahan, verifikasi selalu lewat /proc, bukan lewat ingatan: baca /proc/PID/limits untuk proses yang berjalan dan pastikan baris Max open files menunjukkan nilai baru. Ini juga cara memastikan unit yang Anda sunting benar-benar yang menjalankan proses tersebut, karena pada host dengan beberapa unit serupa, kesalahan menunjuk unit adalah penyebab umum perubahan yang tampak tidak berefek.
Apakah menaikkan batas selalu jawabannya?
Tidak. EMFILE bisa muncul dari dua arah yang berbeda: batas yang terlalu rendah untuk beban sah, atau proses yang membocorkan deskriptor. Pada host ini, 854 entri descriptor terbuka tersebar di seluruh proses, angka yang wajar untuk mesin dengan web server, mail server, resolver DNS, dan beberapa layanan lain. Bila satu proses saja memegang puluhan ribu descriptor tanpa alasan yang jelas, menaikkan batas hanya menunda kegagalan.
Cara membedakannya sederhana: pantau jumlah entri di /proc/PID/fd pada proses yang bermasalah selama beberapa jam. Bila angkanya naik terus dan tidak turun setelah beban mereda, itu kebocoran, biasanya karena koneksi atau berkas yang dibuka tanpa ditutup di jalur error. Bila angkanya naik-turun mengikuti beban dan mentok tepat di batas, itu memang batas yang terlalu rendah.
Pada layanan yang memakai koneksi keluar, seperti klien basis data atau klien HTTP, pastikan juga ada batas jumlah koneksi di lapisan aplikasi. Batas kernel yang tinggi tanpa batas di aplikasi hanya memindahkan titik gagal dari EMFILE ke memori habis, dan kegagalan memori jauh lebih sulit didiagnosis daripada satu pesan error yang jelas.
Memantau pemakaian descriptor
Angka batas hanya berguna bila dipasangkan dengan angka pemakaian. Cara termurah adalah menghitung entri di direktori /proc/PID/fd untuk proses yang dicurigai. Pada host uji ini, jumlah entri di seluruh proses sekitar 854, dan angka itu bisa dijadikan garis dasar: selama totalnya stabil, tidak ada proses yang menumpuk descriptor tanpa batas.
Untuk satu proses, hitung jumlah entri setiap menit selama beberapa jam dan lihat bentuk kurvanya. Pola gigi gergaji yang naik lalu turun mengikuti beban berarti normal. Pola tangga yang hanya naik berarti ada yang membuka dan tidak menutup. Pola datar tepat di angka batas berarti proses itu sudah mentok dan setiap pembukaan baru akan gagal dengan EMFILE.
Pasangkan dengan daftar socket untuk membedakan jenis kebocoran. Bila kenaikan descriptor diikuti kenaikan jumlah koneksi di ss dengan state tertentu, sumbernya koneksi jaringan yang tidak ditutup, misalnya klien HTTP yang kehabisan waktu tanpa menutup koneksi. Bila descriptor naik tanpa kenaikan socket, sumbernya berkas biasa, sering kali berkas log yang dibuka ulang di setiap permintaan tanpa pernah ditutup.
Pada layanan yang dikelola systemd, catat juga batas yang benar-benar diterima proses, bukan batas yang tertulis di berkas konfigurasi. Membaca /proc/PID/limits setelah layanan dijalankan ulang adalah satu-satunya cara memastikan override benar-benar diterapkan. Selisih antara konfigurasi yang tertulis dan batas yang aktif adalah penyebab paling umum dari perubahan yang "sudah dilakukan tetapi tidak berefek".
Terakhir, periksa juga batas inotify bila aplikasi memantau banyak berkas. Batas itu terpisah dari open files, dan pesan errornya bisa mirip sehingga mudah tertukar. Aplikasi pemantau direktori besar bisa menghabiskan jatah watch jauh sebelum jumlah descriptor-nya mendekati batas, dan menaikkan LimitNOFILE tidak akan mengubah apa pun pada kasus itu.
Untuk peringatan dini, cukup satu ambang sederhana: bila pemakaian satu proses melewati 70 persen batas lunaknya, kirim notifikasi. Ambang itu memberi ruang untuk bereaksi sebelum kegagalan terjadi, dan tidak perlu perangkat pemantauan tambahan bila sistem Anda sudah punya penjadwal dan pengirim pesan.
FAQ
Apakah batas 1.024 berasal dari kernel?
Bukan. Kernel mengizinkan sampai 1.048.576 sesuai fs.nr_open pada host ini. Nilai 1.024 adalah batas lunak yang diwariskan dari sesi shell atau dari nilai bawaan systemd, dan bisa dinaikkan oleh proses itu sendiri sampai batas kerasnya.
Apakah menaikkan batas butuh restart server?
Untuk unit systemd, perubahan LimitNOFILE baru berlaku setelah unit dijalankan ulang, bukan setelah sistem di-reboot. Untuk proses yang dijalankan dari shell, cukup jalankan ulang prosesnya setelah ulimit diubah. Tidak ada kebutuhan untuk memuat ulang kernel.
Berapa jumlah descriptor yang normal untuk satu proses?
Bergantung pada beban. Pada host uji, total entri descriptor di seluruh proses sekitar 854, dan itu normal untuk mesin dengan beberapa layanan jaringan. Untuk satu proses web, jumlahnya wajar bila berkisar sepersekian dari jumlah koneksi bersamaan, ditambah satu untuk tiap berkas konfigurasi dan log yang dibuka.
Apakah EMFILE bisa disebabkan hal lain?
Bisa. Selain batas per proses, sistem juga punya batas global yang tercatat di fs.file-nr, dan inotify punya batas tersendiri yang bisa habis lebih dulu pada aplikasi pemantau berkas. Bila pesan errornya menyebut inotify watch, penyebabnya bukan open files dan menaikkan LimitNOFILE tidak akan menolong.
Rujukan resmi untuk nilai dan mekanisme di atas: halaman manual getrlimit(2), dokumentasi systemd.exec bagian LimitNOFILE, dan halaman manual limits.conf(5). Ketiganya menjelaskan perbedaan batas lunak, batas keras, dan batas sistem yang membuat angka 1.024 terlihat seperti batas kernel padahal bukan.
💬 Komentar (0)
Belum ada komentar. Jadilah yang pertama! 💬