kill ve killall Komutu ile Süreç Sonlandırma Teknikleri

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 SIGTERM deneyin.
  • 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: kill veya kill -15 (SIGTERM)
  • Servis yeniden yükleme: kill -HUP veya killall -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.

Yorum yapın