prlimit Komutu ile Çalışan Süreçlerin Kaynak Limitlerini Görüntüleme ve Değiştirme
Bir production sisteminde gecenin ikisinde çağrı alıyorsunuz: uygulama yavaşlamış, loglar dolu, heap dump alamıyorsunuz çünkü core dump limiti sıfır. Ya da tam tersi: bir Java servisi tüm dosya tanıtıcılarını yemiş, yeni bağlantı kabul edemez hale gelmiş. Bu tür anlarda /proc/PID/limits dosyasına bakıp “tamam, şimdi ne yapacağız?” diye düşünüyorsunuz. İşte prlimit tam bu noktada devreye giriyor.
prlimit Nedir ve Neden Önemlidir?
prlimit, çalışan bir sürecin kaynak limitlerini hem görüntülemenizi hem de o süreç yeniden başlatılmadan, anında değiştirmenizi sağlayan bir komut satırı aracıdır. util-linux paketinin parçası olan bu araç, aslında kernel’ın prlimit64() sistem çağrısını kullanıcı alanına taşıyan bir sarmalayıcıdır.
Klasik ulimit komutundan temel farkı şudur: ulimit yalnızca mevcut shell oturumu için ve o oturumdan başlatılacak yeni süreçler için geçerlidir. Halihazırda çalışan bir sürece dokunmaz. prlimit ise PID vererek doğrudan çalışan bir süreci hedef alabilir. Prodüksiyonda uygulama durdurup başlatmak çoğunlukla bir seçenek değildir, bu yüzden prlimit gerçek anlamda hayat kurtaran bir araç haline gelir.
Linux 3.2 kernel’ından itibaren prlimit64() sistem çağrısı mevcut, ama prlimit komutunun kullanılabilir olup olmadığını kontrol etmek için:
prlimit --version
Eğer sistemde yoksa:
# Debian/Ubuntu tabanlı sistemler için
apt install util-linux
# RHEL/CentOS/Rocky tabanlı sistemler için
yum install util-linux
Neredeyse her modern dağıtımda zaten kurulu gelir.
Temel Kullanım: Süreç Limitlerini Görüntüleme
Bir sürecin tüm limitlerini görmek için sadece PID’i vermeniz yeterli:
prlimit --pid 1234
Bu komutun çıktısı yaklaşık olarak şöyle görünür:
RESOURCE DESCRIPTION SOFT HARD UNITS
AS address space limit unlimited unlimited bytes
CORE max core file size 0 unlimited bytes
CPU CPU time unlimited unlimited seconds
DATA max data size unlimited unlimited bytes
FSIZE max file size unlimited unlimited bytes
LOCKS max number of file locks held unlimited unlimited
MEMLOCK max locked-in-memory address space 65536 65536 bytes
MSGQUEUE max bytes in POSIX mqueues 819200 819200 bytes
NICE max nice prio allowed to raise 0 0
NOFILE max number of open files 1024 4096
NPROC max number of processes 15000 15000
RSS max resident set size unlimited unlimited bytes
RTPRIO max real-time priority 0 0
RTTIME timeout for real-time tasks unlimited unlimited microsecs
SIGPENDING max number of pending signals 15000 15000
STACK max stack size 8388608 unlimited bytes
Buradaki SOFT ve HARD limit ayrımını doğru anlamak kritik:
- SOFT limit: Sürecin şu anda fiilen uyguladığı limit. Süreç kendi kendine bu değeri artırabilir, ancak HARD limitin üzerine çıkamaz.
- HARD limit: Root olmayan kullanıcılar için tavan değerdir. Sadece root bu değeri artırabilir.
Belirli bir kaynağa odaklanmak için --resource bayrağını kullanabilirsiniz:
# Sadece açık dosya limiti
prlimit --pid 1234 --nofile
# Sadece core dump boyutu
prlimit --pid 1234 --core
# Sadece process sayısı
prlimit --pid 1234 --nproc
Limit Değiştirme: Syntax ve Örnekler
Limit değiştirme sözdizimi şöyledir:
prlimit --kaynak=soft:hard --pid PID
Değer olarak sayısal bir rakam ya da unlimited kullanabilirsiniz. Sadece soft veya sadece hard değiştirmek için tek taraflı da yazabilirsiniz:
# Hem soft hem hard limit belirle
prlimit --nofile=8192:16384 --pid 1234
# Sadece soft limit değiştir (hard değişmez)
prlimit --nofile=8192: --pid 1234
# Sadece hard limit değiştir
prlimit --nofile=:16384 --pid 1234
# Her ikisini unlimited yap (root gerektirir)
prlimit --nofile=unlimited:unlimited --pid 1234
Core dump’ı etkinleştirmek, o anlık debug senaryolarında sık yapılan işlemlerden biridir:
# Çalışan sürece sınırsız core dump yetkisi ver
prlimit --core=unlimited:unlimited --pid 9876
Gerçek Dünya Senaryo 1: Java Uygulaması “Too Many Open Files” Hatası
Bu senaryoyu muhtemelen hepiniz yaşamıştır. Bir Spring Boot uygulaması production’da birkaç saat çalıştıktan sonra log dosyasına java.io.IOException: Too many open files düşüyor. Uygulama yeni HTTP bağlantılarını, veritabanı connection’larını reddediyor.
İlk adım: mevcut durumu anlamak.
# Servisin PID'ini bul
systemctl status myapp.service | grep "Main PID"
# ya da
pgrep -f "myapp.jar"
# Mevcut limiti kontrol et
prlimit --pid 12345 --nofile
Çıktı: NOFILE: SOFT=1024, HARD=4096 gibi bir şey görüyorsanız, sorunun kaynağı ortada. Systemd’nin varsayılan limiti 1024 olabilir ve bir connection-heavy uygulama için bu yetersizdir.
# Şu an kaç dosya açık?
ls -l /proc/12345/fd | wc -l
# Hangi dosyalar açık, detaylı bak
ls -la /proc/12345/fd/ | tail -20
Şimdi uygulamayı durdurmadan limiti artırıyoruz:
# Soft ve hard limiti artır
sudo prlimit --nofile=65536:65536 --pid 12345
# Değişikliği doğrula
prlimit --pid 12345 --nofile
Bu anlık çözüm. Kalıcı çözüm için systemd unit dosyasına LimitNOFILE=65536 eklemeniz gerekir, ama gece ikisinde önce yangını söndürürsünüz, sabah kalıcı düzeltmeyi yaparsınız.
Gerçek Dünya Senaryo 2: PostgreSQL ve Shared Memory Limitleri
PostgreSQL, shared_buffers parametresini büyük tuttuğunuzda bazen başlamayı bile reddedebilir ya da başladıktan sonra bellek tahsis hataları verebilir. Özellikle MEMLOCK limiti bazı durumlarda kritik hale gelir.
# PostgreSQL process PID'ini bul
pgrep -u postgres -f "postgres: checkpointer"
# Bellek limitlerini incele
prlimit --pid $(pgrep -u postgres -f "postgres: checkpointer" | head -1)
Daha spesifik olarak:
# Stack ve data segment limitlerini kontrol et
prlimit --pid $PG_PID --stack
prlimit --pid $PG_PID --data
prlimit --pid $PG_PID --memlock
Huge pages kullanıyorsanız ve vm.nr_hugepages ayarladıysanız, PostgreSQL’in bellek kilit limitini de artırmanız gerekebilir:
sudo prlimit --memlock=unlimited:unlimited --pid $PG_PID
Gerçek Dünya Senaryo 3: Yeni Süreç Başlatırken Limit Belirlemek
prlimit sadece çalışan süreçlere müdahale etmez, yeni bir süreci belirli limitlerle başlatmanıza da izin verir:
# Belirli limitlerle yeni bir komut çalıştır
prlimit --nofile=2048:2048 --nproc=100:100 -- /usr/local/bin/myapp
# Stress test yaparken CPU süresi kısıtla (test ortamları için)
prlimit --cpu=30 -- stress --cpu 4
# Bir scripti sınırlı kaynaklarla test et
prlimit --as=536870912:536870912 -- ./memory-hungry-script.sh
Bu özellikle test ve sandbox ortamlarında son derece kullanışlıdır. Bir uygulamanın belirli kısıtlamalar altında nasıl davrandığını görmek istediğinizde, container kurmak yerine direkt prlimit ile çalıştırabilirsiniz.
Script ile Toplu Süreç Analizi
Birden fazla süreci aynı anda incelemek istediğinizde küçük bir script işinizi görecektir:
#!/bin/bash
# Belirli bir kullanıcıya ait süreçlerin NOFILE limitlerini listele
TARGET_USER=${1:-"www-data"}
echo "Kullanici: $TARGET_USER icin NOFILE limitleri"
echo "================================================"
for pid in $(pgrep -u "$TARGET_USER"); do
cmdline=$(cat /proc/$pid/cmdline 2>/dev/null | tr '' ' ' | cut -c1-40)
limits=$(prlimit --pid $pid --nofile --output=SOFT,HARD --noheadings 2>/dev/null)
if [ -n "$limits" ]; then
printf "PID: %-8s NOFILE: %-20s CMD: %sn" "$pid" "$limits" "$cmdline"
fi
done
Bu scripti çalıştırdığınızda www-data kullanıcısı altındaki tüm nginx, php-fpm gibi süreçlerin dosya limitleri bir arada görünür. Kapasitede sorun yaşayan süreci hızla tespit edebilirsiniz.
/proc/PID/limits ile Karşılaştırma
prlimit aslında /proc/PID/limits dosyasını okumanın daha pratik bir yolu. İkisi de aynı veriye erişir:
# Manuel olarak /proc üzerinden okuma
cat /proc/1234/limits
# prlimit ile aynı bilgi, daha okunaklı format
prlimit --pid 1234
prlimitin avantajı hem okuma hem yazma yapabilmesi ve çıktı formatını özelleştirebilmenizdir:
# Sadece belirli sütunları göster
prlimit --pid 1234 --output=RESOURCE,SOFT,HARD,UNITS
# Başlık satırı olmadan çıktı al (script'lerde kullanım için)
prlimit --pid 1234 --nofile --noheadings
# Ham sayısal değerler (bytes olarak, human-readable değil)
prlimit --pid 1234 --raw
--raw bayrağı özellikle değerleri script içinde işleyecekseniz çok işe yarar, çünkü unlimited yerine gerçek kernel limitini sayısal olarak gösterir.
systemd ve prlimit Birlikte Kullanımı
Modern sistemlerde servisler systemd üzerinden yönetilir ve prlimit ile yaptığınız anlık değişiklikler servis yeniden başlatıldığında kaybolur. Bu yüzden prlimiti geçici müdahale için kullanırken, kalıcı çözüm için systemd unit dosyasını düzenlemeniz gerekir.
Ancak systemd’nin mevcut bir servis için anlık limit değişikliklerine nasıl tepki verdiğini test etmek için prlimit harika bir araçtır:
# Systemd servisinin PID'ini öğren
MAIN_PID=$(systemctl show myservice --property=MainPID --value)
# Mevcut limitleri kaydet (rollback için)
prlimit --pid $MAIN_PID > /tmp/original_limits_$(date +%Y%m%d_%H%M%S).txt
# Yeni limit uygula
sudo prlimit --nofile=65536:65536 --pid $MAIN_PID
# Test et, sorun yoksa unit dosyasını düzenle
sudo systemctl edit myservice
systemctl edit ile açılan dosyaya şunu eklersiniz:
[Service]
LimitNOFILE=65536
Bu sayede bir sonraki başlatmada limit otomatik olarak uygulanır.
Güvenlik ve Yetki Konuları
prlimit ile limit değiştirirken yetki meselesi önemlidir:
- Root olmayan kullanıcılar yalnızca kendi süreçlerinin limitlerini değiştirebilir ve soft limiti mevcut hard limitin üzerine çıkaramazlar.
- Root tüm süreçlerin limitlerini değiştirebilir ve hard limitleri de artırabilir.
- Bir sürecin limitini görüntülemek genellikle kısıtlı değildir ama farklı kullanıcıya ait süreçlerde
/proc/PID/limitsokuma yetkisi gerekebilir.
# Kendi sürecin limitlerini gör (her zaman çalışır)
prlimit --pid $$
# Başka kullanıcıya ait süreç (root gerekebilir)
sudo prlimit --pid 1234
# Limit artırma her zaman root gerektirir
sudo prlimit --nofile=65536:65536 --pid 1234
Özellikle RLIMIT_NPROC limitine dikkat edin. Eğer bir uygulama çok fazla thread ya da process üretiyor ve bu limit düşükse, fork() çağrıları başarısız olur. Bu da bazen çok garip hata mesajlarına yol açar:
# nproc limitini kontrol et
prlimit --pid $APP_PID --nproc
# Gerekirse artır
sudo prlimit --nproc=32768:32768 --pid $APP_PID
Yararlı Kombinasyonlar ve Tek Satırlıklar
Günlük işlerde sık kullanabileceğiniz bazı kombinasyonlar:
# Sistemdeki tüm Java processlerinin NOFILE limitlerini listele
for pid in $(pgrep java); do
echo -n "PID $pid: "
prlimit --pid $pid --nofile --noheadings --output=SOFT,HARD
done
# Bir sürece core dump yetkisi ver ve nerede dump alınacağını belirle
sudo prlimit --core=unlimited:unlimited --pid $APP_PID
echo "/tmp/core-%e-%p" | sudo tee /proc/sys/kernel/core_pattern
# Tüm nginx worker processlerine toplu limit uygula
for pid in $(pgrep nginx); do
sudo prlimit --nofile=65536:65536 --pid $pid
echo "PID $pid guncellendi"
done
# Bir süreci sınırlı CPU süresiyle başlatıp izle
prlimit --cpu=60 -- /usr/bin/heavy-computation &
COMP_PID=$!
echo "Süreç $COMP_PID başlatıldı, 60 saniye CPU süresi var"
wait $COMP_PID
echo "İşlem tamamlandı"
Monitoring ve Alerting İçin Kullanım
prlimiti monitoring scriptlerine entegre edebilirsiniz. Örneğin, bir sürecin açık dosya sayısı soft limitinin yüzde seksenine ulaştığında uyarı vermek:
#!/bin/bash
# Dosya tanıtıcı kullanımını izle ve uyar
check_fd_usage() {
local pid=$1
local service_name=$2
soft_limit=$(prlimit --pid $pid --nofile --noheadings --raw --output=SOFT 2>/dev/null)
current_open=$(ls /proc/$pid/fd 2>/dev/null | wc -l)
if [ -z "$soft_limit" ] || [ "$soft_limit" = "18446744073709551615" ]; then
return 0 # unlimited, sorun yok
fi
usage_percent=$((current_open * 100 / soft_limit))
if [ $usage_percent -gt 80 ]; then
echo "UYARI: $service_name (PID: $pid) dosya tanıticisi kullanimi %$usage_percent"
echo " Acik: $current_open / Limit: $soft_limit"
fi
}
# Kritik servisleri kontrol et
for service in nginx php-fpm postgres; do
pid=$(pgrep -f $service | head -1)
if [ -n "$pid" ]; then
check_fd_usage $pid $service
fi
done
Bu scripti cron’a atıp her beş dakikada bir çalıştırabilirsiniz. Üretimde dosya tanıtıcı tükenmesini proaktif olarak yakalamak büyük değer taşır.
Sonuç
prlimit, sistem yöneticilerinin araç çantasında haksız yere göz ardı edilen ama kritik anlarda gerçekten fark yaratan bir araçtır. ulimitin yeniden başlatma gerektiren kısıtlamalarından kurtulup, çalışan bir sürece anında ve hassas müdahale imkanı sunar.
Özellikle şu senaryolarda prlimit olmadan iş çıkarmak güçleşir: yüksek trafikli dönemlerde dosya tanıtıcı tükenmesi, anlık debug için core dump etkinleştirme, belirli kısıtlamalar altında uygulama davranışını test etme ve monitoring scriptlerinde kaynak kullanım oranlarını takip etme.
Kernel desteklediği sürece prlimit güvenilir ve öngörülebilir çalışır. Yaptığınız değişiklikler anında etkili olur, süreç yeniden başlatmayı beklemez. Ancak şunu unutmayın: prlimit ile yapılan değişiklikler geçicidir. Kalıcı çözüm için systemd unit dosyaları, /etc/security/limits.conf veya /etc/security/limits.d/ altındaki konfigürasyon dosyaları doğru yerdir.
Bir sonraki “Too many open files” alarmında, önce prlimit ile durumu stabilize edin, sonra sakin kafayla kalıcı konfigürasyonu yapın. Gecenin ikisinde ayakta tutmanızın değeri budur zaten.
