Linux’ta Süreç Sonlandırma Sanatı: kill ve killall Komutları
Bir production sunucusunda gece yarısı bir süreç çıldırıyor, CPU’yu %100 yiyor ve sistemi felç ediyor. Elleriniz titreyerek terminale bağlanıyorsunuz. İşte tam bu anda kill ve killall komutlarını doğru bilmek ile yanlış bilmek arasındaki fark, saatlik kesinti ile 30 saniyelik müdahale arasındaki fark oluyor.
Bu yazıda Linux süreç yönetiminin temel taşlarından olan kill ve killall komutlarını, sinyal mekanizmasını ve gerçek dünya senaryolarını ele alacağız.
Sinyal Sistemi: kill Aslında Ne Yapar?
Bir çok kişi kill komutunu duyduğunda “süreci öldürür” diye düşünür. Ama bu tam olarak doğru değil. kill komutu aslında bir sürece sinyal gönderir. Bu sinyal bir sonlandırma sinyali olabilir, ama başka şeyler de olabilir.
Linux kernel’i onlarca farklı sinyal türünü destekler. Bunların tam listesini görmek için:
kill -l
Çıktı şöyle görünür:
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL
5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE
9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2
13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT
...
En çok kullandığımız sinyaller şunlar:
- SIGTERM (15): Kibarca “lütfen kapat” mesajı. Süreç bu sinyali yakalayabilir, temizlik yapabilir ve kapanabilir.
- SIGKILL (9): Zorla, anında sonlandırma. Kernel seviyesinde çalışır, süreç bu sinyali yakalayamaz veya görmezden gelemez.
- SIGHUP (1): Genellikle konfigürasyon yeniden yükleme için kullanılır. Daemon’lara “ayarlarını yeniden oku” demek için idealdir.
- SIGINT (2): Terminalde Ctrl+C bastığınızda gönderilen sinyal.
- SIGSTOP (19): Süreci dondurur, sonlandırmaz.
- SIGCONT (18): Dondurulmuş süreci devam ettirir.
kill Komutu: Temel Kullanım
PID ile Süreç Sonlandırma
kill komutunun en temel kullanımı PID numarası ile çalışmaktır. Önce süreci bulmanız gerekir:
# Sürecin PID'ini bul
ps aux | grep nginx
# veya
pgrep nginx
# Kibarca sonlandır (SIGTERM gönderir, varsayılan sinyal 15'tir)
kill 1234
# Zorla sonlandır (SIGKILL)
kill -9 1234
# veya
kill -SIGKILL 1234
# veya
kill -KILL 1234
Üç yazım biçimi de aynı işi yapar. Ben genellikle -9 kısayolunu kullanıyorum ama ekip ortamında -SIGKILL yazmak daha okunabilir.
Sinyal Numarası veya İsmi ile Kullanım
# SIGHUP ile nginx konfigürasyonunu yeniden yükle
kill -1 $(pgrep nginx)
kill -HUP $(pgrep nginx)
kill -SIGHUP $(pgrep nginx)
# Süreci dondur
kill -STOP 5678
# Dondurulmuş süreci devam ettir
kill -CONT 5678
Birden Fazla Süreci Aynı Anda Sonlandırma
# Birden fazla PID'e aynı anda sinyal gönder
kill -9 1234 5678 9012
# pgrep ile birlikte kullanım
kill -15 $(pgrep -d ' ' python)
killall Komutu: İsme Göre Sonlandırma
kill komutu PID ile çalışırken killall doğrudan süreç adıyla çalışır. Bu büyük bir kolaylık sağlar.
# Tüm nginx süreçlerini kibarca sonlandır
killall nginx
# Tüm nginx süreçlerini zorla sonlandır
killall -9 nginx
# Belirli bir kullanıcıya ait süreçleri sonlandır
killall -u www-data php-fpm
# Etkileşimli mod: her süreç için onay ister
killall -i firefox
# Belirli bir sürüm numarasıyla eşleşen süreçleri sonlandır
killall -e "python3.9"
killall ile Sinyal Gönderme
# Apache'ye konfigürasyon yeniden yükleme sinyali gönder
killall -HUP apache2
# Tüm sleep süreçlerini durdur
killall -STOP sleep
# Bekleme süresiyle birlikte kullanım: önce SIGTERM, belirli süre sonra zorla
killall -TERM mysqld
sleep 10
killall -KILL mysqld 2>/dev/null
pkill: kill ve killall’ın Kardeşi
pkill komutunu da bu noktada atlamamak gerekir. Pattern matching desteğiyle çok güçlü bir araçtır:
# İsme göre sonlandır (regex destekler)
pkill nginx
# Tam isim eşleşmesi
pkill -x nginx
# Belirli bir kullanıcının süreçlerini sonlandır
pkill -u deploy python
# Terminal'e göre sonlandır
pkill -t pts/2
# Belirli bir süreçten daha yeni başlamış olanları sonlandır
pkill --newer /tmp/lockfile myapp
Gerçek Dünya Senaryoları
Senaryo 1: Zombi Süreç Temizliği
Zombi süreçler hafızanızı yemez ama PID tablosunu doldurur ve rahatsız edicidir. Zombi süreci direkt kill edemezsiniz, parent sürecini bulmanız gerekir:
# Zombi süreçleri listele
ps aux | awk '$8 == "Z" {print}'
# Zombi sürecin parent PID'ini bul (PPID sütununa bak)
ps -o ppid= -p <zombie_pid>
# Parent'a SIGCHLD gönder (zombiyi temizlemesini ister)
kill -SIGCHLD <parent_pid>
# Eğer bu işe yaramazsa parent'ı tamamen sonlandır
kill -9 <parent_pid>
Senaryo 2: Askıda Kalan Web Sunucusu Worker’ları
Production’da PHP-FPM worker’larının bazen askıda kaldığını görürsünüz. Yeni istekler gelemiyor ama süreçler ölmüyor:
# Belirli bir süreden fazladır çalışan PHP-FPM worker'larını bul ve sonlandır
# Önce durumu kontrol et
ps aux | grep php-fpm | grep -v grep
# Sadece www kullanıcısına ait olanları sonlandır
pkill -u www-data -SIGQUIT php-fpm
# Konfigürasyonu yeniden yükle (graceful reload)
killall -USR2 php-fpm
# Eğer graceful işe yaramazsa
killall -9 php-fpm
systemctl start php-fpm
Senaryo 3: Runaway Python Script
Bir data processing scripti kontrolden çıktı ve diskle CPU’yu mahvediyor:
# Süreci bul
ps aux | grep python | grep -v grep
# Çıktı:
# deploy 15234 99.8 2.1 450234 87654 ? R 14:23 45:12 python3 data_processor.py
# Önce kibarca dene
kill -15 15234
# 5 saniye bekle, hala çalışıyor mu kontrol et
sleep 5
kill -0 15234 2>/dev/null && echo "Hala caliyor" || echo "Kapandi"
# Hala çalışıyorsa zorla sonlandır
kill -9 15234
# Temizlik: bu script'in açtığı geçici dosyaları temizle
find /tmp -name "data_processor_*" -delete
kill -0 sinyali sürece hiçbir şey göndermez ama sürecin var olup olmadığını kontrol etmenin harika bir yoludur.
Senaryo 4: Graceful Shutdown Script’i
Production ortamında acele etmeden, temiz bir kapatma prosedürü uygulamak istersiniz:
#!/bin/bash
# graceful_shutdown.sh
APP_NAME="myapp"
TIMEOUT=30
echo "[$APP_NAME] Graceful shutdown baslatiliyor..."
# Süreci bul
PID=$(pgrep -x "$APP_NAME")
if [ -z "$PID" ]; then
echo "[$APP_NAME] Surc bulunamadi, cikiliyor."
exit 0
fi
echo "[$APP_NAME] PID $PID'e SIGTERM gonderiliyor..."
kill -TERM "$PID"
# Kapanmasını bekle
COUNTER=0
while kill -0 "$PID" 2>/dev/null; do
if [ "$COUNTER" -ge "$TIMEOUT" ]; then
echo "[$APP_NAME] Timeout! SIGKILL gonderiliyor..."
kill -KILL "$PID"
break
fi
sleep 1
COUNTER=$((COUNTER + 1))
echo "[$APP_NAME] Bekleniyor... ($COUNTER/$TIMEOUT)"
done
echo "[$APP_NAME] Surc sonlandirildi."
Senaryo 5: Belirli Porta Bağlı Süreci Sonlandırma
3000 portunu kullanan süreci bulmak ve sonlandırmak sık karşılaşılan bir durumdur:
# Hangi süreç 3000 portunu kullanıyor?
lsof -ti:3000
# Tek satırda bul ve sonlandır
kill -9 $(lsof -ti:3000)
# Daha güvenli versiyon
PID=$(lsof -ti:3000)
if [ -n "$PID" ]; then
echo "Port 3000'i kullanan PID: $PID sonlandiriliyor..."
kill -9 "$PID"
echo "Tamamlandi."
else
echo "Port 3000 kullanilmiyor."
fi
# fuser ile alternatif
fuser -k 3000/tcp
Dikkat Edilmesi Gereken Noktalar
SIGKILL’i Her Zaman Kullanmayın
kill -9 her sorunu çözer gibi görünür ama bazı sorunlara yol açabilir:
- Veritabanı bozulması: MySQL veya PostgreSQL SIGKILL ile kapatılırsa InnoDB/WAL dosyaları tutarsız kalabilir. Her zaman önce
SIGTERMdeneyin. - Geçici dosya birikimi: Uygulama kendi temizliğini yapamaz.
- Network bağlantıları: Açık TCP bağlantıları TIME_WAIT durumunda kalabilir.
- Lock dosyaları: Bazı uygulamalar lock dosyası bırakır ve tekrar başlamaz.
Altın kural: Önce SIGTERM, bekle, sonra SIGKILL.
root Dikkatli Kullanın
# BU KOMUTU ASLA CALISTIRMAYIN (sistemi tamamen cokertir)
kill -9 -1 # Tum sureclere SIGKILL gonderir, init dahil
# Belirli bir kullanicinin tum sureclerini sonlandirmak icin
pkill -u baduser
# veya
killall -u baduser
kill -9 -1 komutu sistemdeki tüm süreçlere SIGKILL gönderir. Root olarak bunu yanlışlıkla çalıştırırsanız sisteminiz anında çökücektir.
Kullanışlı Kombinasyonlar
awk ve ps ile Bellek Yiyen Süreçleri Temizleme
# %5'ten fazla RAM kullanan surecleri bul ve sonlandir (dikkatli kullanin!)
ps aux | awk 'NR>1 && $4>5.0 {print $2}' | xargs kill -15
# CPU kullanimi yuksek surecleri listele, sonlandirmadan once gozden gecir
ps aux --sort=-%cpu | head -10
# En fazla CPU kullanan ilk 3 süreci bul
ps aux --sort=-%cpu | awk 'NR>1 && NR<=4 {print $2, $3, $11}'
Özet: Hangi Durumda Hangi Yaklaşım?
- Normal kapatma:
killveyakill -15(SIGTERM) - Servis yeniden yükleme:
kill -HUPveyakillall -HUP servisadi - Son çare zorla kapatma:
kill -9 - İsme göre toplu kapatma:
killall servisadi - Pattern ile kapatma:
pkill -f "pattern" - Port’a göre kapatma:
fuser -k port/tcp - Kullanıcıya göre kapatma:
pkill -u kullanici
Sonuç
kill, killall ve pkill komutları Linux sistem yönetiminin vazgeçilmez araçlarıdır. Ama bu araçları kullanırken acele etmemek gerekir. Her seferinde önce SIGTERM deneyin, uygulamanın temiz kapanmasına fırsat verin. Veritabanı sunucuları, mesaj kuyrukları ve stateful uygulamalar için bu özellikle kritiktir.
Sinyal mekanizmasını anlamak sadece “süreci öldürmek” için değil, servis yönetimi, graceful reload, freeze ve continue gibi gelişmiş senaryolar için de işinize yarayacak. Bir dahaki sefere gece yarısı bir süreç çıldırdığında, artık doğru sinyali doğru şekilde gönderebileceksiniz.
Son olarak: production’da test etmeden önce staging’de deneyin. kill -9‘un ne yaptığını zaten biliyorsunuz, ama uygulamanızın buna nasıl tepki verdiğini de bilmeniz gerekir.