क्या होता है कि दोनों है bash
और ping
SIGINT प्राप्त ( bash
किया जा रहा नहीं इंटरैक्टिव, दोनों ping
और bash
एक ही प्रक्रिया समूह है जो इंटरैक्टिव खोल आप से है कि स्क्रिप्ट चलाने के द्वारा बनाई गई है और सेट टर्मिनल के अग्रभूमि प्रक्रिया समूह के रूप में में चलाने)।
हालाँकि, bash
उस SIGINT को असिंक्रोनस तरीके से हैंडल करता है, केवल वर्तमान में चल रहे कमांड से बाहर निकलने के बाद। bash
केवल उस SIGINT को प्राप्त करने पर बाहर निकलता है यदि वर्तमान में चल रही कमांड SIGINT की मृत्यु हो जाती है (अर्थात इसकी निकास स्थिति इंगित करती है कि यह SIGINT द्वारा मार दी गई है)।
$ bash -c 'sh -c "trap exit\ 0 INT; sleep 10; :"; echo here'
^Chere
इन सबसे ऊपर, bash
, sh
और sleep
SIGINT जब मैं Ctrl-C दबाएँ प्राप्त करते हैं, लेकिन sh
बाहर निकलता है एक 0 बाहर निकलने के कोड के साथ सामान्य रूप से है, इसलिए bash
SIGINT पर ध्यान नहीं देता है, जो कारण है कि हम "यहाँ" देखें।
ping
कम से कम iputils से एक, ऐसा व्यवहार करता है। बाधित होने पर, यह आँकड़े प्रिंट करता है और 0 या 1 के बाहर निकलने की स्थिति के साथ बाहर निकलता है, इस पर निर्भर करता है कि उसके पिंग्स का उत्तर दिया गया था या नहीं। इसलिए, जब आप ping
रनिंग के दौरान Ctrl-C दबाते हैं, तो bash
जो नोट्स आपने Ctrl-C
अपने SIGINT हैंडलर्स में दबाए हैं , लेकिन चूंकि ping
सामान्य रूप से बाहर निकलता है, bash
इसलिए बाहर नहीं निकलता है।
यदि आप sleep 1
उस लूप में जोड़ते हैं और दौड़ते Ctrl-C
समय दबाते हैं sleep
, क्योंकि sleep
SIGINT पर कोई विशेष हैंडलर नहीं है, तो वह मर जाएगा और bash
यह रिपोर्ट करेगा कि यह एक SIGINT की मृत्यु हो गई है, और उस मामले bash
में बाहर निकल जाएगा (यह वास्तव में SIGINT के साथ खुद को मार देगा। अपने अभिभावक को रुकावट की सूचना देना)।
जैसा कि क्यों bash
व्यवहार करता है, मुझे यकीन नहीं है और मैं ध्यान देता हूं कि व्यवहार हमेशा निर्धारक नहीं होता है। मैंने सिर्फ विकास मेलिंग सूची पर सवालbash
पूछा है ( अपडेट : @ जाइल्स ने अब अपने उत्तर में कारण को नीचे कर दिया है )।
केवल दूसरे शेल में मैंने पाया कि इसी तरह का व्यवहार ksh93 है (अपडेट, जैसा कि @Jilles द्वारा उल्लेख किया गया है, इसलिए FreeBSD करता हैsh
)। वहाँ, SIGINT को स्पष्ट रूप से नजरअंदाज किया गया लगता है। और ksh93
जब भी कोई आदेश SIGINT द्वारा मार दिया जाता है तब बाहर निकलता है।
आपको bash
ऊपर जैसा ही व्यवहार मिलता है, बल्कि:
ksh -c 'sh -c "kill -INT \$\$"; echo test'
आउटपुट "परीक्षण" नहीं करता है। यही है, यह बाहर निकलता है (वहाँ खुद को SIGINT के साथ मारकर) अगर यह SIGINT के मरने का इंतजार कर रहा था, तो भी, खुद को उस SIGINT को प्राप्त नहीं हुआ था।
चारों ओर एक काम एक जोड़ने के लिए किया जाएगा:
trap 'exit 130' INT
bash
SIGINT प्राप्त करने के लिए बाहर निकलने के लिए बाध्य करने के लिए स्क्रिप्ट के शीर्ष पर (ध्यान दें कि किसी भी स्थिति में, SIGINT को समकालिक रूप से संसाधित नहीं किया जाएगा, केवल वर्तमान में चल रहे कमांड से बाहर निकलने के बाद)।
आदर्श रूप से, हम अपने माता-पिता को रिपोर्ट करना चाहते हैं कि हम एक SIGINT से मर गए (ताकि यदि bash
उदाहरण के लिए यह एक और स्क्रिप्ट है, तो वह bash
स्क्रिप्ट भी बाधित होती है)। ऐसा करना exit 130
SIGINT के मरने के समान नहीं है (हालांकि कुछ गोले $?
दोनों मामलों के लिए समान मूल्य पर सेट होंगे ), हालांकि इसका उपयोग अक्सर SIGINT द्वारा मौत की रिपोर्ट करने के लिए किया जाता है (उन प्रणालियों पर जहां SIGINT 2 सबसे अधिक है)।
हालाँकि bash
, ksh93
या FreeBSD के लिए sh
, यह काम नहीं करता है। उस 130 बाहर निकलने की स्थिति को SIGINT द्वारा मृत्यु के रूप में नहीं माना जाता है और एक मूल स्क्रिप्ट वहां गर्भपात नहीं करेगी ।
तो, SIGINT प्राप्त करने पर SIGINT के साथ हमारे आप को मारने के लिए संभवतः एक बेहतर विकल्प होगा:
trap '
trap - INT # restore default INT handler
kill -s INT "$$"
' INT
for f in *.txt; do vi "$f"; cp "$f" newdir; done
। यदि उपयोगकर्ता किसी एक फाइल को संपादित करते समय Ctrl + C टाइपvi
करता है , तो बस एक संदेश प्रदर्शित करता है। यह उचित लगता है कि उपयोगकर्ता द्वारा फाइल को संपादित करने के बाद लूप जारी रहना चाहिए। (और हां, मुझे पता है कि आप कह सकते हैंvi *.txt; cp *.txt newdir
; मैं सिर्फfor
एक उदाहरण के रूप में लूप प्रस्तुत कर रहा हूं ।)