एक शेल स्क्रिप्ट लिखने की कोशिश करना, जो किसी सर्वर का परीक्षण दूरस्थ रूप से करता रहता है, लेकिन जब मैं लॉगआउट करता हूं तो यह दूसरे स्टेटमेंट में गिरता रहता है


9

यहां एक शेल स्क्रिप्ट लिखने की कोशिश की जा रही है जो मेरे सर्वर का परीक्षण करती रहती है और नीचे होने पर मुझे ईमेल करती है।

समस्या यह है कि जब मैं ssh कनेक्शन से लॉगआउट करता हूं , तो इसे &कमांड के अंत में चलाने के बावजूद , जैसे ही ./stest01.sh &, यह स्वचालित रूप से दूसरे में गिर जाता है और मुझे बिना किसी बाधा के मेल करता रहता है, जब तक कि मैं फिर से लॉग इन नहीं करता और इसे मार देता हूं।

#!/bin/bash
while true; do
    date > sdown.txt ;
    cp /dev/null pingop.txt ;
    ping -i 1 -c 1 -W 1 myserver.net > pingop.txt &
    sleep 1 ;
    if
        grep "64 bytes" pingop.txt ;
    then
        :
    else
        mutt -s "Server Down!" myemail@address.com < sdown.txt ;
        sleep 10 ;
    fi
done

1
मैं बैश विशेषज्ञ नहीं हूं, लेकिन बृहदान्त्र क्या करता :है? यह मुझे समझ में आता है कि यह एक अर्धविराम था ;...
नेड64

3
@ नेड64 :कुछ नहीं करता है। यह ऐसा करने के लिए डिज़ाइन किया गया है। इधर, परीक्षण के अयोग्य होने के बजाय, वे इसका उपयोग करने से पहले नो-ऑप करते हैं else
Kusalananda

@ कुसलानंद ओके, धन्यवाद। सोचा कि यह एक टाइपो हो सकता है जो समस्या की व्याख्या कर सकता है।
नेड64

1
मैं भी उलझन में हूं कि लॉगआउट के बाद शेल स्क्रिप्ट को छोड़ने की कोशिश क्यों की जाएगी। क्या क्रोन या सिस्टमड टाइमर इसके लिए बेहतर विकल्प नहीं होंगे?
क्लिफ आर्मस्ट्रांग

जवाबों:


20

जब जीएनयू grepअपना परिणाम लिखने की कोशिश करता है, तो यह एक गैर-शून्य निकास स्थिति के साथ विफल हो जाएगा, क्योंकि इसमें आउटपुट लिखने के लिए कहीं नहीं है, क्योंकि एसएसएच कनेक्शन चला गया है।

इसका मतलब है कि ifबयान हमेशा elseशाखा ले रहा है ।

इसे स्पष्ट करने के लिए ( आपके मामले में वास्तव में ऐसा नहीं है , लेकिन यह दिखाता है कि क्या होता है अगर GNU grepअपना आउटपुट लिखने में असमर्थ है):

$ echo 'hello' | grep hello >&- 2>&-
$ echo $?
2

यहां हम grepउस स्ट्रिंग के लिए हैं जो echoउत्पादन करता है, लेकिन हम दोनों आउटपुट स्ट्रीम को बंद कर देते हैं grepताकि यह कहीं भी न लिख सके। जैसा कि आप देख सकते हैं, GNU grepका निकास स्थिति 0 के बजाय 2 है।

यह विशेष रूप से जीएनयू के लिए है grep, grepबीएसडी सिस्टम पर समान व्यवहार नहीं होगा:

$ echo 'hello' | grep hello >&- 2>&-    # using BSD grep here
$ echo $?
0

इसे मापने के लिए, सुनिश्चित करें कि स्क्रिप्ट आउटपुट उत्पन्न नहीं करती है। आप इसके साथ कर सकते हैं exec >/dev/null 2>&1। इसके अलावा, हमें grepइसके -qविकल्प का उपयोग करना चाहिए क्योंकि हम इसमें से आउटपुट को देखने के इच्छुक नहीं हैं (यह आम तौर पर गति भी बढ़ाएगा grepक्योंकि इसे पूरी फ़ाइल को पार्स करने की आवश्यकता नहीं है, लेकिन इस मामले में यह बहुत कम है गति में अंतर चूंकि फ़ाइल इतनी छोटी है)।

संक्षेप में:

#!/bin/sh

# redirect all output not redirected elsewhere to /dev/null by default:
exec >/dev/null 2>&1

while true; do
    date >sdown.txt

    ping -c 1 -W 1 myserver.net >pingop.txt

    if ! grep -q "64 bytes" pingop.txt; then
        mutt -s "Server Down!" myemail@address.com <sdown.txt
        break
    fi

    sleep 10
done

आप pingइंटरमीडिएट फ़ाइलों में से किसी एक की आवश्यकता को हटाते हुए (और वास्तव में कभी केवल एक डेटास्टैम्प शामिल कर सकते हैं) भी सीधे परीक्षण पर उपयोग कर सकते हैं :

#!/bin/sh

exec >/dev/null 2>&1

while true; do
    if ! ping -q -c 1 -W 1 myserver.net; then
        date | mutt -s "Server Down!" myemail@address.com
        break
    fi

    sleep 10
done

उपरोक्त स्क्रिप्ट के दोनों रूपों में, मैं होस्ट तक पहुंचने में विफलता पर पाश से बाहर निकलने का चयन करता हूं, बस भेजे गए ईमेल की संख्या को कम करने के लिए। यदि आप सर्वर से अंततः फिर से आने की अपेक्षा करते हैं, तो आप इसके बजाय breakउदाहरण के लिए sleep 10mया कुछ और के साथ बदल सकते हैं ।

मैं भी थोड़ा के साथ इस्तेमाल किया विकल्प के pingरूप में -i 1ज्यादा मतलब नहीं है के साथ tweaked है -c 1

शॉर्टर (जब तक आप यह नहीं चाहते कि मेजबान के अप्राप्य होने पर ईमेल भेजना जारी रहे):

#!/bin/sh

exec >/dev/null 2>&1

while ping -q -c 1 -W 1 myserver.net; do
    sleep 10
done

date | mutt -s "Server Down!" myemail@address.com

क्रोन जॉब के रूप में हर मिनट चल रहा है (यदि सर्वर डाउन रहता है तो हर मिनट ईमेल भेजना जारी रहेगा):

* * * * * ping -q -c 1 -W 1 >/dev/null 2>&1 || ( date | mail -s "Server down" myemail@address.com )

उपयोग >&-करने से fd बंद हो जाएगा (जैसा कि, फ़ाइल डिस्क्रिप्टर 1 बंद है), जबकि SSH कनेक्शन को बंद करने का एक अलग प्रभाव होगा (एक फाइल डिस्क्रिप्टर अभी भी चारों ओर होगा, लेकिन दूसरी तरफ कुछ भी जुड़ा नहीं है।) मुझे लगता है कि बिंदु अभी भी खड़ा है, जो यह है कि GNU grep गैर-शून्य से बाहर निकलता है अगर यह आउटपुट लिखने की कोशिश करता है और वह विफल हो जाता है। हाँ, सबसे अच्छा समाधान सीधे पिंग के बाहर निकलने की स्थिति की जाँच कर रहा है।
filbranden

4
यह exec </dev/null >/dev/null 2>&1शुरुआत के पास जोड़कर पूरी स्क्रिप्ट के लिए / से / dev / null के लिए सब कुछ पुनर्निर्देशित करने के लिए सुरक्षित हो सकता है । इस तरह अगर उदाहरण के pingलिए कुछ लिखने का फैसला किया है तो यह एक समस्या का कारण नहीं होगा।
गॉर्डन डेविसन

@GordonDavisson मुझे वास्तव में स्टड को /dev/nullयहाँ से खींचने का कोई कारण नहीं दिखता है, लेकिन मैंने आउटपुट को हल कर दिया है। सलाह के लिये धन्यवाद।
Kusalananda
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.