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/limits okuma 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.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir