$ का उपयोग करने के लिए सबसे अच्छा अभ्यास? बाश में?


10

जब मैंने $ के बारे में यह उत्तर पढ़ा ? एक और सवाल दिमाग में आता है।

क्या $ का उपयोग करने के लिए कोई सर्वोत्तम अभ्यास है? बाश में?


चलो एक उदाहरण है:

हमारे पास एक रेखीय लिपि है और मैं यह जानना चाहूंगा कि सभी आदेश ठीक निष्पादित किए गए थे। क्या आपको लगता है कि एक छोटे से फ़ंक्शन को कॉल करना ठीक है (चलो इसे "did_it_work" कहते हैं), त्रुटि कोड की जांच करने और यदि ऐसा नहीं है तो तोड़ने के लिए।

#!/bin/bash 

function did_it_work {
    code=$1
    if [ "$code" -ne "0" ]
    then
        echo "Error failure: code $code "
        exit 1
    fi
}

dir=some/path

mkdir -p $dir
did_it_work $? 

cd $dir
did_it_work $? 

run_some_command
did_it_work $? 

निश्चित रूप से इस दृष्टिकोण का मतलब है कि मुझे इस समस्या को मैन्युअल रूप से हल करना होगा यदि कोई स्क्रिप्ट है और फिर से चलाएँ।

क्या आपको लगता है कि यह एक अच्छा विचार है या ऐसा करने के लिए कुछ अन्य सर्वोत्तम अभ्यास है?

/धन्यवाद

जवाबों:


15

एक सामान्य तरीका है:

die() {
    IFS=' ' # make sure "$*" is joined with spaces

    # output the arguments if any on stderr:
    [ "$#" -eq 0 ] || printf '%s\n' "$*" 1>&2
    exit 1
}

तो आप इसे इस तरह उपयोग करते हैं:

mkdir -p some/path || die "mkdir failed with status $?"

या यदि आप बाहर निकलने की स्थिति को शामिल करना चाहते हैं, तो आप इसे बदल सकते हैं:

die() {
    last_exit_status=$?
    IFS=' '
    printf '%s\n' "FATAL ERROR: $* (status $last_exit_status)" 1>&2
    exit 1
}

और फिर इसका उपयोग करना थोड़ा आसान है:

mkdir -p some/path || die "mkdir failed"

जब यह विफल हो जाता है, mkdirतो संभवतः पहले से ही एक त्रुटि संदेश जारी किया जाएगा, ताकि दूसरे को बेमानी के रूप में देखा जा सके, और आप बस कर सकते हैं:

mkdir -p some/path || exit   # with the same (failing) exit status as mkdir's
mkdir -p some/path || exit 1 # with exit status 1 always

(या dieतर्क के बिना ऊपर के पहले संस्करण का उपयोग करें )

बस अगर आपने पहले नहीं देखा है command1 || command2, तो यह चलता है command1, और यदि command1विफल रहता है, तो यह चलता है command2

तो आप इसे पढ़ सकते हैं जैसे "निर्देशिका बनाएं या मरें"।

आपका उदाहरण ऐसा दिखेगा:

mkdir -p some/path || die "mkdir failed"
cd some/path || die "cd failed"
some_command || die "some_command failed"

या आप diesदाईं ओर आगे संरेखित कर सकते हैं ताकि मुख्य कोड अधिक स्पष्ट हो।

mkdir -p some/path         || die "mkdir failed"
cd some/path               || die "cd failed"
some_command               || die "some_command failed"

या कमांड लाइन लंबी होने पर निम्न लाइन पर:

mkdir -p some/path ||
  die "mkdir failed"

cd some/path ||
  die "cd failed"

some_command ||
  die "some_command failed"

इसके अलावा, यदि आप some/pathकई बार नाम का उपयोग करने जा रहे हैं, तो इसे एक चर में संग्रहीत करें ताकि आपको इसे टाइप करना न पड़े, और यदि आवश्यक हो तो इसे आसानी से बदल सकते हैं। और जब आदेशों के लिए चर तर्कों को पास किया जाता है, तो --विकल्प सीमांकक का उपयोग करना सुनिश्चित करें ताकि तर्क को एक विकल्प के रूप में नहीं लिया जाए यदि इसके साथ शुरू होता है -

dir=some/path
mkdir -p -- "$dir"         || die "Cannot make $dir"
cd -P -- "$dir"            || die "Cannot cd to $dir"
some_command               || die "Cannot run some_command"

9

आप अपने कोड को इस तरह दोबारा लिख ​​सकते हैं:

#!/bin/bash
function try {
    "$@"
    code=$?
    if [ $code -ne 0 ]
    then
        echo "$1 did not work: exit status $code"
        exit 1
    fi
}

try mkdir -p some/path
try cd some/path
try run_some_command

यदि आपको वास्तव में त्रुटि कोड को लॉग इन करने की आवश्यकता नहीं है, लेकिन सिर्फ कमांड सफल हुआ या नहीं, तो आप इसे try()आगे भी छोटा कर सकते हैं :

function try {
    if ! "$@"
    then
        echo "$1 did not work"
        exit 1
    fi
}

आप इस प्रारूप में कोड का उपयोग भी कर सकते हैं। <प्री> फंक्शन ट्राई {
BillThor

आप इस कार्यक्षमता इनलाइन का उपयोग करें और सही की ओर से वापस जाने के लिए नहीं करना चाहते हैं आप की जगह ले सकता return $?के साथ :निर्मित।
बिलथोर

8

यदि आप वास्तव में exitएक त्रुटि पर चाहते हैं और बैश का उपयोग कर रहे हैं, तो आपको भी विचार करना चाहिए set -e। से help set:

-अगर एक गैर-शून्य स्थिति के साथ एक कमांड से बाहर निकलें तो तुरंत बाहर निकलें।

यह निश्चित रूप से आपको did_it_work () फ़ंक्शन का लचीलापन नहीं देता है, लेकिन यह सुनिश्चित करने का एक आसान तरीका है कि आपके नए फ़ंक्शन में बहुत सारी कॉल को जोड़े बिना आपकी बैश स्क्रिप्ट एक त्रुटि पर बंद हो जाती है।


set -eउपयोगी है। कुछ आदेश हैं जो सामान्य परिस्थितियों (उदाहरण के लिए diff) के तहत गैर-शून्य लौटते हैं । जब मैं एक स्क्रिप्ट में सेट-ई का उपयोग कर रहा हूं, जहां मुझे नॉनजरो रिटर्न की उम्मीद है, तो मैं करता हूं command || true
शॉन जे। गोफ

2
इसके अलावा, यहां तक ​​कि अगर आप उपयोग करते हैं set -e, तो आप सभी त्रुटियों को पकड़ने के लिए "अपवाद हैंडलर" सेट कर सकते हैं trap did_it_work EXIT
गिल्स एसओ- बुराई को रोकना '

1
यह POSIX का हिस्सा है, न कि एक विशिष्ट सुविधा। इसका उपयोग करें, लेकिन कुछ नुकसानों से अवगत रहें mywiki.wooledge.org/BashFAQ/105
kmkaplan

@ ShawnJ.Goff मुझे करना पसंद है command && true। जैसे कि रिटर्न वैल्यू नहीं बदली जाती।
किमीकप्लान

@kmkaplan आपकी अंतिम टिप्पणी से मुझे कोई मतलब नहीं है। यदि गैर-शून्य निकास कोड लौटाता है, तो स्क्रिप्ट से बाहर निकलने से command || trueरोकना उद्देश्य है । यह निकास कोड को बदल देता है क्योंकि हमें इसकी आवश्यकता होती है। केवल एक ही कार्य चलाया जाता है (यदि शून्य निकास कोड लौटाया जाता है) यदि `आदेश सफल हुआ (शून्य निकास कोड लौटाया गया) - यह एक पूर्ण नहीं-ऑप है। set -ecommandcommand && truetrue
ट्रिपल जू
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.