त्रुटि मिलने पर मैं बैश में लाइन नंबर कैसे खोजूं?


21

आपको बैश में लाइन नंबर कैसे मिलेगा जहां एक त्रुटि हुई?

उदाहरण

मैं यह बताने के लिए कि हम क्या चाहते हैं, यह बताने के लिए लाइन नंबरों के साथ निम्नलिखित सरल स्क्रिप्ट बनाते हैं। स्क्रिप्ट फ़ाइलों की प्रतिलिपि बनाएगी

cp $file1 $file2
cp $file3 $file4

जब cpकमांड में से एक विफल हो जाता है तो फ़ंक्शन 1 से बाहर निकल जाएगा । हम फ़ंक्शन की क्षमता को लाइन नंबर (उदाहरण के लिए, 8 या 12) के साथ त्रुटि को प्रिंट करना चाहते हैं।

क्या यह संभव है?

नमूना लिपि

1 #!/bin/bash
2
3
4 function in_case_fail {
5 [[ $1 -ne 0 ]] && echo "fail on $2" && exit 1
6 }
7
8 cp $file1 $file2
9 in_case_fail $? "cp $file1 $file2"
10
11
12 cp $file3 $file4
13 in_case_fail $? "cp $file3 $file4"
14


आप उपयोग कर सकते हैं set -xऔर / या set -vट्रेस करने के लिए क्या निष्पादित किया गया है। आपने जो मांगा था, ठीक वैसा नहीं, लेकिन यह शायद मददगार भी होगा।
रॉल्फ

जवाबों:


29

अपने फ़ंक्शन का उपयोग करने के बजाय, मैं इस पद्धति का उपयोग करूंगा:

$ cat yael.bash
#!/bin/bash

set -eE -o functrace

file1=f1
file2=f2
file3=f3
file4=f4

failure() {
  local lineno=$1
  local msg=$2
  echo "Failed at $lineno: $msg"
}
trap 'failure ${LINENO} "$BASH_COMMAND"' ERR

cp -- "$file1" "$file2"
cp -- "$file3" "$file4"

यह ईआरआर पर फंसकर काम करता है और फिर failure()फ़ंक्शन को मौजूदा लाइन नंबर + बैश कमांड के साथ कॉल करता है जिसे निष्पादित किया गया था।

उदाहरण

यहाँ मैं किसी भी देखभाल फ़ाइलें बनाने के लिए नहीं लिया है, f1, f2, f3, या f4। जब मैं उपरोक्त स्क्रिप्ट चलाता हूं:

$ ./yael.bash
cp: cannot stat f1’: No such file or directory
Failed at 17: cp -- "$file1" "$file2"

यह विफल रहता है, लाइन नंबर प्लस कमांड को निष्पादित किया गया था।


14

के अलावा LINENOवर्तमान पंक्ति संख्या वाले, देखते हैं BASH_LINENOऔर FUNCNAME(और BASH_SOURCE) सरणियों कि समारोह के नाम और लाइन नंबर वे से कहा जाता है होते हैं।

तो आप ऐसा कुछ कर सकते हैं:

#!/bin/bash

error() {
        printf "'%s' failed with exit code %d in function '%s' at line %d.\n" "${1-something}" "$?" "${FUNCNAME[1]}" "${BASH_LINENO[0]}"
}

foo() {
        ( exit   0 ) || error "this thing"
        ( exit 123 ) || error "that thing"
}

foo

चल रहा है कि प्रिंट होगा

'that thing' failed with exit code 123 in function 'foo' at line 9.

यदि आप उपयोग करते हैं set -e, या trap ... ERRस्वचालित रूप से त्रुटियों का पता लगाने के लिए, ध्यान दें कि उनके पास कुछ चेतावनी है। यह वर्णन करना भी कठिन है कि स्क्रिप्ट उस समय क्या कर रही थी (जैसा कि आपने अपने उदाहरण में किया था), हालांकि यह केवल पंक्ति संख्या की तुलना में एक नियमित उपयोगकर्ता के लिए अधिक उपयोगी हो सकता है।

set -eअन्य लोगों के साथ समस्याओं के लिए इन्हें देखें :


13

बैश में एक अंतर्निहित वैरिएबल है $LINENOजिसे स्टेटमेंट में वर्तमान लाइन नंबर द्वारा प्रतिस्थापित किया जाता है, इसलिए आप कर सकते हैं

in_case_fail $? "at $LINENO: cp $file1 $file2"

आप यह भी प्रयोग कर सकते हैं trap ... ERRकि कौन सी कमांड के विफल होने पर (यदि परिणाम का परीक्षण नहीं किया गया है)। उदाहरण के लिए:

trap 'rc=$?; echo "error code $rc at $LINENO"; exit $rc' ERR

फिर अगर cp $file1 $file2फेल जैसा कोई कमांड आपको लाइन नंबर और एग्जिट के साथ एरर मैसेज मिलेगा। आपको चर में त्रुटि में भी कमांड मिलेगी $BASH_COMMAND(हालांकि कोई पुनर्निर्देशन नहीं)।

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