शेल स्क्रिप्ट से, दिए गए लाइन को आउटपुट करने के बाद किल प्रोग्राम


16

पृष्ठभूमि:

मैं कम्प्यूटेशनल बायोलॉजी सॉफ़्टवेयर के एक टुकड़े के लिए एक परीक्षण स्क्रिप्ट लिख रहा हूं। मैं जिस सॉफ्टवेयर का परीक्षण कर रहा हूं, उसे चलाने के लिए दिन या सप्ताह भी लग सकते हैं, इसलिए इसमें सिस्टम के क्रैश या खराब होने की स्थिति में रिकवरी फंक्शनलिटी है।

मैं यह पता लगाने की कोशिश कर रहा हूं कि वसूली प्रणाली का परीक्षण कैसे किया जाए। विशेष रूप से, मैं नियंत्रित तरीके से प्रोग्राम को "क्रैश" करने का तरीका नहीं समझ सकता। मैं किसी भी तरह समय की कुछ राशि के बाद चलाने के लिए एक SIGKILL निर्देश के बारे में सोच रहा था। यह शायद आदर्श नहीं है, क्योंकि परीक्षण मामले में हर बार एक ही गति को चलाने की गारंटी नहीं है (यह एक साझा वातावरण में चलता है), इसलिए लॉग को वांछित आउटपुट से तुलना करना मुश्किल होगा।

यह सॉफ़्टवेयर विश्लेषण के प्रत्येक अनुभाग के लिए एक लाइन प्रिंट करता है।

सवाल:

मैं सोच रहा था कि क्या किसी प्रोग्राम से आउटपुट कैप्चर करने के लिए एक अच्छा / सुरुचिपूर्ण तरीका (शेल स्क्रिप्ट में) था और प्रोग्राम को तब मारना चाहिए जब प्रोग्राम द्वारा किसी लाइन / # लाइन का आउटपुट हो?


1
आपको एक विशिष्ट समय पर कार्यक्रम को रोकने की आवश्यकता क्यों है? आउटपुट बफ़रिंग के कारण आप प्रोग्राम को उस समय तक मार सकते हैं जब वह आपके द्वारा चेक किए जा रहे टेक्स्ट को आउटपुट करता है।
२०:१२

@stardt मैं एक विशिष्ट समय पर कार्यक्रम को रोकना चाहता था ताकि परीक्षण के परिणाम अधिक नियंत्रित और प्रतिलिपि प्रस्तुत करने योग्य हों। मुझे अब इसके चारों ओर एक रास्ता मिल गया है। मैं प्रोग्राम को केवल एक बार मैन्युअल रूप से मारूंगा, फिर केवल रिकवरी कोड का परीक्षण करूंगा। सभी पुनर्प्राप्ति प्रयास एक ही बिंदु से शुरू होंगे। मैं परीक्षण कर रहा हूं कि यह कैसे ठीक हो जाता है, न कि यह कैसे दुर्घटनाग्रस्त हो जाता है :)
पॉल

जवाबों:


7

इस तरह की एक रैपर स्क्रिप्ट एक मानक दृष्टिकोण है। स्क्रिप्ट पृष्ठभूमि में प्रोग्राम चलाता है और फिर लूप करता है, कुछ स्ट्रिंग के लिए हर मिनट लॉग फ़ाइल की जाँच करता है। यदि स्ट्रिंग पाया जाता है, तो पृष्ठभूमि कार्यक्रम को मार दिया जाता है और स्क्रिप्ट को छोड़ दिया जाता है।

command="prog -foo -whatever"
log="prog.log"
match="this is the what i want to match"

$command > "$log" 2>&1 &
pid=$!

while sleep 60
do
    if fgrep --quiet "$match" "$log"
    then
        kill $pid
        exit 0
    fi
done

15

यदि आपका कार्यक्रम SIGPIPE (जो डिफ़ॉल्ट क्रिया है) पर समाप्त हो जाएगा, तो यह आउटपुट को एक पाठक में पाइप करने के लिए पर्याप्त होना चाहिए जो उस लाइन को पढ़ने पर बाहर निकल जाएगा।

तो यह जितना सरल हो सकता है

$ program | sed -e '/Suitable text from the line/q'

यदि आप डिफ़ॉल्ट आउटपुट उपयोग को दबाना चाहते हैं

$ program | sed -n -e '/Suitable text from the line/q'

इसी तरह अगर कोई एक निश्चित संख्या में लाइनों के बाद रुकना चाहता है तो सिर सेड की जगह इस्तेमाल कर सकता है

$ program | head -n$NUMBER_OF_LINES_TO_STOP_AFTER

जिस समय हत्या होती है, उसका सटीक समय टर्मिनल के बफरिंग व्यवहार पर निर्भर करता है क्योंकि टिप्पणियों में स्टार्ड का सुझाव है।


-1। यहाँ एक गंभीर दोष है। कार्यक्रम तभी समाप्त होगा जब (यदि) यह sedसमाप्त होने के बाद (टूटे हुए) पाइप पर लिखने की कोशिश करता है । ओपी का कहना है कि "यह सॉफ्टवेयर विश्लेषण के प्रत्येक खंड के लिए एक लाइन प्रिंट करता है जो इसे पूरा करता है"। इसका मतलब यह हो सकता है कि कार्यक्रम एक अतिरिक्त अनुभाग को पूरा करेगा! अवधारणा का प्रमाण { echo 1; sleep 3; >&2 echo peekaboo; sleep 3; echo 2; } | sed -e '/1/q':। इस जवाब को देखें । संभव समाधान ( program & ) | sed -e '/Suitable text from the line/q'; killall program:। अपने जवाब को दोष के बारे में अवगत कराएं और मैं अपने अपमान को रद्द कर दूंगा।
कामिल मैकियोरोस्की

हम्म् ... वास्तव में। और बफ़रिंग समस्या आपके सुधार के साथ भी अविश्वसनीय होती है (हालाँकि, निश्चित रूप से, जो मेरे द्वारा देखे गए हर समाधान को प्रभावित करता है)। मैं संभव होने पर सिग्नल के बुनियादी ढांचे का उपयोग करना पसंद करता हूं, लेकिन कुछ बिंदु पर यह लालित्य खोने लगता है। शायद यह बेहतर है कि पूरी चीज को ही स्क्रैप कर दिया जाए।
dmckee --- पूर्व-मध्यस्थ बिल्ली का बच्चा

7

Dmckee के उत्तर के विकल्प के रूप में, विकल्प के grepसाथ कमांड -m(उदाहरण के लिए यह मैन पेज देखें ) कमांड का भी उपयोग किया जा सकता है:

compbio | grep -m 1 "Text to match"

बंद करने के लिए जब 1 पंक्ति पाठ मिल रहा है या

compbio | grep -v -m 10 "Text to match"

10 पंक्तियों के लिए प्रतीक्षा करें जो दिए गए पाठ से मेल नहीं खाती हैं।


3

आप expect(1)एक कार्यक्रम के स्टडआउट को देखने के लिए उपयोग कर सकते हैं फिर कुछ पैटर्न पर पूर्वनिर्धारित कार्रवाई को निष्पादित कर सकते हैं ।

#!/usr/bin/env expect

spawn your-program -foo -bar 
expect "I want this text" { close }

या किसी अन्य स्क्रिप्ट में एम्बेड करने के लिए एक-लाइनर:

expect -c "spawn your-program -foo -bar; expect \"I want this text\" { close }"

ध्यान दें कि expectकमांड हर ओएस के साथ डिफ़ॉल्ट रूप से नहीं आता है। आपको इसे स्थापित करने की आवश्यकता हो सकती है।


यह अच्छा उपाय है। मैं set timeout -1अनिश्चितकालीन समय निर्धारित करने के लिए उल्लेख करने की सलाह देता हूं , अन्यथा यह सभी expectडिफ़ॉल्ट 10 एस टाइमआउट के तहत बंद हो जाएगा ।
काली मिर्च_ मिर्च

1

आप "समय" कथन का उपयोग कर सकते हैं:

आपको अपने सॉफ़्टवेयर (या उसके लॉग्स) के आउटपुट को पाइप करना होगा और फिर, प्रत्येक नई लाइन के लिए, एक सशर्त परीक्षण करना होगा, फिर किल -किला चलाना होगा। उदाहरण के लिए (मैंने लॉगफ़ाइल के रूप में / var / log / संदेशों के साथ परीक्षण किया):

tail -f /var/log/messages | while read line; do test "$line" = "THE LINE YOU WANT TO MATCH" && kill PIDTOKILL; done

या सीधे सॉफ्टवेयर के साथ:

./biosoftware | while read line; do test "$line" = "THE LINE YOU WANT TO MATCH" && kill PIDTOKILL; done

आपको लॉग पथ / एप्लिकेशन का नाम, मिलान करने के लिए लाइन और PID को मारने के लिए (आपको किलॉल का उपयोग भी कर सकते हैं) को हटाने की आवश्यकता है।

अपने सॉफ्टवेयर के साथ गुड लक,

ह्यूगो,

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