Ctrl-C neden çalışmadı?


9

CtrlcBitirmek uzun zaman alan bir işlemi durdurmak için kabuğuma iki kez vurdum .

^C iki kez yankılandı, ama süreç devam etti.

Neden Ctrlcnormalde olduğu gibi işlemden çıkmadınız?


4
Ölmek istemeyen can sıkıcı programlara yönelik çözümüm genellikle CTRL + Z ile askıya almak ve sonra kill -9 %onu öldürmektir. Sinyal 9 göz ardı edilemez ve askıya alma sinyali de olamaz. CTRL + Z klavye dizisi teoride yok sayılabilir - ancak pratikte yoktur.
David Sainty

@DavidSainty Askıya alma sinyali yok sayılabilir (veya en azından durdurulamaz). Örnek: perl -E '$SIG{TSTP} = sub { say "ha ha" }; sleep 1 while 1'. Muhtemelen farklı bir sinyal olan SIGSTOP'u düşünüyorsunuz.
derobert

Ah, haklısın :)
David Sainty

Yanıtlar:


13

İşlemler aşağıdakileri seçebilir:

  • genellikle Ctrl-C( trap '' INTkabukta olduğu gibi) basıldığında gönderilen SIGINT sinyalini yok sayın veya sonlandırmamaya karar veren (veya zamanında sona ermeyen) kendi işleyicisine sahip olun.
  • terminal cihazına, SIGINT'in ön plana gönderilmesine neden olan karakterin başka bir şey olduğunu söyleyin ( stty int '^K'kabukta olduğu gibi)
  • terminal cihazına herhangi bir sinyal göndermemesini söyleyin ( stty -isigkabukta olduğu gibi).

Veya, bir sistem çağrısının ortasında kesilemeyen gibi kesintisiz olabilirler.

(Görece yeni çekirdek ile) Linux'ta, bir süreç görmezden ve / veya eğer söyleyebilir taşıma çıkışında bakarak SIGINT

$ kill -l INT
2
$ grep Sig "/proc/$pid/status"
SigQ:   0/63858
SigPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000002
SigCgt: 0000000000000000

SIGINT 2'dir. Yukarıdaki SigIgn'ın ikinci biti 1'dir, bu da SIGINT'in yok sayıldığı anlamına gelir.

Bunu aşağıdakilerle otomatikleştirebilirsiniz:

$ SIG=$(kill -l INT) perl -lane 'print $1 if $F[0] =~ /^Sig(...):/ && 
    $F[1] & (1<<($ENV{SIG}-1))' < "/proc/$pid/status"
Ign

Geçerli intrkarakterin ne olduğunu veya isigbelirli bir terminal için etkin olup olmadığını kontrol etmek için:

$ stty -a < /dev/pts/0
[...] intr = ^C [...] isig

( intrkarakterin üstünde ^C(genellikle terminaliniz (emülatör) tarafından basıldığında CTRL-Cve giriş sinyalleri devre dışı bırakılmadığında).

$ stty -a < /dev/pts/1
[...] intr = ^K [...] -isig

( intrkarakteri için ^Kve isigdevre dışı /dev/pts/1).

Tamlık için, bir sürecin SIGINT'leri almayı durdurmak için bir şey yapmasının başka iki yolu vardır, ancak bu tipik olarak göreceğiniz bir şey değildir.

Üzerine Ctrl+CSIGINT sinyali süreçleri tüm gönderilen terminal ön işlem grubunda . Genellikle süreçleri süreç gruplarına yerleştiren (kabuk işleriyle eşlenen ) kabuktur ve terminal aygıtına ön plan olanı söyler .

Artık bir süreç şunları yapabilir:

  • İşlem grubundan ayrıl. Başka bir işlem grubuna ( ön plandakinden başka herhangi bir işlem grubu) geçerse , artık SIGINT'i Ctrl-C(veya SIGTSTP, SIGQUIT gibi klavyeyle ilgili diğer sinyalleri) almaz. Bununla birlikte, terminal cihazından (arka plan işlemlerinin yaptığı gibi) okumaya (muhtemelen terminal cihazı ayarlarına bağlı olarak da yazmaya) çalışırsa askıya alınabilir.

    Örnek olarak:

    perl -MPOSIX -e 'setpgid(0,getppid) or die "$!"; sleep 10'

    ile kesilemedi Ctrl-C. Yukarıdaki perl, kimliği üst süreç kimliğiyle aynı olan işlem grubuna katılmaya çalışacaktır. Genel olarak, bu kimliğe sahip böyle bir süreç grubu olduğuna dair bir garanti yoktur. Ancak burada, bu perlkomutun etkileşimli bir kabuk isteminde kendi başına çalışması durumunda , ppid kabuğun işlemi olacak ve kabuk tipik olarak kendi işlem grubunda başlamış olacaktır.

    Komut zaten bir süreç grubu lideri (bu ön plan süreç grubunun lideri) değilse, yeni bir süreç grubunun başlatılması aynı etkiye sahip olacaktır.

    Örneğin, kabuğa bağlı olarak,

    $ ps -j >&2 | perl -MPOSIX -e 'setpgid(0,0) or die "$!"; sleep 10'
      PID  PGID   SID TTY          TIME CMD
    21435 21435 21435 pts/12   00:00:00 zsh
    21441 21441 21435 pts/12   00:00:00 ps
    21442 21441 21435 pts/12   00:00:00 perl

    aynı etkiye sahip olur. psve perlönalan işlem grubunda başlamış, ancak çoğu kabukları üzerinde, ps(görüldüğü gibi o grubun lideri olacağını pshem pgid nerede yukarıdaki çıktı psve perlbir pid ps) bu yüzden, perlkendi süreç grubu başlatabilirsiniz.

  • Veya ön plan süreç grubunu değiştirebilir. Temel olarak tty cihazına SIGINT'i başka bir işlem grubunaCtrl+C

    perl -MPOSIX -e 'tcsetpgrp (0, getppid) veya die $ !; uyku 5 '

    Orada, perlaynı işlem grubunda kalır, ancak bunun yerine terminal cihazına ön plan işlem grubunun kimliği üst işlem kimliğiyle aynı olan grup olduğunu söyler (bu konuda yukarıdaki nota bakın).


1
Kesintisiz aramanın iyi bir örneği, yanıt vermeyen bir donanım aygıtına erişmektir. Örneğin, kullanmaya çalışırsanız hdparmya smartctlda sonsuza askıda yanıt vermiyor kusurlu bir sabit disk üzerinde ve CTRL + C onları öldürmek olamaz. Bir süreç içinde istatistik sütununa bakarak kesintisiz uykuda olup olmadığını anlayabilirsiniz ps auxveya S sütununda top/ htop- Daraçlarının kesintisiz bir uyku. Bu mutlaka kötü bir şey değil, sadece sürecin çok fazla IO yaptığı anlamına gelebilir.
Martin von Wittich
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.