Linux’ta kill komutu bir süreci doğrudan “öldürmekten” çok, belirtilen PID’ye bir sinyal gönderir. Güvenli akış; hedef PID’yi kesin olarak bulmak, komutunu doğrulamak, önce SIGTERM göndermek, sürece kapanması için süre tanımak ve yalnızca kapanamıyorsa SIGKILL kullanmaktır.
PID nedir?
PID (Process ID), çalışan bir sürecin sayısal kimliğidir. Aynı uygulamanın birden fazla örneği farklı PID’lerle çalışabilir; ayrıca bir süreç kapandıktan sonra PID daha sonra başka bir sürece verilebilir. Bu nedenle eski bir nottaki PID’yi kullanmak yerine işlemden hemen önce hedefi yeniden doğrulamak önemlidir.
Süreçleri genel olarak incelemek için:
ps aux
top
Belirli bir süreç adını tam eşleşmeyle bulmak için pgrep -x, PID ile birlikte komut satırını görmek için de -a kullanılabilir:
pgrep -a -x firefox
Uzun süreç adları veya yorumlayıcı üzerinden çalışan betikler için ad alanı yeterli olmayabilir. Böyle bir durumda pgrep -a -f tam komut satırında arama yapar; ancak daha geniş eşleşebileceği için sonucu mutlaka inceleyin.
Güvenli sonlandırma adımları
Aşağıdaki örneklerde 1234, doğruladığınız gerçek PID ile değiştirilmelidir.
1. Süreci bulun
pgrep -a -x my-app
Tek bir sonuç beklerken birden fazla PID görürseniz hepsine sinyal göndermeyin. Önce hangi örneğin hedef olduğunu belirleyin.
2. PID’nin çalıştırdığı komutu doğrulayın
ps -p 1234 -o pid,ppid,user,stat,etime,cmd
Çıktıda PID, üst süreç, kullanıcı, durum, çalışma süresi ve komut satırı birlikte görünür. Yanlış kullanıcıya veya benzer adlı başka bir servise ait süreci durdurma riskini bu adım azaltır.
STAT alanındaki ilk harf sürecin durumunu bildirir ve sinyalin nasıl karşılanacağını doğrudan etkiler:
| Harf | Anlamı |
|---|---|
R | Çalışıyor veya çalışmaya hazır |
S | Uyuyor; bekliyor fakat sinyal geldiğinde uyanır |
D | Kesintiye uğratılamaz uyku; sinyal geldiğinde uyanmaz |
T | Durdurulmuş (SIGSTOP veya Ctrl+Z) |
Z | Zombie |
İlk harften sonra gelen ekler de bilgi taşır: s sürecin oturum lideri olduğunu, + ön plandaki process group’ta bulunduğunu, l çok iş parçacıklı olduğunu gösterir. Denetleyen terminali olmayan bir daemon tipik olarak Ss görünür ve + taşımaz.
3. Önce SIGTERM gönderin
kill sinyal belirtilmediğinde varsayılan olarak SIGTERM gönderir:
kill -s TERM 1234
Sinyal adını -s ile vermek önemlidir. Kabuklarda kill hem yerleşik bir komut hem de ayrı bir program (/bin/kill, util-linux) olarak bulunur ve yerleşik olan her zaman önceliklidir. Util-linux’a ait --signal uzun seçeneğini bash ve zsh’in yerleşik kill komutu tanımaz; kill --signal TERM 1234 etkileşimli bir kabukta invalid signal specification hatası verir. -s TERM biçimi hem yerleşik komutlarda hem /bin/kill içinde çalışır ve POSIX tarafından tanımlıdır.
SIGTERM, uygulamaya kapanış işleyicisini çalıştırma fırsatı verir. Uygulama yeni istek almayı durdurabilir, açık dosyaları kapatabilir ve tamponlanmış veriyi yazabilir. Bu davranış uygulamanın sinyali nasıl ele aldığına bağlıdır; sinyalin “nazik” olması sürecin mutlaka kapanacağı anlamına gelmez.
4. Bekleyin ve durumu yeniden kontrol edin
Uygulamaya uygun bir süre tanıdıktan sonra aynı PID’yi kontrol edin:
ps -p 1234 -o pid,stat,etime,cmd
Komut başlık dışında sonuç döndürmüyorsa süreç artık yoktur. Uzun kapanış yapan veritabanı veya worker süreçlerinde bekleme süresini uygulamanın dokümantasyonuna göre seçin.
5. Yalnızca gerekirse SIGKILL kullanın
Süreç SIGTERM sonrasında kapanmıyor ve başka bir güvenli kurtarma yolu bulunmuyorsa:
kill -s KILL 1234
SIGKILL yakalanamaz, engellenemez veya yok sayılamaz. Uygulama temizleme kodunu çalıştıramadan çekirdek tarafından sonlandırılır; tamponlanmış durum, yarım yazılmış dosya veya tamamlanmamış işlem kaybı oluşabilir. Bu yüzden ilk adım değil, son çaredir.
Bir portu dinleyen süreci bulma
Örneğin TCP 8080 portunu dinleyen süreci ve PID bilgisini görmek için:
sudo ss -lptn 'sport = :8080'
Alternatif olarak lsof kuruluysa:
sudo lsof -nP -iTCP:8080 -sTCP:LISTEN
Bulduğunuz PID’yi yine ps ile doğruladıktan sonra aynı SIGTERM → bekle → gerekirse SIGKILL sırasını izleyin.
Sık kullanılan sinyaller
- SIGTERM (15): Varsayılan sonlandırma isteğidir; süreç bunu yakalayabilir veya yok sayabilir.
- SIGKILL (9): Süreci çekirdek seviyesinde sonlandırır; yakalanamaz, engellenemez veya yok sayılamaz.
- SIGHUP (1): Varsayılan davranışı sonlandırmadır. Bazı daemon’lar bunu yapılandırma yenileme olarak yorumlar, fakat bu evrensel değildir; uygulamanın belgesini kontrol edin.
- SIGSTOP: Süreci duraklatır ve
SIGKILLgibi yakalanamaz veya yok sayılamaz. - SIGCONT: Durmuş bir sürecin çalışmaya devam etmesini sağlar.
Numaralar bazı mimarilerde farklılaşabildiği için betiklerde kill -s TERM veya kill -TERM gibi sinyal adları daha okunaklıdır.
Sinyal gönderildiği anda uygulanmaz
Sinyal, sürece anında ulaşan bir mesaj değildir. kill çağrıldığında çekirdek hedef sürecin kaydına bekleyen sinyal bayrağını koyar; bayrak yalnızca süreç çekirdek alanından kullanıcı alanına dönerken denetlenir ve etkisi o anda uygulanır.
Bu ayrım, SIGKILL gönderildiği hâlde ölmeyen süreçleri açıklar. STAT alanında D görünen bir süreç kesintiye uğratılamaz uykudadır: bir çekirdek çağrısının ortasında donanım yanıtı bekler. Disk arızası, kopmuş bir ağ dosya sistemi bağlantısı veya çıkarılmış bir aygıt tipik sebeplerdir. Süreç kullanıcı alanına dönmediği için bekleyen sinyal hiç denetlenmez; SIGKILL kaybolmaz, sırasını bekler ve G/Ç tamamlandığı anda uygulanır.
Bu durumda süreci sonlandırmak mümkün değildir; çözüm altındaki G/Ç sorununu gidermektir. Linux’ta D durumundaki süreçlerin yük ortalamasına dahil edilmesi de belirgin bir ipucudur: CPU kullanan hiçbir şey yokken yük ortalamasının yükselmesi genellikle takılı G/Ç anlamına gelir.
Özetle SIGKILL’in etkisiz kaldığı iki durum vardır: süreç henüz sonlandırılamayacak durumdadır (D) veya zaten sonlanmıştır (Z).
Eksi işaretli PID: process group’a sinyal göndermek
kill komutunda hedef değeri yalnızca bir PID olarak okunmaz; işareti ve büyüklüğü hedefin kapsamını belirler:
| Değer | Sinyalin gittiği yer |
|---|---|
1234 | Yalnızca 1234 numaralı süreç |
0 | Çağıran sürecin kendi process group’u |
-1234 | PGID’si 1234 olan process group’un tamamı |
-1 | Çağıranın yetkili olduğu tüm süreçler (PID 1 hariç) |
Process group, kabuğun birlikte başlattığı süreçleri tek hedef altında toplar. cat dosya | grep hata | wc -l boru hattındaki üç süreç aynı gruptadır; Ctrl+C bastığınızda üçünün birden sonlanmasının sebebi, terminalin SIGINT sinyalini tek bir sürece değil ön plandaki process group’a göndermesidir. STAT alanındaki + eki de sürecin ön plan grubunda olduğunu belirtir.
Bir sürecin grubunu görmek için:
ps -o pid,pgid,comm -p 1234
Grup hedeflemek, alt süreç doğuran bir betiği durdururken işe yarar: yalnızca ana süreci sonlandırmak alt süreçleri öksüz bırakır ve çalışmaya devam ederler. Aynı özellik dikkatsiz kullanıldığında risklidir. kill -9 -1 root olarak çalıştırıldığında sistemdeki hemen her süreci sonlandırır; ayrıca kill -9 1234 yerine yanlışlıkla kill -9 -1234 yazmak tek süreç yerine bir grubu hedefler ve bu hata sessizce gerçekleşir.
Systemd’nin varsayılan KillMode=control-group davranışı bu fikrin daha güvenli hâlidir: sinyal process group’a değil servisin cgroup’una uygulanır. Bir süreç setpgid() ile process group’undan ayrılabilir, fakat cgroup’undan ayrılamaz.
İsimle sonlandırma neden dikkat ister?
pkill bir desene uyan birden fazla sürece sinyal gönderebilir. İsimle işlem yapmak zorundaysanız önce aynı eşleşmeyi yalnızca listelemek için kullanın:
pgrep -a -x my-app
Sonuç hedeflediğiniz süreçlerle birebir uyuşuyorsa yine de PID’leri tek tek incelemek en güvenli yöntemdir. Komut ikamesiyle kill -9 $(pidof ...) çalıştırmak, beklenmedik sayıda PID’yi doğrulama fırsatı olmadan hedefleyebilir; bu nedenle operasyonel örneklerde kullanılmamalıdır.
Yetki hataları ve servis yöneticileri
Bir kullanıcı normalde yalnızca yetkili olduğu süreçlere sinyal gönderebilir. sudo kullanmadan önce hedef PID’nin gerçekten doğru olduğunu iki kez kontrol edin. Süreç systemd tarafından yönetiliyorsa PID’ye doğrudan sinyal göndermek yerine çoğunlukla servis yöneticisini kullanmak daha doğrudur:
sudo systemctl stop my-app.service
Bu yaklaşım servisin tanımlı kapanış süresini, yeniden başlatma politikasını ve bağlı süreç grubunu dikkate alır.
Servis yöneticisini tercih etmenin bir sebebi daha vardır. PID ile çalışan her akışta doğrulama ile sinyal gönderme arasında bir boşluk kalır; bu araya sıkışan durum değişikliğine kontrol-kullanım yarışı (TOCTOU, time of check to time of use) denir. ps çıktısı doğrulandıktan sonra hedef süreç kendiliğinden sonlanabilir, PID serbest kalabilir ve aynı numara başka bir sürece atanabilir; ardından gönderilen sinyal yanlış hedefe ulaşır. Boşluk bir betikte milisaniyelerle ölçülür, çıktıyı okuyan bir kişi söz konusuysa dakikalara çıkar. Sistemdeki PID sınırı cat /proc/sys/kernel/pid_max ile görülebilir; sınırın düşük olduğu ve süreç döngüsünün yoğun olduğu makinelerde numaraların yeniden kullanılması hızlanır.
Systemd bu yarışa açık değildir, çünkü servisi PID ile değil cgroup üyeliğiyle izler. Kendi araçlarınızda aynı güvenceye ihtiyaç duyarsanız Linux 5.3 ile gelen pidfd arayüzü süreci numarayla değil dosya tanıtıcısıyla adresler:
import os, signal
fd = os.pidfd_open(1234)
# ... hedefi doğrulayın ...
signal.pidfd_send_signal(fd, signal.SIGTERM)
Tanıtıcı belirli bir süreç örneğine bağlıdır. Süreç sonlanmışsa çağrı ESRCH ile başarısız olur ve yeniden kullanılmış bir PID’ye sinyal gönderilmesi mümkün olmaz. Bir süreci kendiniz fork() ile başlattıysanız bu yarış zaten oluşmaz: PID, wait ailesiyle toplanana kadar yeniden kullanılamaz.
Zombie süreçler
ps çıktısındaki STAT alanında Z görünen zombie süreç zaten çalışmasını tamamlamıştır; ona ek sinyal göndermek çıkış kaydını ortadan kaldırmaz. Üst sürecin çocuğun durumunu wait ailesiyle toplaması gerekir. Sorun tekrarlanıyorsa üst uygulamanın çocuk süreç yönetimi düzeltilmelidir; üst süreci rastgele sonlandırmak genel bir çözüm değildir.