क्या होता है कि दोनों है bashऔर pingSIGINT प्राप्त ( bashकिया जा रहा नहीं इंटरैक्टिव, दोनों pingऔर bashएक ही प्रक्रिया समूह है जो इंटरैक्टिव खोल आप से है कि स्क्रिप्ट चलाने के द्वारा बनाई गई है और सेट टर्मिनल के अग्रभूमि प्रक्रिया समूह के रूप में में चलाने)।
हालाँकि, bashउस SIGINT को असिंक्रोनस तरीके से हैंडल करता है, केवल वर्तमान में चल रहे कमांड से बाहर निकलने के बाद। bashकेवल उस SIGINT को प्राप्त करने पर बाहर निकलता है यदि वर्तमान में चल रही कमांड SIGINT की मृत्यु हो जाती है (अर्थात इसकी निकास स्थिति इंगित करती है कि यह SIGINT द्वारा मार दी गई है)।
$ bash -c 'sh -c "trap exit\ 0 INT; sleep 10; :"; echo here'
^Chere
इन सबसे ऊपर, bash, shऔर sleepSIGINT जब मैं Ctrl-C दबाएँ प्राप्त करते हैं, लेकिन shबाहर निकलता है एक 0 बाहर निकलने के कोड के साथ सामान्य रूप से है, इसलिए bashSIGINT पर ध्यान नहीं देता है, जो कारण है कि हम "यहाँ" देखें।
pingकम से कम iputils से एक, ऐसा व्यवहार करता है। बाधित होने पर, यह आँकड़े प्रिंट करता है और 0 या 1 के बाहर निकलने की स्थिति के साथ बाहर निकलता है, इस पर निर्भर करता है कि उसके पिंग्स का उत्तर दिया गया था या नहीं। इसलिए, जब आप pingरनिंग के दौरान Ctrl-C दबाते हैं, तो bashजो नोट्स आपने Ctrl-Cअपने SIGINT हैंडलर्स में दबाए हैं , लेकिन चूंकि pingसामान्य रूप से बाहर निकलता है, bashइसलिए बाहर नहीं निकलता है।
यदि आप sleep 1उस लूप में जोड़ते हैं और दौड़ते Ctrl-Cसमय दबाते हैं sleep, क्योंकि sleepSIGINT पर कोई विशेष हैंडलर नहीं है, तो वह मर जाएगा और 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
bashSIGINT प्राप्त करने के लिए बाहर निकलने के लिए बाध्य करने के लिए स्क्रिप्ट के शीर्ष पर (ध्यान दें कि किसी भी स्थिति में, SIGINT को समकालिक रूप से संसाधित नहीं किया जाएगा, केवल वर्तमान में चल रहे कमांड से बाहर निकलने के बाद)।
आदर्श रूप से, हम अपने माता-पिता को रिपोर्ट करना चाहते हैं कि हम एक SIGINT से मर गए (ताकि यदि bashउदाहरण के लिए यह एक और स्क्रिप्ट है, तो वह bashस्क्रिप्ट भी बाधित होती है)। ऐसा करना exit 130SIGINT के मरने के समान नहीं है (हालांकि कुछ गोले $?दोनों मामलों के लिए समान मूल्य पर सेट होंगे ), हालांकि इसका उपयोग अक्सर 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एक उदाहरण के रूप में लूप प्रस्तुत कर रहा हूं ।)