Linux sunucularda file descriptor exhaustion hatası, sistem kaynaklarının kritik bir tükenmesini işaret eder ve sunucunun performansını ciddi şekilde etkileyebilir. Bu hata, süreçlerin açabileceği dosya tanımlayıcılarının (file descriptor) sistem veya süreç limitlerini aşması sonucu ortaya çıkar. Özellikle yüksek trafikli web sunucuları, veritabanı uygulamaları veya bağlantı yoğun ağ servislerinde sık rastlanır. Sunucu yanıt vermemeye başlar, yeni bağlantılar reddedilir ve loglarda “Too many open files” gibi uyarılar görülür. Bu makalede, sorunun kökenini anlayacak, teşhis edecek ve etkili çözümler uygulayacaksınız. Kurumsal ortamlar için pratik adımlar ve önleme stratejileriyle donatılmış bu rehber, sistem yöneticilerine somut bir yol haritası sunar.
File descriptor’lar, Linux’ta dosyalar, soketler, pipe’lar gibi kaynaklara erişim sağlayan tam sayılardır. Her süreç, 0 (stdin), 1 (stdout), 2 (stderr) gibi düşük numaralardan başlayarak FD’leri kullanır. Sistem genelinde /proc/sys/fs/file-max ile belirlenen maksimum limit bulunurken, her süreç için ulimit -n komutuyla soft/hard limitler tanımlanır. Varsayılan değerler genellikle 1024’tür, ancak yoğun uygulamalarda yetersiz kalır.
Limitleri kontrol etmek için ulimit -n komutunu mevcut kabukta çalıştırın; sistem genelini görmek için cat /proc/sys/fs/file-max kullanın. Bir süreçteki açık FD sayısını lsof -p PID | wc -l ile sayabilirsiniz. Bu değerler aşıldığında kernel, ENFILE veya EMFILE hataları üretir. Kurumsal sunucularda, Apache veya Nginx gibi servislerin worker süreçleri binlerce bağlantı yönetirken bu limitler hızla dolar; örneğin, her TCP soketi bir FD tüketir.
Sistem limitini artırmak için echo 2097152 > /proc/sys/fs/file-max geçici olarak uygular, kalıcı hale getirmek için /etc/sysctl.conf’a fs.file-max = 2097152 ekleyin ve sysctl -p ile yükleyin. Süreç limitleri için /etc/security/limits.conf’a şu satırları ekleyin: * soft nofile 65536 ve * hard nofile 65536. Bu, tüm kullanıcılar için soft limit 65536, hard 65536 yapar. Değişiklikleri uygulamak için ssh oturumunu yeniden başlatın veya yeni kabuk açın. Test için ulimit -n 65536 ile geçici ayarlayın.
Belirli servisler için systemd unit dosyalarında [Service] bölümüne LimitNOFILE=65536 ekleyin. Örneğin, Nginx için /lib/systemd/system/nginx.service dosyasını düzenleyin, sonra systemctl daemon-reload ve systemctl restart nginx çalıştırın. Bu yaklaşım, genel sistem yükünü artırmadan hedefe odaklanır ve yüksek bağlantılı ortamlarda önerilir.
Teşhis, açık FD’leri izleyerek başlar. lsof | awk '{print $2}' | sort | uniq -c | sort -nr | head -10 komutu en çok FD tüketen süreçleri listeler. Ağ soketleri için ss -s toplam bağlantıları, ss -anp | wc -l açık soket sayısını gösterir. Loglarda /var/log/messages veya dmesg’te “VFS: file-max limit reached” arayın. Prometheus + Node Exporter gibi araçlarla fd_usage metriğini izleyin; eşik aşıldığında uyarı kurun.
Gerçek zamanlı izleme için watch -n 1 'lsof | wc -l' kullanın. Bellek ve CPU ile ilişkilendirin; örneğin, bir MySQL sunucusu query’lerde FD biriktiriyorsa slow_query_log etkinleştirin. Kurumsal olarak, bu komutları cron job’lara entegre ederek günlük raporlar üretin.
Yaygın nedenler: Leak’ler (kapanmayan soketler), yüksek concurrency (load balancer’lar), dosya tabanlı cache’ler. Log analizi için journalctl -u nginx -g "too many" filtreleyin. Bir örnek: Nginx’te proxy bağlantıları kapanmıyorsa worker_processes artırın ve worker_connections’ı 4096’ya çıkarın (/etc/nginx/nginx.conf).
New Relic veya Zabbix ile FD metriğini dashboard’a ekleyin. Script örneği: #!/bin/bash\nopenfds=$(lsof | wc -l)\nif [ $openfds -gt 100000 ]; then echo "Uyarı: $openfds FD açık" | mail -s "FD Exhaustion" [email protected]; fi. Bu script’i crontab’a her 5 dakikada ekleyin (@reboot ile kalıcı hale getirin).
Çözümde öncelik, mevcut limitleri artırmak ve leak’leri kapatmaktır. Tüm servisleri yeniden başlatmadan önce limits.conf değişikliklerini uygulayın. Uygulama seviyesinde, Python’da with open() kullanın veya Go’da defer close(). Nginx örneğinde, keepalive_timeout 65; ve worker_rlimit_nofile 65536; direktiflerini ekleyin.
Önleme için kapasite planlaması yapın: Trafik tahminine göre file-max’ı %50 fazladan ayarlayın. Container’larda (Docker) –ulimit nofile=65536:65536 flag’ini kullanın. Düzenli audit için aylık find /proc/*/fd -type l | wc -l raporu oluşturun. Bu stratejiler, downtime’ı minimize eder ve ölçeklenebilirlik sağlar.
Leak tespiti için Valgrind veya strace kullanın: strace -p PID -e trace=file yeni FD açılışlarını izler. Java uygulamalarında -XX:+HeapDumpOnOutOfMemoryError ile birleştirin. Veritabanlarında connection pooling etkinleştirin; örneğin PostgreSQL’de max_connections 1000, effective_cache_size artırın.
Sonuç olarak, file descriptor exhaustion’ını yönetmek, proaktif izleme ve doğru konfigürasyonla mümkündür. Bu adımları uygulayarak sunucunuzun kararlılığını artırın, beklenmedik kesintileri önleyin ve kurumsal operasyonlarınızı güçlendirin. Düzenli bakım ve testlerle sisteminizi optimize edin.