Ctrl-C काम क्यों नहीं किया?


9

मैं सिर्फ Ctrlcएक प्रक्रिया को रोकने की कोशिश में अपने खोल पर दो बार मारा जो खत्म होने में लंबा समय ले रहा है।

^C दो बार गूँज गया था, लेकिन यह प्रक्रिया अभी भी जारी रही।

Ctrlcइस प्रक्रिया को सामान्य रूप से क्यों नहीं छोड़ा?


4
कष्टप्रद कार्यक्रमों के लिए मेरा समाधान जो मरना नहीं चाहते हैं, आमतौर पर उन्हें kill -9 %मारने के लिए CTRL + Z के साथ निलंबित करना है। सिग्नल 9 को नजरअंदाज नहीं किया जा सकता है, न ही सिग्नल को सस्पेंड किया जा सकता है। CTRL + Z कीबोर्ड अनुक्रम को सिद्धांत में अनदेखा किया जा सकता है - लेकिन व्यवहार में नहीं है।
डेविड सैंटी

@DavidSainty सस्पेंड सिग्नल को अनदेखा किया जा सकता है (या, कम से कम नहीं रोका गया)। उदाहरण: perl -E '$SIG{TSTP} = sub { say "ha ha" }; sleep 1 while 1'। आप शायद SIGSTOP के बारे में सोच रहे हैं, जो एक अलग संकेत है।
derobert

आह, ठीक है आप :)
डेविड सैनी

जवाबों:


13

प्रक्रियाएं चुन सकती हैं:

  • SIGINT सिग्नल को आमतौर पर दबाने पर Ctrl-C(जैसे trap '' INTशेल में) भेजा जाता है या इसके लिए अपने स्वयं के हैंडलर को अनदेखा करें जो इसे समाप्त नहीं करने का निर्णय लेता है (या समय पर फैशन में समाप्त होने में विफल रहता है)।
  • टर्मिनल डिवाइस को बताएं कि चरित्र जो SIGINT को अग्रभूमि नौकरी में भेजने का कारण बनता है वह कुछ और है (जैसे stty int '^K'एक शेल में)
  • टर्मिनल डिवाइस को किसी भी सिग्नल (जैसे stty -isigशेल में) नहीं भेजने के लिए कहें ।

या, वे निर्बाध हो सकते हैं, जैसे कि एक सिस्टम कॉल के बीच में जब बाधित नहीं किया जा सकता है।

लिनक्स पर (अपेक्षाकृत हाल के कर्नेल के साथ), आप बता सकते हैं कि क्या कोई प्रक्रिया अनदेखी कर रही है और / या आउटपुट को देखकर SIGINT को संभाल रही है

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

SIGINT 2 है। ऊपर सिगीन का दूसरा बिट 1 है, जिसका मतलब है कि SIGINT को नजरअंदाज कर दिया गया है।

आप इसे स्वचालित कर सकते हैं:

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

यह देखने के लिए कि वर्तमान intrवर्ण क्या है या isigकिसी दिए गए टर्मिनल के लिए सक्षम है या नहीं :

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

( intrवर्ण के ऊपर ^C(वर्ण आमतौर पर आपके टर्मिनल (एमुलेटर) द्वारा भेजा जाता है) जब दबाने CTRL-Cऔर इनपुट सिग्नल अक्षम नहीं होते हैं।

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

( intrचरित्र है ^Kऔर के isigलिए अक्षम है /dev/pts/1)।

पूर्णता के लिए, दो अन्य तरीके हैं जो एक प्रक्रिया SIGINTs को प्राप्त करने से रोकने के लिए कुछ कर सकते हैं, हालांकि यह कुछ ऐसा नहीं है जो आप आमतौर पर देखेंगे।

ऊपर Ctrl+C, SIGINT सिग्नल टर्मिनल के अग्रभूमि प्रक्रिया समूह में सभी प्रक्रियाओं के लिए भेजा जाता है । यह आमतौर पर शेल होता है जो प्रोसेस ग्रुप (शेल जॉब के लिए मैप ) में प्रोसेस करता है और टर्मिनल डिवाइस को बताता है जो फोरग्राउंड वन है।

अब एक प्रक्रिया हो सकती है:

  • इसके प्रोसेस ग्रुप को छोड़ दें। यदि यह किसी अन्य प्रक्रिया समूह (किसी भी प्रक्रिया समूह लेकिन वह जो अग्रभूमि वाला है) में चला जाता है, तो यह अब SIGINT पर प्राप्त नहीं होगा Ctrl-C(और न ही अन्य कीबोर्ड-संबंधी संकेत जैसे SIGTSTP, SIGQUIT)। हालाँकि यह निलंबित हो सकता है अगर यह टर्मिनल डिवाइस से पढ़ने की कोशिश करता है (संभवतः टर्मिनल डिवाइस सेटिंग्स पर निर्भर करता है) (जैसा कि बैकग्राउंड प्रोसेस करते हैं)।

    उदहारण के लिए:

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

    के साथ बाधित नहीं किया जा सकता है Ctrl-C। ऊपर perlप्रक्रिया समूह में शामिल होने का प्रयास करेंगे जिसकी आईडी इसकी मूल प्रक्रिया आईडी के समान है। सामान्य तौर पर, इस बात की कोई गारंटी नहीं है कि उस आईडी के साथ ऐसा कोई प्रक्रिया समूह हो। लेकिन यहां, perlएक इंटरेक्टिव शेल के संकेत पर अपने आप चलने वाली कमांड के मामले में , ppid शेल की प्रक्रिया होगी और शेल आमतौर पर अपने प्रोसेस ग्रुप में शुरू किया जाएगा।

    यदि आदेश पहले से ही एक प्रक्रिया समूह नेता (उस अग्रभूमि प्रक्रिया समूह का नेता) नहीं है, तो यह एक नई प्रक्रिया समूह शुरू करने का एक ही प्रभाव होगा।

    उदाहरण के लिए, शेल के आधार पर,

    $ 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

    एक ही प्रभाव होगा। psऔर perlअग्रभूमि प्रक्रिया समूह में शुरू किया जाता है, लेकिन अधिकांश गोले पर, psउस समूह का नेता होगा (जैसा कि psऊपर आउटपुट में देखा गया है, जहां दोनों के pgid psऔर perlpid हैं ps), इसलिए perlअपना स्वयं का प्रक्रिया समूह शुरू कर सकते हैं।

  • या यह अग्रभूमि प्रक्रिया समूह को बदल सकता है। मूल रूप से tty डिवाइस को SIGINT को किसी अन्य प्रक्रिया समूह पर भेजने के लिए कहेंCtrl+C

    perl -MPOSIX -e 'tcsetpgrp (0, getppid) या $ मरना! नींद 5 '

    वहां, perlएक ही प्रक्रिया समूह में रहता है, लेकिन टर्मिनल डिवाइस को बता रहा है कि अग्रभूमि प्रक्रिया समूह वह है जिसकी आईडी इसकी मूल प्रक्रिया आईडी के समान है (इसके बारे में ऊपर नोट देखें)।


1
एक निर्बाध कॉल का एक अच्छा उदाहरण एक हार्डवेयर डिवाइस तक पहुंच रहा है जो प्रतिक्रिया नहीं करता है। उदाहरण के लिए, आप उपयोग करने का प्रयास करता है, तो hdparmया smartctlएक दोषपूर्ण हार्ड डिस्क है कि जवाब नहीं है वे हमेशा के लिए रखती हूँ पर, और आप उन्हें Ctrl + सी के साथ नहीं मार सकता है। आप यह बता सकते हैं कि क्या कोई प्रक्रिया निर्बाध नींद में है ps auxया एस के स्तंभ पर top/ htop- का Dअर्थ है अबाधित नींद। यह आवश्यक रूप से एक बुरी बात नहीं है, हालांकि, इसका मतलब यह हो सकता है कि प्रक्रिया बहुत अधिक आईओ कर रही है।
मार्टिन वॉन विटिच
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.