Bir sunucu yavaşlamaya başladığında, disk dolmadığında, CPU da çıkmaz değilken ve ağ da sorunsuzken, gözler hemen RAM’e kayar. Peki ya RAM doluymuş gibi görünüyor ama neden dolduğunu tam olarak tespit edemiyorsanız? İşte bu noktada klasik top veya free komutları yetersiz kalmaya başlıyor. Paylaşımlı bellek, yazarken kopyala (copy-on-write) mekanizmaları ve çok sayıda çalışan process düşünüldüğünde, “bu process ne kadar RAM yiyor?” sorusunun cevabı sandığınızdan çok daha karmaşık. smem tam bu karmaşıklığı çözmek için var.
smem Nedir ve Neden Farklıdır?
smem, Linux sistemlerinde bellek kullanımını gerçekçi biçimde raporlayan bir araçtır. Klasik araçlardan farkını anlamak için önce Linux’un belleği nasıl hesapladığını bilmek gerekiyor.
Bir process başladığında, işletim sistemi o process için bellek ayırır. Ama modern sistemlerde işler bu kadar basit değil. Birçok process aynı kütüphaneleri (örneğin libc) paylaşır. Bu paylaşımlı bellek bölgelerine shared memory denir. top veya ps gibi araçlar genellikle VSZ (Virtual Size, sanal bellek) ve RSS (Resident Set Size, fiziksel RAM’de bulunan kısım) değerlerini gösterir.
Sorun şu: RSS, paylaşımlı belleği her process için tam olarak sayar. Yani 10 process aynı 10 MB’lık kütüphaneyi paylaşıyorsa, RSS toplamı 100 MB gösterir. Ama gerçekte bu 10 MB sadece bir kez bellekte bulunuyor.
smem ise üç farklı metrik sunar:
- USS (Unique Set Size): Sadece o processe ait, hiçbir başka processle paylaşılmayan bellek miktarı. Process öldüğünde gerçekten serbest kalacak bellek budur.
- PSS (Proportional Set Size): Paylaşımlı belleği, onu kullanan process sayısına bölerek hesaplar. 10 process 10 MB paylaşıyorsa, her birine 1 MB yazar. Sistem genelinde en gerçekçi toplamı bu verir.
- RSS (Resident Set Size): Klasik RSS değeri, karşılaştırma için gösterilir.
Bellek sızıntısı tespitinde en değerli metrik USS‘dir. Bir process’in USS değeri sürekli artıyorsa, o process belleği tahsis edip serbest bırakmıyor demektir.
Kurulum
smem çoğu dağıtımda paket deposunda mevcuttur:
# Debian/Ubuntu
sudo apt install smem
# RHEL/CentOS/Rocky Linux
sudo dnf install smem
# Arch Linux
sudo pacman -S smem
# Fedora
sudo dnf install smem
Python tabanlı bir araç olduğundan Python 3 de sistemde kurulu olmalıdır. Kurulum sonrası çalışıp çalışmadığını doğrulamak için:
smem --version
Temel Kullanım
smem‘i parametresiz çalıştırdığınızda, o anki kullanıcının processlerini listeler:
smem
Çıktı şu şekilde görünür:
PID User Command Swap USS PSS RSS
1842 ahmet bash 0 668 782 2100
2341 ahmet vim /etc/nginx/nginx.conf 0 4512 5021 11200
2890 ahmet python3 monitor.py 0 12400 13100 18900
Tüm kullanıcıların processlerini görmek için root yetkisiyle veya sudo ile çalıştırın:
sudo smem
Sıralama Seçenekleri
Bellek sızıntısı tespitinde en çok kullandığım parametre USS’e göre azalan sıralamadır:
sudo smem -s uss -r
- -s: Sıralama kriteri (uss, pss, rss, swap, pid, user, command)
- -r: Reverse, yani azalan sıra (büyükten küçüğe)
PSS’e göre sıralamak için:
sudo smem -s pss -r
Önemli Parametreler
- -k: Değerleri kilobyte yerine insan okuyabilir formatta gösterir (KB, MB, GB)
- -s [alan]: Belirtilen alana göre sırala
- -r: Sıralamayı tersine çevir
- -u: Kullanıcı bazında özet göster
- -m: Bellek haritası (mapping) bazında göster
- -w: Sistem geneli özeti göster
- -P [regex]: Process adına göre filtrele
- -U [kullanici]: Belirli kullanıcının processlerini filtrele
- -n: Başlık satırını gizle
- -t: Toplam satırı ekle
- -p: Yüzde olarak göster
- –pie: Pasta grafik oluştur (grafik ortamda)
- –bar: Bar grafik oluştur
Gerçek Dünya Senaryosu 1: Web Sunucusu Bellek Sızıntısı
Diyelim ki bir production PHP-FPM sunucunuz var ve her gece 03:00’te yeniden başlatılıyor çünkü aksi takdirde sistem belleği tükenip web sitesi çöküyor. Klasik bir bellek sızıntısı vakası.
Önce PHP-FPM processlerinin anlık durumuna bakalım:
sudo smem -k -s uss -r -P php-fpm
Bu komut tüm php-fpm processlerini USS’e göre sıralar ve insan okuyabilir format kullanır. Çıktıda şuna benzer bir şey göreceksiniz:
PID User Command Swap USS PSS RSS
12341 www-data php-fpm: worker process 0 145.2M 148.1M 162.3M
12289 www-data php-fpm: worker process 0 134.8M 137.6M 151.2M
12201 www-data php-fpm: worker process 0 98.4M 101.2M 115.8M
12156 www-data php-fpm: worker process 0 45.2M 48.1M 62.3M
12089 www-data php-fpm: master process 0 12.1M 13.4M 18.2M
Worker processlerin birbirinden bu kadar farklı USS değerleri göstermesi alarm verici. En eski process (düşük PID) en fazla belleği tutuyor. Bu, zaman içinde biriken sızıntının klasik göstergesi.
Şimdi bu durumu belirli aralıklarla izleyelim. Basit bir bash scripti:
#!/bin/bash
# php_memory_watch.sh
LOG_FILE="/var/log/php_memory_leak.log"
INTERVAL=300 # 5 dakikada bir
echo "Timestamp,PID,USS_KB,PSS_KB,RSS_KB" > $LOG_FILE
while true; do
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
sudo smem -n -s uss -r -P "php-fpm: worker" | while read pid user cmd swap uss pss rss; do
echo "$TIMESTAMP,$pid,$uss,$pss,$rss" >> $LOG_FILE
done
echo "--- $TIMESTAMP ---" >> $LOG_FILE
sleep $INTERVAL
done
Bu scripti çalıştırıp birkaç saat sonra loglara baktığınızda, hangi PID’lerin USS değerinin sürekli arttığını net olarak görebilirsiniz.
Gerçek Dünya Senaryosu 2: Sistem Geneli Bellek Dağılımı
Sunucunuzda ne çalıştığını ve belleğin nereye gittiğini net görmek için önce sistem özetine bakın:
sudo smem -w -k
Çıktı şuna benzer:
Area Used Cache Noncache
firmware/hardware 0 0 0
kernel image 0 0 0
kernel dynamic memory 1.2G 912.4M 311.6M
userspace memory 6.8G 234.1M 6.6G
free memory 1.1G 1.1G 0
Ardından kullanıcı bazında özet:
sudo smem -u -k -s uss -r
User Count Swap USS PSS RSS
www-data 48 0 2.1G 2.3G 2.8G
postgres 8 0 1.2G 1.2G 1.4G
redis 1 0 234.1M 235.2M 241.3M
root 23 0 145.2M 198.4M 412.3M
ahmet 6 0 45.2M 58.9M 124.1M
Bu çıktıdan görüyoruz ki www-data kullanıcısı (yani web sunucusu) toplam 2.1 GB USS tutuyor. Bu normalin üzerinde mi? Geçmiş değerlerle karşılaştırmanız gerekiyor. Bunun için düzenli cron job çalıştırmak iyi bir alışkanlık:
# /etc/cron.d/smem_monitor
*/15 * * * * root smem -u -k -s uss -r -n >> /var/log/smem_summary.log 2>&1
Gerçek Dünya Senaryosu 3: Belirli Bir Processi Derinlemesine İncelemek
Şüpheli bir process bulduğunuzda, onun hangi bellek bölgelerini kullandığını görmek için -m parametresini kullanın:
sudo smem -m -P "python3 app.py" -k
Bu komut, o process’in açtığı her bellek mapping’ini listeler. Hangi .so dosyaları, hangi anonim bellek bölgeleri var, hepsini görürsünüz.
Belirli bir PID için daha detaylı bilgi almak isterseniz, Linux’un kendi /proc filesystem’ini de kullanabilirsiniz. smem ile PID’yi tespit ettikten sonra:
# Processi bul
sudo smem -k -s uss -r | head -20
# Detaylı bellek haritası
sudo cat /proc/12341/smaps | grep -E "^(Size|Rss|Pss|Shared|Private)" |
awk '{sum[$1] += $2} END {for (key in sum) printf "%s: %d kBn", key, sum[key]}'
Bu çıktı size o processın kaynakları nasıl kullandığını çok detaylı gösterir.
Periyodik İzleme ile Sızıntı Tespiti
Bellek sızıntısını tek anlık ölçümle yakalamak zordur. Önemli olan zaman içindeki değişimi izlemek. Bunun için aşağıdaki scripti kullanabilirsiniz:
#!/bin/bash
# leak_detector.sh - Bellek sızıntısı dedektörü
# Kullanim: ./leak_detector.sh <process_adi> <esik_mb> <sure_dakika>
PROCESS_NAME="${1:-nginx}"
THRESHOLD_MB="${2:-100}"
DURATION_MIN="${3:-60}"
INTERVAL=60
ITERATIONS=$((DURATION_MIN * 60 / INTERVAL))
LOG="/tmp/leak_detect_${PROCESS_NAME}.log"
echo "Izleme basliyor: $PROCESS_NAME | Esik: ${THRESHOLD_MB}MB | Sure: ${DURATION_MIN} dakika"
echo "Timestamp | PID | USS_MB | Degisim_MB" | tee $LOG
declare -A INITIAL_USS
# Baslangic degerlerini kaydet
while IFS= read -r line; do
pid=$(echo $line | awk '{print $1}')
uss_kb=$(echo $line | awk '{print $5}')
INITIAL_USS[$pid]=$uss_kb
done < <(sudo smem -n -P "$PROCESS_NAME" 2>/dev/null)
for i in $(seq 1 $ITERATIONS); do
sleep $INTERVAL
TIMESTAMP=$(date '+%H:%M:%S')
while IFS= read -r line; do
pid=$(echo $line | awk '{print $1}')
uss_kb=$(echo $line | awk '{print $5}')
uss_mb=$((uss_kb / 1024))
initial=${INITIAL_USS[$pid]:-$uss_kb}
diff_kb=$((uss_kb - initial))
diff_mb=$((diff_kb / 1024))
echo "$TIMESTAMP | PID:$pid | USS:${uss_mb}MB | +${diff_mb}MB" | tee -a $LOG
if [ $diff_mb -gt $THRESHOLD_MB ]; then
echo "UYARI: PID $pid $THRESHOLD_MB MB esigini asti! Toplam artis: ${diff_mb}MB"
# Buraya mail veya Slack bildirimi eklenebilir
fi
done < <(sudo smem -n -P "$PROCESS_NAME" 2>/dev/null)
echo "---"
done
echo "Izleme tamamlandi. Log: $LOG"
Bu scripti şöyle çalıştırırsınız:
chmod +x leak_detector.sh
./leak_detector.sh "java" 200 120
Bu örnek java processlerini 120 dakika boyunca izler ve USS’i 200 MB’dan fazla artan processler için uyarı verir.
smem ile Swap Kullanımını Birlikte Değerlendirmek
Bellek sızıntısı zamanla swap kullanımına da yansır. smem swap bilgisini de gösterir:
sudo smem -k -s swap -r | head -20
En fazla swap kullanan processleri listeler. Swap’a düşen processlerin USS değerleri yüksekse, bu sistem hafızasının tükenmeye başladığının işaretidir. Bu durumda hem sızıntıyı bulup gidermek, hem de kısa vadeli çözüm olarak belirli processleri yeniden başlatmak gerekebilir.
Swap ve USS’yi birlikte değerlendiren bir özet almak için:
sudo smem -k -s pss -r -t | tail -5
-t parametresi en alta toplam satırı ekler. Bu toplamı düzenli aralıklarla loglamak, sisteminizin bellek trendini takip etmenizi sağlar.
Grafik Çıktı Almak
smem grafik çıktı da üretebilir. Sunucu başında X11 forwarding ile çalışıyorsanız veya yerel bir Linux masaüstü kullanıyorsanız:
# Pasta grafik - process bazında PSS
sudo smem --pie name -s pss
# Bar grafik - kullanici bazinda
sudo smem -u --bar name -s uss
Grafik çıktıyı PNG dosyasına kaydetmek için --png parametresini ekleyin:
sudo smem --pie name -s pss --png /tmp/memory_pie.png
Bu PNG’yi monitoring sistemine veya raporlara eklemek son derece kullanışlı. Özellikle management’a “neden daha fazla RAM lazım” diye anlatırken bir pasta grafik, satır satır sayılardan çok daha etkili olur.
Monitoring Sistemleriyle Entegrasyon
Zabbix veya Prometheus gibi sistemlerle entegre etmek için smem çıktısını parse etmeniz gerekiyor. İşte basit bir Prometheus textfile collector scripti:
#!/bin/bash
# smem_prometheus.sh
# /var/lib/node_exporter/textfile_collector/smem.prom dosyasini gunceller
OUTFILE="/var/lib/node_exporter/textfile_collector/smem.prom"
TMPFILE=$(mktemp)
echo "# HELP process_uss_bytes Unique Set Size in bytes" > $TMPFILE
echo "# TYPE process_uss_bytes gauge" >> $TMPFILE
sudo smem -n -s uss -r 2>/dev/null | while read pid user cmd swap uss pss rss; do
# Komut adini temizle
clean_cmd=$(echo "$cmd" | tr ' /:' '___' | cut -c1-50)
uss_bytes=$((uss * 1024))
pss_bytes=$((pss * 1024))
echo "process_uss_bytes{pid="$pid",user="$user",cmd="$clean_cmd"} $uss_bytes" >> $TMPFILE
echo "process_pss_bytes{pid="$pid",user="$user",cmd="$clean_cmd"} $pss_bytes" >> $TMPFILE
done
mv $TMPFILE $OUTFILE
chmod 644 $OUTFILE
Bunu 5 dakikada bir çalıştıran bir cron job ekleyin:
*/5 * * * * root /usr/local/bin/smem_prometheus.sh
Artık Grafana’da bu metrikleri görselleştirebilir, eşik değerlerinde alert alabilirsiniz.
smem’in Sınırları
Her araç gibi smem‘in de sınırları var:
- Yavaş çalışır:
/procfilesystem’i taradığından, çok sayıda process olan sistemlerde birkaç saniye sürebilir. Production sistemlerde sık aralıklarla çalıştırırken bu gecikmeyi göz önünde bulundurun. - Root yetkisi gerektirir: Diğer kullanıcıların processlerini görmek için root veya sudo şart.
- Kernel thread’leri göstermez: Sadece userspace processleri raporlar.
- Anlık görüntü: Sürekli izleme için kendiniz sarmalayıcı script yazmanız gerekir (ya da
watchkomutunu kullanın).
watch ile gerçek zamanlı izleme:
watch -n 5 'sudo smem -k -s uss -r | head -20'
Bu komut her 5 saniyede ekranı güncelleyerek en fazla USS kullanan 20 processi gösterir. Kısa süreli gözlem için idealdir.
Karşılaştırmalı Analiz: smem vs Diğer Araçlar
top veya htop kullandığınızda gördüğünüz RES (yani RSS) değeri, paylaşımlı belleği çok sayar. Bunu anlamak için küçük bir deney yapabilirsiniz:
# top ciktisindaki toplam RSS
ps aux | awk '{sum += $6} END {print sum/1024 " MB"}'
# smem'in PSS toplami (daha gercekci)
sudo smem -t -n | tail -1 | awk '{print $6/1024 " MB PSS"}'
Çoğu sistemde RSS toplamı, sistemdeki toplam fiziksel RAM’den daha yüksek çıkar. Oysa PSS toplamı gerçek kullanıma çok daha yakındır. Bu fark, smem‘in ne kadar değerli olduğunu gösterir.
Özet: smem Kullanım Kılavuzu Hızlı Başvuru
Sık kullandığım komutları bir araya getiriyorum:
sudo smem -k -s uss -r: En fazla unique bellek kullanan processleri listelesudo smem -u -k -s uss -r: Kullanıcı bazında bellek özetisudo smem -w -k: Sistem geneli bellek dağılımısudo smem -k -P nginx: Sadece nginx processlerini göstersudo smem -t -k: Toplam satırıyla birlikte listelesudo smem -m -P "myapp": Process bellek mapping detaylarıwatch -n 5 'sudo smem -k -s uss -r | head -15': Gerçek zamanlı izleme
Sonuç
Bellek sızıntısı, sistem yöneticilerinin en sinir bozucu problemlerinden biridir. Yavaş yavaş gerçekleşir, bazen sadece haftalar sonra kendini gösterir ve hangi processın suçlu olduğunu bulmak klasik araçlarla gerçekten zordur. smem, özellikle USS metriği sayesinde bu işi ciddi ölçüde kolaylaştırır. Paylaşımlı belleği doğru hesaplaması, sizi yanlış suçlamaların önüne geçer.
Eğer sunucunuzda henüz smem kullanmıyorsanız, bugün kurun ve sistem geneli bir USS anlık görüntüsü alın. Bu değerleri bir yere kaydedin. Bir hafta, bir ay sonra tekrar ölçün. Trendin nereye gittiğini gördüğünüzde, sorun büyümeden müdahale etme şansınız olur. Production’da reaktif değil, proaktif olmak, iyi bir sysadmin’in en temel özelliğidir.