कैसे एक बैश स्क्रिप्ट डिबग करने के लिए? [बन्द है]


159

क्या बैश स्क्रिप्ट को डीबग करने का कोई तरीका है? जैसे कुछ ऐसा जो एक तरह के निष्पादन लॉग को प्रिंट करता है जैसे "कॉलिंग लाइन 1", "कॉलिंग लाइन 2" आदि।



जवाबों:


195
sh -x script [arg1 ...]
bash -x script [arg1 ...]

ये आपको अंजाम दे रहे हैं जो निष्पादित किया जा रहा है। (उत्तर के निचले भाग के पास 'स्पष्टीकरण' भी देखें।)

कभी-कभी, आपको स्क्रिप्ट के भीतर डिबगिंग को नियंत्रित करने की आवश्यकता होती है। उस स्थिति में, जैसा कि चेतो ने मुझे याद दिलाया , आप उपयोग कर सकते हैं:

set -x

इससे डिबगिंग चालू हो जाती है। आप इसे फिर से बंद कर सकते हैं:

set +x

(आप $-मौजूदा झंडे की स्थिति का विश्लेषण करके पता लगा सकते हैं , वर्तमान झंडे, के लिए x)

इसके अलावा, गोले आम तौर पर -n'कोई निष्पादन नहीं' और -v'क्रिया' मोड के लिए विकल्प प्रदान करते हैं ; आप यह देखने के लिए संयोजन में इनका उपयोग कर सकते हैं कि क्या शेल को लगता है कि यह आपकी स्क्रिप्ट को निष्पादित कर सकता है - कभी-कभी उपयोगी यदि आपके पास एक असंतुलित उद्धरण है


इस बात पर विवाद है कि -xबाश में ' ' विकल्प अन्य गोले (टिप्पणियों को देखें) से अलग है। बैश मैनुअल का कहना है:

  • -एक्स

    साधारण कमांड्स, forकमांड्स, caseकमांड्स, selectकमांड्स और अरिथमेटिक forकमांड्स और उनके तर्कों या संबंधित शब्द सूचियों को उनके विस्तारित होने के बाद और उनके निष्पादित होने से पहले प्रिंट करें । PS4चर के मूल्य का विस्तार किया जाता है और परिणामी मूल्य को कमांड और उसके विस्तारित तर्कों से पहले प्रिंट किया जाता है।

यह बहुत अलग व्यवहार को इंगित नहीं करता है। मैं -xमैनुअल में ' ' के लिए कोई अन्य प्रासंगिक संदर्भ नहीं देखता हूं । यह स्टार्टअप अनुक्रम में अंतर का वर्णन नहीं करता है।

क्लेरिफिकेशन : एक विशिष्ट लिनक्स बॉक्स जैसे सिस्टम पर, जहां '' /bin/sh'एक सिमलिंक है' /bin/bash'(या जहां भी बैश निष्पादन योग्य पाया जाता है), दो कमांड लाइन निष्पादन ट्रेस के साथ स्क्रिप्ट को चलाने के बराबर प्रभाव को प्राप्त करते हैं। अन्य प्रणालियों पर (उदाहरण के लिए, सोलारिस और लिनक्स के कुछ और आधुनिक संस्करण), /bin/shबैश नहीं है, और दो कमांड लाइन अलग-अलग परिणाम देंगे। सबसे विशेष रूप से, ' /bin/sh' बैश में निर्माणों से भ्रमित होगा कि यह बिल्कुल भी नहीं पहचानता है। (सोलारिस पर, /bin/shएक बॉर्न शेल है, आधुनिक लिनक्स पर, यह कभी-कभी डैश होता है - एक छोटा, अधिक कड़ाई से पीओएस-ओनली शेल।) जब इस तरह के नाम से आह्वान किया जाता है, तो 'शेबंग' लाइन (' #!/bin/bash' बनाम '#!/bin/sh'')

बैश मैनुअल में बैश पोसिक्स मोड पर एक सेक्शन है , जो इस उत्तर के लंबे समय तक लेकिन गलत संस्करण के विपरीत है (नीचे टिप्पणी भी देखें), विस्तृत विवरण में 'बैश इनवॉल्ड sh' और 'बैश इनवॉक्ड' के बीच के अंतर का वर्णन करता है। bash'।

जब (बश) शेल स्क्रिप्ट को डीबग करना, यह समझदार और समझदार होगा - आवश्यक भी - -xविकल्प के साथ शेलबैंग लाइन में नामित शेल का उपयोग करने के लिए । अन्यथा, आप (विल?) स्क्रिप्ट चलाते समय डिबगिंग करते समय अलग व्यवहार प्राप्त कर सकते हैं।


1
उन्होंने एक bashस्क्रिप्ट निर्दिष्ट की । और इसके साथ बैश स्क्रिप्ट चलाने से sh -xयह पूरी तरह से अलग व्यवहार करेगा! कृपया अपना उत्तर अपडेट करें।
लहुनाथ

1
@ ललनाथ: किस तरह से 'श-एक्स' (या 'बैश-एक्स') स्क्रिप्ट को पूरी तरह से अलग व्यवहार करता है? जाहिर है, यह स्ट्रेडर को जानकारी ट्रेस करता है; यह एक दिया (हालांकि मेरे जवाब में उल्लेख नहीं किया गया है)। लेकिन और क्या? मैं लिनक्स और मैकओएस एक्स पर 'बा' के रूप में 'बैश' का उपयोग करता हूं और एक गंभीर मुद्दे पर ध्यान नहीं दिया है।
जोनाथन लेफ़लर

6
स्टार्टअप में और रनटाइम में अंतर हैं। वे बैश वितरण में पूरी तरह से प्रलेखित हैं।
बोनसाई

4
यहाँ bash doc का लिंक दिया गया है: gnu.org/software/bash/manual/bashref.html#Bash-Startup-Files 'अगर बैश को नाम श के साथ लगाया जाता है, तो यह श के ऐतिहासिक संस्करणों के स्टार्टअप व्यवहार की नकल करने की कोशिश करता है। संभव के रूप में निकटता के रूप में अच्छी तरह से, संभव के रूप में बारीकी से '
thethinman

6
और अधिक उपयोगी जानकारी देने के लिए PS4 प्रॉम्प्ट का उपयोग करें जैसे:export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
estani

28

मैंने अपनी स्क्रिप्ट को डीबग करने के लिए निम्न विधियों का उपयोग किया है।

set -eयदि कोई बाहरी कार्यक्रम एक गैर-शून्य निकास स्थिति देता है, तो स्क्रिप्ट को तुरंत रोक देता है। यह उपयोगी है यदि आपकी स्क्रिप्ट सभी त्रुटि मामलों को संभालने का प्रयास करती है और जहां ऐसा करने में विफलता फंस गई है।

set -x ऊपर उल्लेख किया गया था और निश्चित रूप से सभी डिबगिंग विधियों में सबसे उपयोगी है।

set -n यदि आप सिंटैक्स त्रुटियों के लिए अपनी स्क्रिप्ट की जांच करना चाहते हैं तो यह उपयोगी हो सकता है।

straceयह देखने के लिए भी उपयोगी है कि क्या हो रहा है। विशेष रूप से उपयोगी है यदि आपने स्वयं स्क्रिप्ट नहीं लिखी है।


1
किसी स्क्रिप्ट को स्ट्रेंथ करना (यानी स्क्रिप्ट को निष्पादित करने वाली शेल को स्ट्रेच करना) एक अजीब शेल डिबगिंग विधि है (लेकिन सीमित मुद्दों के लिए काम कर सकती है)।
बोनसाई

1
मैं मानता हूं कि यह अजीब है और बहुत ही क्रियात्मक भी है, लेकिन यदि आप स्ट्रेस के आउटपुट को कुछ सिस्कॉल तक सीमित करते हैं, तो यह उपयोगी हो जाता है।

1
ध्यान दें कि strace -fयदि आप स्क्रिप्ट द्वारा शुरू की गई प्रक्रियाओं में त्रुटियों को ढूंढना चाहते हैं, तो इसकी आवश्यकता है। (जो इसे कई गुना अधिक क्रियात्मक बनाता है, लेकिन फिर भी उपयोगी है यदि आप इसे उन सीस्कॉल तक सीमित करते हैं जो आप रुचि रखते हैं)।
रैंडम 832


12

यह उत्तर मान्य और उपयोगी है: https://stackoverflow.com/a/951352

लेकिन, मुझे लगता है कि "मानक" स्क्रिप्ट डीबगिंग विधियाँ अक्षम, अचूक, और उपयोग करने में कठिन हैं। उन लोगों के लिए जो परिष्कृत GUI डीबगर्स का उपयोग करते थे, जो आपकी उंगलियों पर सब कुछ डालते हैं और काम को आसान समस्याओं (और कठिन समस्याओं के लिए संभव) के लिए एक हवा बनाते हैं, ये समाधान बहुत संतोषजनक नहीं हैं।

मैं जो भी करता हूं वह DDD और bashdb के संयोजन का उपयोग करता है। पूर्व अपने उत्तरार्द्ध को निष्पादित करता है, और उत्तरार्द्ध आपकी स्क्रिप्ट को निष्पादित करता है। यह आपके सिर में संदर्भ बनाए रखने या स्रोत को फिर से सूचीबद्ध करने के लिए निरंतर मानसिक प्रयास के बिना, संदर्भ में कोड के माध्यम से कदम रखने और चर, स्टैक आदि को देखने के लिए एक बहु-खिड़की यूआई प्रदान करता है।

यहाँ स्थापित करने पर मार्गदर्शन है: http://ubuntuforums.org/showthread.php?t=660223


बस अपने जवाब के लिए धन्यवाद ddd की खोज की। Ubuntu 12.04.3 (64 बिट) में, उपयुक्त-स्रोत संस्करण काम नहीं करता है। मुझे अपनी बैश स्क्रिप्ट को डीबग करना शुरू करने के लिए स्रोत से संकलित और संस्थापित करना पड़ा। यहाँ निर्देश - askubuntu.com/questions/156906/… ने मदद की।
क्रोनोडेकर

हाँ, यह एक समस्या है। मैंने इसे कुछ समय पहले कुछ स्क्रिप्टिंग के साथ हल किया था - 'dddbash' डीडीडी को स्थापित / बनाता है, पुराने संस्करण को हटा देता है यदि इसके गलत, इंस्टॉलेशन बैशब, आदि (उत्तर को इस जानकारी के साथ अब संपादित किया गया है)
Stabledog '26


10

मुझे शेलचेक उपयोगिता मिली और कुछ लोगों को यह दिलचस्प लग सकता है https://github.com/koalaman/shellcheck

एक छोटा सा उदाहरण:

$ cat test.sh 
ARRAY=("hello there" world)

for x in $ARRAY; do
  echo $x
done

$ shellcheck test.sh 

In test.sh line 3:
for x in $ARRAY; do
         ^-- SC2128: Expanding an array without an index only gives the first element.

बग को ठीक करें, पहले प्रयास करें ...

$ cat test.sh       
ARRAY=("hello there" world)

for x in ${ARRAY[@]}; do
  echo $x
done

$ shellcheck test.sh

In test.sh line 3:
for x in ${ARRAY[@]}; do
         ^-- SC2068: Double quote array expansions, otherwise they're like $* and break on spaces.

चलो फिर से कोशिश करें...

$ cat test.sh 
ARRAY=("hello there" world)

for x in "${ARRAY[@]}"; do
  echo $x
done

$ shellcheck test.sh

अभी खोजे!

यह सिर्फ एक छोटा सा उदाहरण है।



सौभाग्य से यह उपकरण उस बिंदु पर विकसित हुआ है जहाँ यह शेष बग को भी खोजता है।
ट्रिपल

3

VSCode स्थापित करें , फिर बैश डीबग एक्सटेंशन जोड़ें और आप दृश्य मोड में डीबग करने के लिए तैयार हैं। यहाँ देखें कार्रवाई में।

यहां छवि विवरण दर्ज करें


3

प्लग किए गए और बेसहेस के साथ ग्रहण का उपयोग करें।

https://sourceforge.net/projects/shelled/?ource=directory https://sourceforge.net/projects/basheclipse/?source=directory

शेल्ड के लिए: ज़िप डाउनलोड करें और इसे सहायता के माध्यम से ग्रहण में आयात करें -> नया सॉफ़्टवेयर स्थापित करें: स्थानीय संग्रह के लिए आधारभूत: जार को ड्रॉप्सीन की निर्देशिका में कॉपी करें

चरणों का पालन करें https://sourceforge.net/projects/basheclipse/files/?source=navbar

यहां छवि विवरण दर्ज करें

मैंने http://dietrichschroff.blogspot.de/2017/07/bash-en enable-eclipse-for-bash.html पर कई स्क्रीनशॉट के साथ एक ट्यूटोरियल लिखा है


2
यह एक बॉर्डरलाइन लिंक-ओनली उत्तर है ( यहां भी देखें )। आपको यथासंभव अधिक से अधिक जानकारी शामिल करने के लिए अपने उत्तर का विस्तार करना चाहिए, कम से कम न्यूनतम आवश्यकता वास्तव में जो आप सुझाव दे रहे हैं उसे पूरा करने के लिए, और केवल संदर्भ के लिए लिंक का उपयोग करें। मूल रूप से, स्टैक ओवरफ्लो (और स्टैक एक्सचेंज के सभी) पर पोस्ट स्व-निहित होना चाहिए। इसका अर्थ है कि आपके उत्तर में पर्याप्त जानकारी का होना आवश्यक है ताकि पाठक को निर्देश के लिए ऑफ-साइट जाने की आवश्यकता न हो। अभी, इस उत्तर के लिए ऐसा नहीं है।
Makyen

यह पहला उत्तर है जो मैंने कई को देखने के बाद पाया है जो वास्तव में दिखाता है कि सच्ची डिबगिंग संभव है। मानक उत्तर "सेट + एक्स" पूरी तरह से एक स्व-निहित उत्तर से मेल खाते हैं, लेकिन सच्चे डिबगिंग के बारे में सही प्रश्नों की उपेक्षा करेंगे। मैं इस उत्तर की सराहना करता हूं
bo

2

मैंने एक बैश डीबगर बनाया। इसे मात्र आजमाएं। मुझे उम्मीद है कि यह https://sourceforge.net/projects/bashdebugingbash मदद करेगा


BDB वर्तमान में अंग्रेजी और स्पेनिश भाषाओं में समर्थित है। भाषा बदलने के लिए, फाइल / etc / default / bdb
abadjm

स्क्रीनशॉट दिलचस्प लग रहा है, लेकिन मैं इसे "bdb.sh: लाइन 32: bdbSTR [1]: अन-वेरिएबल" नहीं चला सका; btw यह सभी सेट चर के वर्तमान मूल्यों को दिखाएगा जो हम कोड पर प्रत्येक चरण करते हैं?
कुंभ राशि

2

set + x = @ECHO OFF, सेट -x = @ECHO ON।


आप -xvनिम्न प्रकार से मानक शेबंग में विकल्प जोड़ सकते हैं :

#!/bin/bash -xv  

-x: प्रदर्शन कमांड और उनके तर्क जैसे ही वे निष्पादित होते हैं।
-v: शेल इनपुट लाइनें प्रदर्शित करें क्योंकि वे पढ़े जाते हैं।


ltraceके समान एक और लिनक्स उपयोगिता है strace। हालाँकि, ltraceसभी लाइब्रेरी कॉल को एक निष्पादन योग्य या चलने वाली प्रक्रिया में सूचीबद्ध करता है। इसका नाम खुद लाइब्रेरी-कॉल ट्रेसिंग से आता है। उदाहरण के लिए:

ltrace ./executable <parameters>  
ltrace -p <PID>  

स्रोत


1

मुझे लगता है कि आप इस बैश डीबगर को आज़मा सकते हैं: http://bashdb.sourceforge.net/


शेल के वैश्विक वैरिएबल के माध्यम से शेल स्क्रिप्ट के लिए लॉगिंग पर विस्तार की अच्छी मात्रा है। हम शेल स्क्रिप्ट में इसी तरह की लॉगिंग का अनुकरण कर सकते हैं: cubicrace.com/2016/03/efficient-log-mechnism-in-shell.html
पीयूष

1

डिबग करने के लिए कुछ ट्रिक स्क्रिप्ट:

का उपयोग करते हुए set -[nvx]

के अतिरिक्त

set -x

तथा

set +x

डंप को रोकने के लिए।

मैं set -vविच डंप के बारे में कम विकसित आउटपुट के रूप में बोलना चाहूंगा ।

bash <<<$'set -x\nfor i in {0..9};do\n\techo $i\n\tdone\nset +x' 2>&1 >/dev/null|wc -l
21

for arg in x v n nx nv nvx;do echo "- opts: $arg"
    bash 2> >(wc -l|sed s/^/stderr:/) > >(wc -l|sed s/^/stdout:/) <<eof
        set -$arg
        for i in {0..9};do
            echo $i
          done
        set +$arg
        echo Done.
eof
    sleep .02
  done
- opts: x
stdout:11
stderr:21
- opts: v
stdout:11
stderr:4
- opts: n
stdout:0
stderr:0
- opts: nx
stdout:0
stderr:0
- opts: nv
stdout:0
stderr:5
- opts: nvx
stdout:0
stderr:5

मक्खी पर डंप चर या अनुरेखण

कुछ चर का परीक्षण करने के लिए, मैं कुछ समय का उपयोग करता हूं:

bash <(sed '18ideclare >&2 -p var1 var2' myscript.sh) args

जोड़ने के लिए:

declare >&2 -p var1 var2

पंक्ति 18 पर और परिणामी स्क्रिप्ट ( आर्ग्स के साथ ) चल रही है, उन्हें संपादित किए बिना।

बेशक, इसे जोड़ने के लिए इस्तेमाल किया जा सकता है set [+-][nvx]:

bash <(sed '18s/$/\ndeclare -p v1 v2 >\&2/;22s/^/set -x\n/;26s/^/set +x\n/' myscript) args

declare -p v1 v2 >&2लाइन 18 के बाद, set -xलाइन 22 set +xसे पहले और लाइन 26 से पहले जोड़ देगा ।

थोड़ा नमूना:

bash <(sed '2,3s/$/\ndeclare -p LINENO i v2 >\&2/;5s/^/set -x\n/;7s/^/set +x\n/' <(
        seq -f 'echo $@, $((i=%g))' 1 8)) arg1 arg2
arg1 arg2, 1
arg1 arg2, 2
declare -i LINENO="3"
declare -- i="2"
/dev/fd/63: line 3: declare: v2: not found
arg1 arg2, 3
declare -i LINENO="5"
declare -- i="3"
/dev/fd/63: line 5: declare: v2: not found
arg1 arg2, 4
+ echo arg1 arg2, 5
arg1 arg2, 5
+ echo arg1 arg2, 6
arg1 arg2, 6
+ set +x
arg1 arg2, 7
arg1 arg2, 8

नोट: देखभाल के बारे में मक्खी संशोधनों से $LINENOप्रभावित होगा !

(परिणामी स्क्रिप्ट को देखने के लिए, केवल ड्रॉप करना bash <(और ) arg1 arg2)

कदम से कदम, निष्पादन समय

बैश स्क्रिप्ट को कैसे प्रोफाइल करें, इस बारे में मेरे जवाब पर एक नज़र डालें


0

शेल के वैश्विक वैरिएबल के माध्यम से शेल स्क्रिप्ट के लिए लॉगिंग पर विस्तार की अच्छी मात्रा है। हम शेल स्क्रिप्ट में इसी तरह की लॉगिंग का अनुकरण कर सकते हैं: http://www.cubicrace.com/2016/03/log-tracing-mechnism-for-shell-scripts.html

इस पोस्ट में INFO, DEBUG, ERROR जैसे लॉग स्तरों के परिचय पर विवरण है। स्क्रिप्ट प्रविष्टि, स्क्रिप्ट निकास, फ़ंक्शन प्रविष्टि, फ़ंक्शन निकास जैसे अनुरेखण विवरण।

नमूना लॉग:

यहां छवि विवरण दर्ज करें

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