Kapatma süreçlerine hangi sırayla sinyal göndermeliyim?


90

Bir de açıklama üzerine bu cevabı diğerinin sorusuna , yorumcu diyor ki:

kesinlikle gerekli olmadıkça kill -9 kullanmayın! SIGKILL yakalanamaz, bu nedenle öldürülen program, örneğin geçici dosyaları silmek için herhangi bir kapatma rutini çalıştıramaz. Önce HUP (1), ardından INT (2), ardından QUIT (3) 'ü deneyin

Prensip olarak buna katılıyorum SIGKILL, ama geri kalanı benim için haber. Tarafından gönderilen varsayılan sinyal göz önüne alındığında killise SIGTERM, bunun keyfi bir sürecin düzgün kapanmasına en-yaygın beklenen sinyaldir beklenebilir. Ayrıca, SIGHUPbir arka plan programına "yapılandırma dosyanızı yeniden okuyun" demek gibi sonlandırıcı olmayan nedenlerle kullanıldığını gördüm . Ve bana öyle geliyor ki SIGINT(Ctrl-C ile tipik olarak elde edeceğiniz aynı kesinti, değil mi?) Olması gerektiği kadar geniş çapta desteklenmiyor veya oldukça ürkütücü bir şekilde sonlanıyor.

Bunun SIGKILLson çare olduğu düşünüldüğünde - İşlemi olabildiğince zarif bir şekilde kapatmak için rastgele bir sürece hangi sinyalleri ve hangi sırayla göndermelisiniz?

Lütfen cevaplarınızı destekleyici gerçeklerle (kişisel tercih veya görüşün ötesinde) veya mümkünse referanslarla kanıtlayın.

Not: Özellikle bash / Cygwin'i dikkate alan en iyi uygulamalarla ilgileniyorum.

Düzenleme: Şimdiye kadar kimse INT veya QUIT'ten bahsetmiyor gibi görünüyor ve HUP'tan sınırlı olarak bahsediliyor. Bunları düzenli bir süreç öldürmeye dahil etmek için herhangi bir sebep var mı?


4
Bir süreci gerçekten öldürmek için SIGKILL'e başvurmanız gerekiyorsa, bunu programda bir hata olarak değerlendiririm.
sigjuice

Yanıtlar:


121

SIGTERM, bir uygulamaya sonlandırmasını söyler. Diğer sinyaller, uygulamaya kapatma ile ilgisi olmayan ancak bazen aynı sonuca sahip olabilecek başka şeyler söyler. Bunları kullanmayın. Bir uygulamanın kapanmasını istiyorsanız, ona söyleyin. Yanıltıcı sinyaller vermeyin.

Bazı insanlar bir süreci sonlandırmanın akıllıca standart yolunun, ona HUP, INT, TERM ve son olarak KILL gibi bir dizi sinyal göndermek olduğuna inanıyor. Bu gülünç. Sonlandırma için doğru sinyal SIGTERM'dir ve SIGTERM, tercih edebileceğiniz gibi işlemi anında sonlandırmazsa, bunun nedeni uygulamanın sinyali işlemeyi seçmiş olmasıdır. Bu, hemen sonlandırmamak için çok iyi bir nedeni olduğu anlamına gelir: Yapacak temizlik işleri var. Temizleme çalışmasını diğer sinyallerle keserseniz, bellekteki hangi verilerin henüz diske kaydetmediğini, hangi istemci uygulamalarının askıda kaldığını veya etkin bir veri bozulması olan "cümlenin ortasında" kesintiye uğrayıp uğramadığınızı bilemezsiniz.

Sinyallerin gerçek anlamının ne olduğu hakkında daha fazla bilgi için, bkz. Sigaction (2). "Varsayılan Eylem" i "Açıklama" ile karıştırmayın, bunlar aynı şey değildir.

SIGINT, sürecin etkileşimli bir "klavye kesintisini" işaret etmek için kullanılır. Bazı programlar, terminal kullanıcılarının amacı için durumu özel bir şekilde ele alabilir.

SIGHUP, terminalin kaybolduğunu ve artık işleme bakmadığını belirtmek için kullanılır. Hepsi bu. Bazı süreçler yanıt olarak kapatmayı seçerler, çünkü genellikle terminal olmadan işlemlerinin bir anlamı yoktur, bazıları ise yapılandırma dosyalarını yeniden kontrol etmek gibi başka şeyler yapmayı tercih eder.

SIGKILL, süreci çekirdekten zorla kaldırmak için kullanılır. Bu, aslında işlem için bir sinyal olmaması, daha ziyade doğrudan çekirdek tarafından yorumlanması açısından özeldir.

SIGKILL göndermeyin. SIGKILL kesinlikle asla komut dosyalarıyla gönderilmemelidir. Uygulama SIGTERM'i kullanıyorsa, temizlenmesi bir saniye, bir dakika, bir saat sürebilir . Uygulamanın bitmeye hazır hale gelmeden önce ne yapması gerektiğine bağlı olarak. "O Herhangi mantık kabul X saniye sonra kısayol ya SIGKILLed olmak bir uygulamanın temizleme sırası yeterince uzun almıştır" ve ihtiyaçları olan sadece düz yanlış .

Bir uygulamanın sonlandırmak için bir SIGKILL'e ihtiyaç duymasının tek nedeni , temizleme dizisi sırasında bir şeyin arızalanmasıdır. Bu durumda bir terminal açıp manuel olarak SIGKILL yapabilirsiniz. Bunun dışında, bir şeyi SIGKILL yapmanın bir diğer nedeni, onun kendi kendini temizlemesini engellemek İSTEDİĞİNİZdir .

Dünyanın yarısı, 5 saniye sonra SIGKILL'i körü körüne göndermesine rağmen, yapılması gereken hala korkunç derecede yanlış bir şey.


13
SIGKILL'in birçok kötüye kullanımı olduğu konusunda haklısınız. Ama bir senaryodan bile onu kullanmanın bir zamanı ve yeri var. Pek çok uygulama SIGTERM'i yakalar ve bir saniyeden daha kısa bir sürede veya sadece birkaç saniye içinde zarif bir şekilde çıkar ve bunlardan biri sıkışmış olduğu için 30 saniye sonra hala çalışıyor.
dwc

4
@dwc: Bir saat boyunca bir kez çalışmasına izin vermeyi deneyin. Eğer ölmezse, o zaman "sıkışmış" olur ve ya onarır ya da tembelleşir ve gelecekte bir süre sonra SIGKILL. Muhtemelen bir şeyleri bozduğunuzu unutmayın ve bunun "varsayılan olarak" yapmanız gereken bir şey olmadığını unutmayın.
lhunath

2
@lhunath: Umarım aldırmazsınız, cevabı sorudan daha doğrudan ve net bir şekilde takip edebilmek için paragraflarınızı yeniden düzenledim. Anti-SIGKILL rantı iyi bir şey ama ikincil bir nokta. Mükemmel ve eğitici bir yanıt için tekrar teşekkürler.
sistem

8
SIGKILL göndermeyin. Hiç. Sadece yanlış. Gerçekten mi? Sonsuz döngüler sayesinde sisteminiz zaten yanıyor olsa bile. İyi şanslar. -1
konsolebox

//, Buna Oy Vermek çok saçma.
Nathan Basanese

18

Kısa Cevap : Gönder SIGTERM, 30 saniye sonra SIGKILL. Yani gönder SIGTERM, biraz bekle (programdan programa değişebilir, sisteminizi daha iyi tanıyabilirsiniz, ancak 5 ila 30 saniye yeterlidir. Bir makineyi kapatırken otomatik olarak 1'30'lara kadar beklediğini görebilirsiniz. Sonuçta neden acele?), Sonra gönderin SIGKILL.

Makul Cevap : SIGTERM, SIGINT, SIGKILL Bu yeter de artar. Süreç büyük olasılıkla daha önce sona erecek SIGKILL.

Uzun Cevap : SIGTERM, SIGINT, SIGQUIT, SIGABRT,SIGKILL

Bu gereksizdir, ancak en azından mesajınızla ilgili süreci yanıltmıyorsunuz. Bütün bu sinyaller yok sen süreç yaptığını ve çıkış ne durdurmak istiyor demek.

Bu açıklamadan hangi cevabı seçerseniz seçin, bunu aklınızda bulundurun!

Başka bir anlama gelen bir sinyal gönderirseniz, süreç bunu çok farklı şekillerde ele alabilir (bir yandan). Öte yandan, eğer süreç sinyali işlemezse, ne gönderdiğiniz önemli değil, süreç yine de sonlandırılacaktır (tabii ki varsayılan eylem sonlandırmak olduğunda).

Yani, kendinizi bir programcı olarak düşünmelisiniz. Bir SIGHUPşeye bağlanan bir programdan çıkmak için bir işlev işleyiciyi kodlar mıydınız yoksa tekrar bağlanmayı denemek için onu döngüye mi sokardınız? Buradaki ana soru bu! Bu nedenle, niyet ettiğiniz şeyi ifade eden sinyaller göndermek önemlidir.

Neredeyse Aptalca Uzun Cevap :

Aşağıdaki tablo, ilgili sinyalleri ve programın bunları işlememesi durumunda varsayılan eylemleri içerir.

Kullanmayı önerdiğim sırayla sipariş ettim (BTW, makul cevabı kullanmanızı öneririm , burada değil), gerçekten hepsini denemeniz gerekiyorsa (masanın sıralı olduğunu söylemek eğlenceli olur. neden olabilecekleri yıkım, ancak bu tamamen doğru değil ).

Yıldız (*) ile sinyaller vardır DEĞİL önerilir. Bunlarla ilgili önemli olan şey, ne yapmak için programlandığını asla bilemeyeceğinizdir. Özellikle SIGUSR! Kıyameti başlatabilir (bir programcı için ne isterse yapması ücretsiz bir işarettir!). Ancak, ele alınmazsa VEYA beklenmedik bir durumda sona erdirilirse, program sona erecektir.

Tabloda, sonlandırmak ve bir çekirdek dökümü oluşturmak için varsayılan seçeneklere sahip sinyaller, hemen öncesinde sonunda bırakılmıştır SIGKILL.

Signal     Value     Action   Comment
----------------------------------------------------------------------
SIGTERM      15       Term    Termination signal
SIGINT        2       Term    Famous CONTROL+C interrupt from keyboard
SIGHUP        1       Term    Disconnected terminal or parent died
SIGPIPE      13       Term    Broken pipe
SIGALRM(*)   14       Term    Timer signal from alarm
SIGUSR2(*)   12       Term    User-defined signal 2
SIGUSR1(*)   10       Term    User-defined signal 1
SIGQUIT       3       Core    CONTRL+\ or quit from keyboard
SIGABRT       6       Core    Abort signal from abort(3)
SIGSEGV      11       Core    Invalid memory reference
SIGILL        4       Core    Illegal Instruction
SIGFPE        8       Core    Floating point exception
SIGKILL       9       Term    Kill signal

Sonra bunun için öneririm neredeyse aptal uzun cevap : SIGTERM, SIGINT, SIGHUP, SIGPIPE, SIGQUIT, SIGABRT,SIGKILL

Ve son olarak

Kesinlikle Aptal Uzun Uzun Cevap :

Bunu evde denemeyin.

SIGTERM, SIGINT, SIGHUP, SIGPIPE, SIGALRM, SIGUSR2, SIGUSR1, SIGQUIT, SIGABRT, SIGSEGV, SIGILL, SIGFPEVe hiçbir şey, eğer çalıştı SIGKILL.

SIGUSR2daha önce denenmeli SIGUSR1çünkü program sinyali işlemezse daha iyi durumda oluruz. Ve SIGUSR1bunlardan sadece birini idare etmesi çok daha muhtemeldir .

BTW, KILL : SIGKILLDiğer yanıtın da belirttiği gibi bir işleme göndermek yanlış değildir . Peki, bir shutdownemir gönderdiğinizde ne olacağını düşünün ? Bu çalışacağız SIGTERMve SIGKILLsadece. Neden böyle olduğunu düşünüyorsun? Ve eğer shutdownkomut sadece bu ikisini kullanıyorsa , neden başka sinyallere ihtiyacınız var ?


Şimdi, uzun cevaba dönelim , bu güzel bir oneliner:

for SIG in 15 2 3 6 9 ; do echo $SIG ; echo kill -$SIG $PID || break ; sleep 30 ; done

Sinyaller arasında 30 saniye uyur. Başka neden bir oneliner'e ihtiyacınız var ? ;)

Ayrıca, önerilir: yalnızca makul cevaptan15 2 9 gelen sinyallerle deneyin .

güvenlik : echogitmeye hazır olduğunuzda ikinciyi kaldırın . Bunu benim çağrı dry-runiçin Onliners . Her zaman test etmek için kullanın.


Komut öldürücü bir şekilde

Aslında bu soru o kadar ilgimi çekti ki tam da bunu yapmak için küçük bir senaryo oluşturmaya karar verdim. Lütfen buradan indirin (klonlayın):

Killgracefully deposuna GitHub bağlantısı


8

Normalde SIGTERMvarsayılan öldürmeyi gönderirsiniz . Bir nedenden ötürü varsayılandır. Yalnızca bir program makul bir süre içinde kapanmazsa, başvurmanız gerekir SIGKILL. Ancak SIGKILL, programın bir şeyleri temizleme imkanı olmadığını ve verilerin bozulabileceğini unutmayın.

Gelince SIGHUP, HUP"asmak" anlamına gelir ve tarihsel olarak modem bağlantısı kesildi anlamına geliyordu. Esasen eşdeğerdir SIGTERM. Arka SIGHUPplan programlarının bazen yapılandırmayı yeniden başlatmak veya yeniden yüklemek için kullanmalarının nedeni, bir arka plan programının bunlara ihtiyacı olmadığı ve bu nedenle hiçbir zaman alamayacağı için arka plan yordamlarının herhangi bir kontrol terminalinden ayrılmasıdır, bu nedenle SIGHUPsinyal genel kullanım için "serbest bırakılmış" olarak kabul edilir. Tüm artalan süreçleri bunu yeniden yüklemek için kullanmaz! SIGHUP için varsayılan eylem sonlandırmaktır ve birçok arka plan yordamı bu şekilde davranır! Bu yüzden SIGHUP, cinlere körü körüne posta gönderemez ve onların hayatta kalmasını bekleyemezsiniz.

Düzenleme: SIGINT Normalde bağlı olduğu ^Cveya terminal ayarı bir programı kesintiye uğratacağı için bir işlemi sonlandırmak muhtemelen uygun değildir . Birçok program bunu kendi amaçları için yakalar, bu nedenle işe yaramayacak kadar yaygındır. SIGQUITtipik olarak bir çekirdek dökümü oluşturma varsayılanına sahiptir ve çekirdek dosyaların etrafına yerleştirilmesini istemiyorsanız, bu da iyi bir aday değildir.

Özet: Gönderirseniz SIGTERMve program zaman diliminizde ölmezse, gönderin SIGKILL.


4
Bunu SIGKILL ile takip etmenin yalnızca anında kapatmanın veri kaybını / veri bozulmasını önlemekten daha yüksek bir öncelik olduğu durumlarda yapılması gerektiğini unutmayın.
thomasrutter

@dwc Cevabınızda aşağıdaki noktayı anlamadım. yardımcı olabilir misiniz "arka plan yordamlarının bazen yapılandırmayı yeniden başlatmak veya yeniden yüklemek için SIGHUP kullanmasının nedeni, arka plan yordamlarının herhangi bir kontrol terminalinden ayrılması ve bu nedenle hiçbir zaman SIGTERM almamasıdır, bu nedenle sinyal genel kullanım için" serbest bırakılmış "olarak kabul edildi."
Jack

3
@Jack Deneyeyim: SIGHUP, bir işleme terminalin bağlantısının kesildiğini söyleyen "telefonu kapat" sinyalidir. Arka planda çalışan arka planda çalıştığından, uçbirime ihtiyaçları yoktur. Bu, "telefonu kapat" sinyalinin arka plan yordamlarıyla ilgili olmadığı anlamına gelir. İlk etapta bağlı terminalleri olmadığı için bunu bir terminal bağlantısının kesilmesinden asla alamazlar. Ve sinyal yine de tanımlandığından, orijinal amaç için buna ihtiyaç duymasalar da, birçok arka plan yordamı onu bunun yerine yapılandırma dosyalarını yeniden okumak gibi farklı bir amaç için kullanır.
sistem

Teşekkürler sistemi DURAKLAT. bu yardımcı olur.
Jack

7

SIGTERMaslında bir uygulamaya bir mesaj göndermek anlamına gelir: " bu kadar nazik davranıp intihar eder miydiniz ". Temizleme ve kapatma kodunu çalıştırmak için uygulama tarafından yakalanabilir ve işlenebilir.

SIGKILLuygulama tarafından yakalanamaz. Uygulama, temizleme şansı olmadan işletim sistemi tarafından öldürülür.

SIGTERMÖnce göndermek , biraz uyumak ve sonra göndermek normaldir SIGKILL.


Sanırım yoklama, uyumaktan biraz daha verimli olurdu (SIGKILL'den önce)
Ohad Schneider

@OhadSchneider olur, ancak bu basit bash komutundan daha fazlasını gerektirir.
vartec

Evet, sanırım süreç hala canlıyken şuna benzer bir şey kullanarak döngü yapmanız gerekir: stackoverflow.com/a/15774758/67824 .
Ohad Schneider

5
  • SIGTERM, bir penceredeki "X" e tıklamakla eşdeğerdir.
  • SIGTERM, Linux kapandığında ilk olarak kullandığı şeydir.

Bilmek istediğim buydu. +1. Teşekkürler.
Luc

6
"SIGTERM, bir pencerede" 'X "e tıklamakla eşdeğerdir" Hayır, değildir, çünkü herhangi bir uygulama, bırakın diyaloglar bir yana, herhangi bir sayıda (örneğin belge ve araç) pencereleri kolayca açabilir ve açmayabilir. bir çıkış komutuna olduğu gibi son bir pencere kapatma komutuna bile yanıt verin (herhangi bir açık örnek düşünemiyorum, ancak açık olmasa da, bu şekilde yapılmaması için hiçbir neden yok). SIGTERM, uygulamadan nazikçe sonlandırılmasını istemeye eşdeğerdir (veya olmalıdır), ancak bu belirli bir uygulamada gerçekleştirilebilir .
kullanıcı

3

Burada tüm tartışmalar devam ederken, hiçbir kod sunulmadı. İşte benim almam:

#!/bin/bash

$pid = 1234

echo "Killing process $pid..."
kill $pid

waitAttempts=30 
for i in $(seq 1 $waitAttempts)
do
    echo "Checking if process is alive (attempt #$i / $waitAttempts)..."
    sleep 1

    if ps -p $pid > /dev/null
    then
        echo "Process $pid is still running"
    else
        echo "Process $pid has shut down successfully"
        break
    fi
done

if ps -p $pid > /dev/null
then
    echo "Could not shut down process $pid gracefully - killing it forcibly..."
    kill -SIGKILL $pid
fi

0

HUP bana çöp gibi geliyor. Yapılandırmasını yeniden okuması için bir arka plan programı almaya gönderirim.

SIGTERM yakalanabilir; arka plan programlarınız, bu sinyali aldığında çalıştırılacak temizleme koduna sahip olabilir. Bunu SIGKILL için yapamazsınız. Bu nedenle SIGKILL ile arka planın yazarına herhangi bir seçenek sunmuyorsunuz.

Wikipedia'da daha fazlası

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.