एक अनंत लूप को समाप्त करना


52

मेरे पास एक कमांड है जिसे मैं हर बार समाप्त होने पर फिर से स्वचालित रूप से चलाना चाहता हूं, इसलिए मैंने कुछ इस तरह से भाग लिया:

while [ 1 ]; do COMMAND; done;

लेकिन अगर मैं उस लूप को नहीं रोक सकता, Ctrl-cजैसा कि सिर्फ मारता है COMMANDऔर पूरे लूप को नहीं।

मैं ऐसा ही कुछ कैसे हासिल करूंगा लेकिन जिसे मैं टर्मिनल को बंद किए बिना रोक सकता हूं?


11
अगर मैं बकवास कर रहा हूं तो मैं काम को रोकने के लिए Ctrl-Z का उपयोग करता हूं और फिर इसे मारने के लिए "% 1 मारता हूं"।
पॉल नागर

3
बस प्रतीक्षा करें ... लिनुस को यह कहते हुए उद्धृत किया गया था: "हम सभी जानते हैं कि लिनक्स महान है ... यह 5 सेकंड में अनंत छोरों करता है।" - तो वास्तव में ... बस कुछ और सेकंड प्रतीक्षा करें, इसे पूरा करना चाहिए।
lornix

@PaulCager ने मेरे लिए भी काम किया! वह काम क्यों करता है जहाँ Ctrl-C नहीं है?
सिरो सेंटिल्ली 新疆 i i i 事件 '15

@cirosantilli यह बाहरी नौकरी (बैश "रैपर") को मारता है। कुछ स्थितियों में, यह तुरंत "COMMAND" को नहीं मारेगा, उदाहरण के लिए, यदि आप इसे पृष्ठभूमि में रखते हैं, तो यह पिछले जीवित हो सकता है, भले ही यह माता-पिता की मृत्यु हो। लेकिन पाश मर चुका है, और यह महत्वपूर्ण हिस्सा है।
ओरियन

जवाबों:


37

कमांड की निकास स्थिति की जाँच करें। यदि कमांड को सिग्नल द्वारा समाप्त किया गया था, तो एक्जिट कोड 128 + सिग्नल नंबर होगा। गश के लिए GNU ऑनलाइन प्रलेखन से :

शेल के उद्देश्यों के लिए, एक शून्य निकास स्थिति के साथ बाहर निकलने वाला एक आदेश सफल रहा है। एक गैर-शून्य निकास स्थिति विफलता को इंगित करती है। यह प्रतीत होता है कि काउंटर-सहज ज्ञान युक्त योजना का उपयोग किया जाता है, इसलिए सफलता को इंगित करने के लिए एक अच्छी तरह से परिभाषित तरीका है और विभिन्न विफलता मोड को इंगित करने के विभिन्न तरीके हैं। जब कोई कमांड घातक संकेत पर समाप्त होता है जिसकी संख्या N है, तो बैश निकास स्थिति के रूप में मान 128 + N का उपयोग करता है।

POSIX यह भी निर्दिष्ट करता है कि एक संकेत द्वारा समाप्त की गई कमांड का मूल्य 128 से अधिक है, लेकिन इसके सटीक मान को निर्दिष्ट नहीं करता है जैसे GNU करता है:

एक आदेश की समाप्ति स्थिति जिसे संकेत मिला क्योंकि उसे 128 से अधिक बताया जाएगा।

उदाहरण के लिए, यदि आप नियंत्रण-सी के साथ एक कमांड को बाधित करते हैं तो निकास कोड 130 होगा, क्योंकि सिगंट यूनिक्स सिस्टम पर सिग्नल 2 है। इसलिए:

while [ 1 ]; do COMMAND; test $? -gt 128 && break; done

9
यह उल्लेख किया जाना चाहिए कि यह गारंटी नहीं है, वास्तव में, कई एप्लिकेशन ऐसा नहीं करेंगे।
क्रिस डाउन

1
@ काइल जोन्स: क्या आप पोसिक्स / जीएनयू डॉक्स से लिंक कर सकते हैं जो इसका उल्लेख करते हैं?
सिरो सेंटिल्ली 新疆 改造 iro i 事件 '15

@cirosantilli किया।
काइल जोन्स

@KyleJones धन्यवाद! अभी भी व्यवहार में COMMAND = के लिए काम नहीं कर रहा है paplay alert.ogg, शायद क्योंकि paplayसंकेत संभालता है?
सिरो सेंटिल्ली 新疆 改造 i i 事件 '16

@cirosantilli हां, यही कारण है। यदि कोई प्रक्रिया सिग्नल को संभालती है और क्विट करती है, तो यह प्रक्रिया एक अनहेल्ड सिग्नल द्वारा समाप्त होने से अलग है।
काइल जोन्स

48

ctrl+ का उपयोग करते हुए आप अपनी नौकरी को रोक सकते हैं और पृष्ठभूमि में रख सकते हैं z। तब आप अपनी नौकरी को मार सकते हैं:

$ kill %1

जहां [1] आपका काम नंबर है।


स्पष्टीकरण और अधिक के लिए यह उत्तर भी देखें ।
स्किप्पी ले ग्रैंड गौरू

2
यह अपेक्षाकृत हाल ही में जवाब बस काम करता है। उखाड़ने की जरूरत है। +1
shivams

आपने मेरी बहुत मदद की। यह वही है जो मैंने इस प्रश्न में खोजा है :)
मैक्सिमिलियन रूटा

18

मैं कहूंगा कि एक स्क्रिप्ट में अपने अनंत लूप को डालना और वहां संकेतों को संभालना सबसे अच्छा हो सकता है। यहाँ एक मूल प्रारंभिक बिंदु है । मुझे यकीन है कि आप इसे सूट करना चाहते हैं। स्क्रिप्ट trapपकड़ने के लिए उपयोग करता है ctrl- c(या SIGTERM), कमांड को मारता है (मैंने sleepयहां परीक्षण के रूप में उपयोग किया है) और बाहर निकलता है।

cleanup ()
{
kill -s SIGTERM $!
exit 0
}

trap cleanup SIGINT SIGTERM

while [ 1 ]
do
    sleep 60 &
    wait $!
done

4
अच्छा लगा। यहां बताया गया है कि मैंने इस टिप का इस्तेमाल ऑटोरस्टार्टिंग नेटकैट रैपर बनाने के लिए कैसे किया:trap "exit 0" SIGINT SIGTERM; while true; do netcat -l -p 3000; done
डगलस

2
अगर आप इस trapदृष्टिकोण को उसी (bash) स्क्रिप्ट के साथ जोड़ते हैं जिसमें अनंत पाश को मार दिया जाए, तो $$इसके बजाय का उपयोग करें $!( यहाँ देखें )
ardnew

15

मैं आमतौर पर बस पकड़ता हूं Ctrl-C। जल्दी या बाद में यह रजिस्टर होगा COMMANDऔर इस तरह whileलूप को समाप्त करेगा । शायद एक बेहतर तरीका है।


1
यकीन नहीं क्यों, लेकिन यह paplay1s फ़ाइल की तरह कुछ COMMANDs के लिए विफल रहता है ।
सिरो सेंटिल्ली 新疆 改造 i i 事件 '15

इसने मेरे लिए काम किया
अलेक्जेंडर

यही कारण है कि सभी समाधानों की क्रूर ताकत है। : /
चिह्नक


7

बस क्यों नहीं,

while [ 1 ]; do COMMAND || break; done;

या जब एक स्क्रिप्ट में इस्तेमाल किया,

#!/bin/bash
while [ 1 ]; do
  # ctrl+c terminates COMMAND and exits the while loop
  # (assuming COMMAND responds to ctrl+c)
  COMMAND || break
done;

1
बहुत ही सुंदर समाधान। लेकिन क्या यह केवल काम नहीं करेगा यदि COMMAND हमेशा सफलता से बाहर निकलने की स्थिति में आए?
हावर्ड

हाँ @ हर्ष, यह सही है।
डेल एंडरसन

3

मैं एक और समाधान पसंद करते हैं:

touch .runcmd; while [ -f ".runcmd" ]; do COMMAND; sleep 1; done

पाश को मारने के लिए, बस करें:

rm .runcmd && kill `pidof COMMAND`

2
  1. आप हमेशा इसकी PID का उपयोग करके एक प्रक्रिया को मार सकते हैं, अपने टर्मिनल को बंद करने की कोई आवश्यकता नहीं है
  2. यदि आप एक अनंत लूप में एक डेमॉन की तरह कुछ चलाना चाहते हैं, तो आप इसे पृष्ठभूमि में डाल देंगे
  3. while : एक अनंत लूप बनाएगा और आपको लिखने से बचाएगा [ 1 ]

    while :; do COMMAND; done &

यह पीआईडी ​​प्रिंट करेगा। यदि आप अपने प्रॉम्प्ट का उपयोग कर बाहर निकलते हैं, ctrl+dतो पृष्ठभूमि नौकरी नहीं छोड़ेगी, और आप बाद में कहीं भी उपयोग करने से नौकरी को मार सकते हैंkill PID

यदि आप अपने पीआईडी ​​का ट्रैक खो देते हैं, तो आप इसे ढूंढने में मदद pstree -pa $USERया उपयोग कर सकते हैंpgrep -fl '.*PROCESS.*'


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.