किसी विशेष कमांड के लिए त्रुटि को अनदेखा करें


444

मैं निम्नलिखित विकल्पों का उपयोग कर रहा हूं

set -o pipefail
set -e

त्रुटि पर निष्पादन को रोकने के लिए बैश स्क्रिप्ट में। मेरे पास स्क्रिप्ट निष्पादित करने की ~ 100 लाइनें हैं और मैं स्क्रिप्ट में हर लाइन का रिटर्न कोड नहीं देखना चाहता।

लेकिन एक विशेष आदेश के लिए, मैं त्रुटि को अनदेखा करना चाहता हूं। मैं उसे कैसे कर सकता हूँ?

जवाबों:


757

समाधान:

particular_script || true

उदाहरण:

$ cat /tmp/1.sh
particular_script()
{
    false
}

set -e

echo one
particular_script || true
echo two
particular_script
echo three

$ bash /tmp/1.sh
one
two

three कभी नहीं छपेगा।

इसके अलावा, मैं यह जोड़ना चाहता हूं कि जब pipefailचालू होता है, तो शेल के लिए यह सोचना पर्याप्त है कि पूरे पाइप में गैर-शून्य निकास कोड है जब पाइप में कमांड में से एक में गैर-शून्य निकास कोड होता है (इसके साथ pipefailअंतिम एक होना चाहिए) ।

$ set -o pipefail
$ false | true ; echo $?
1
$ set +o pipefail
$ false | true ; echo $?
0

15
+1। जैसा कि बैश संदर्भ नियमावली बताती है , "शेल तब बाहर नहीं निकलता है" जब -eविशेषता सेट हो जाती है "यदि वह कमांड विफल हो जाती है जो कमांड लिस्ट का हिस्सा है whileया एक untilकीवर्ड के तुरंत बाद , एक ifस्टेटमेंट में परीक्षण का हिस्सा, किसी भी कमांड का हिस्सा निष्पादित होता है। अंतिम या , किसी पाइपलाइन में किसी भी कमांड को छोड़कर या अंतिम, या यदि कमांड की वापसी की स्थिति को उलटा किया जा रहा है, तो सिवाय एक &&या ||सूची के । " &&||!
बरबाद

@IgorChubin मैं पता नहीं क्यों, लेकिन उनका कार्य उत्पादन नहीं करते हैं = (ldd $2/bin/* || true) | grep "not found" | wc -lस्क्रिप्ट इस लाइन के बाद समाप्त होता है जब ldd वापसी विफलता
विवेक गोयल

1
(ldd $2/bin/* || true) | grep "not found" | wc -l || true
इगोर चुबिन

1
की वजह से set -o pipefail। जब grepकुछ नहीं मिलता है, तो वह गैर-शून्य निकास कोड देता है और शेल के लिए यह सोचना पर्याप्त है कि पूरे पाइप में गैर-शून्य निकास कोड है।
इगोर चुबिन

3
यदि आप वापसी मूल्य (बिना बाहर निकाले) को संरक्षित करने का विकल्प चाहते हैं, तो आप mycommand && सत्य की कोशिश करें। यह आपको बाद के चरणों में रिटर्न कोड की जांच करने और इसे प्रोग्रामेटिक रूप से संभालने की अनुमति देता है।
एड ऑस्ट

179

केवल || trueउस कमांड के बाद जोड़ें जहां आप त्रुटि को अनदेखा करना चाहते हैं।


11
मुझे लगता है कि इसे जोड़ना महत्वपूर्ण है: यह विधि प्रतिक्रिया कोड और त्रुटि संदेश को जारी रखने की अनुमति देगा, जबकि "!" नीचे उल्लिखित विधि प्रतिक्रिया कोड को बदल देगी और इस प्रकार त्रुटि उत्पन्न नहीं करेगी। set -eकिसी त्रुटि संदेश को पकड़ने और उपयोग करने की कोशिश करते समय यह महत्वपूर्ण है : उदाहरण के लिएset -e; TEST=$(foo 2>&1 || true); echo $TEST
स्पंकी

87

बंद करो और बाहर निकलने की स्थिति को भी न बचाएं

यदि आप चाहते हैं कि आपकी स्क्रिप्ट बंद न हो, यदि कोई विशेष आदेश विफल हो जाता है और आप असफल कमांड के त्रुटि कोड को भी सहेजना चाहते हैं:

set -e
EXIT_CODE=0
command || EXIT_CODE=$?
echo $EXIT_CODE

2
यह वही है जो मुझे चाहिए था
19 'sarink

किसी कारण से मेरे लिए काम नहीं करता है ... ओह अच्छी तरह से
Jeef

EXIT_CODE को शून्य पर सेट नहीं किया जाता है जब कमांड रिटर्न 0. गैर शून्य निकास कोड पर कब्जा कर लिया जाता है। कोई विचार क्यों?
अंकिता 13

@ अंकिता 13 क्योंकि अगर यह शून्य था तो पहला commandसफल था और इसके बाद जो होना चाहिए उसे चलाने की आवश्यकता है ||। इसे इस रूप में पढ़ें: यदि commandविफल रहता है, तो करें EXIT_CODE=$?। आप शायद command || echo "$?"अधिक क्रिया डिबगिंग के लिए बस "जाल" का उपयोग या उपयोग कर सकते हैं । इसे देखें -> stackoverflow.com/a/6110446/10737630
टिनिंक

63

अधिक संक्षेप में:

! particular_script

से POSIX विनिर्देशन के बारे में set -e(जोर मेरा):

जब यह विकल्प चालू होता है, यदि कोई साधारण आदेश शेल त्रुटियों के परिणामों में सूचीबद्ध कारणों में से किसी एक के लिए विफल रहता है या एक निकास स्थिति मान> 0 लौटाता है, और कीवर्ड, और यदि कीवर्ड, और थोड़ी देर के बाद यौगिक सूची का हिस्सा नहीं है, तो एक और या सूची का हिस्सा नहीं है, और एक पाइप लाइन से पहले नहीं है ! आरक्षित शब्द , तो शेल तुरंत बाहर निकल जाएगा।


16
यह केवल एक कमांड के एग्जिट कोड को निकालता है, इसलिए सफलतापूर्वक समाप्त होने वाली कमांड 0 के बजाय 1 वापस आ जाएगी और स्क्रिप्ट को विफल कर देगी -e
मर्बोनी

17
मेरी समझ यह है कि यह !खोल किसी भी मामले से बाहर निकलने से रोकेगा। जब मैं इसे चलाता हूं तो यह स्क्रिप्ट संदेश प्रदर्शित करती Still alive!है, यह दर्शाता है कि स्क्रिप्ट पूरी होने के लिए दौड़ी है। क्या आप अलग व्यवहार देख रहे हैं?
लिली फिनाले

7
आप सही हैं, यह बाहर निकलने की स्थिति का संकेत देता है, लेकिन स्क्रिप्ट को क्रैश नहीं करता है जब कमांड 0 या 1 दोनों के साथ समाप्त होता है। मैं असावधान था। वैसे भी, प्रलेखन उद्धृत करने के लिए धन्यवाद, मैंने अपनी अभिव्यक्ति को ifखंड में रखा और समस्या को हल किया।
मर्बोनी

42

"वापस लौटने" के बजाय, आप "नॉप" या अशक्त उपयोगिता का उपयोग भी कर सकते हैं (जैसा कि पोसिक्स स्पेक्स में कहा गया है ) :और सिर्फ "कुछ भी न करें"। आप कुछ अक्षर बचा लेंगे। :)

#!/usr/bin/env bash
set -e
man nonexistentghing || :
echo "It's ok.."

3
यद्यपि ||: जैसा स्पष्ट नहीं है || सच (जो गैर विशेषज्ञ उपयोगकर्ताओं को भ्रमित कर सकता है), मुझे यह पसंद है
डेविड

यह संस्करण किसी भी पाठ को वापस नहीं करता है जो CI में महत्वपूर्ण हो सकता है।
किवगंत

5

यदि आप अपनी स्क्रिप्ट को विफल होने से रोकना चाहते हैं और रिटर्न कोड एकत्र करना चाहते हैं :

command () {
    return 1  # or 0 for success
}

set -e

command && returncode=$? || returncode=$?
echo $returncode

returncode कोई भी बात एकत्रित नहीं की जाती है, चाहे कमांड सफल हो या विफल।


2

मैं CLI टूल के साथ काम करते समय नीचे दिए गए स्निपेट का उपयोग कर रहा हूं और मैं जानना चाहता हूं कि कुछ संसाधन मौजूद हैं या नहीं, लेकिन मुझे आउटपुट की परवाह नहीं है।

if [ -z "$(cat no_exist 2>&1 >/dev/null)" ]; then
    echo "none exist actually exist!"
fi

1
यह कहने के लिए एक बहुत ही गोल चक्कर और मामूली महंगा तरीका लगता हैif [ -r not_exist ]
ट्रिपल

1

मुझे यह समाधान पसंद है:

: `particular_script`

बैक टिक के बीच कमांड / स्क्रिप्ट को निष्पादित किया जाता है और इसका आउटपुट कमांड को खिलाया जाता है ":" (जो "सही" के बराबर है)

$ false
$ echo $?
1
$ : `false`
$ echo $?
0

संपादित करें: फिक्स्ड बदसूरत टाइपो


0

जबकि || true एक पसंद किया जाता है, लेकिन आप भी कर सकते हैं

var=$(echo $(exit 1)) # it shouldn't fail

0

यहां से मेरे लिए कोई समाधान काम नहीं किया, इसलिए मुझे एक और मिल गया:

set +e
find "./csharp/Platform.$REPOSITORY_NAME/obj" -type f -iname "*.cs" -delete
find "./csharp/Platform.$REPOSITORY_NAME.Tests/obj" -type f -iname "*.cs" -delete
set -e

यह CI & CD के लिए उपयोगी है। इस तरह से त्रुटि संदेश मुद्रित होते हैं लेकिन पूरी स्क्रिप्ट निष्पादित होती रहती है।


0
output=$(*command* 2>&1) && exit_status=$? || exit_status=$?
echo $output
echo $exit_status

लॉग फ़ाइल बनाने के लिए इसका उपयोग करने का उदाहरण

log_event(){
timestamp=$(date '+%D %T') #mm/dd/yy HH:MM:SS
echo -e "($timestamp) $event" >> "$log_file"
}

output=$(*command* 2>&1) && exit_status=$? || exit_status=$?

if [ "$exit_status" = 0 ]
    then
        event="$output"
        log_event
    else
        event="ERROR $output"
        log_event
fi

0

ऊपर से यहाँ सरल समाधान के लिए धन्यवाद:

<particular_script/command> || true

निम्नलिखित निर्माण का उपयोग अतिरिक्त कार्रवाई / स्क्रिप्ट चरणों की समस्या निवारण और अतिरिक्त प्रवाह नियंत्रण विकल्पों के लिए किया जा सकता है:

if <particular_script/command>
then
   echo "<particular_script/command> is fine!"
else
   echo "<particular_script/command> failed!"
   #exit 1
fi

हम आगे की कार्रवाई को रोक सकते हैं और exit 1यदि आवश्यक हो।

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