2009-03-26 23 views
17

द्वारा निष्पादित निष्पादित प्रोग्रामों का ट्रेस एक स्क्रिप्ट गलत व्यवहार कर रहा है। मुझे यह जानने की जरूरत है कि कौन सी स्क्रिप्ट कॉल करता है, और कौन कॉलिंग स्क्रिप्ट को कॉल करता है, और इसी तरह, केवल गलत व्यवहार स्क्रिप्ट को संशोधित करके।बैश स्क्रिप्ट

यह एक स्टैक-ट्रेस के समान है, लेकिन मैं एक एकल बैश स्क्रिप्ट के भीतर फ़ंक्शन कॉल के कॉल स्टैक में दिलचस्पी रखने वाला हूं। इसके बजाय, मुझे मेरी स्क्रिप्ट द्वारा शुरू की गई निष्पादित प्रोग्राम/स्क्रिप्ट की श्रृंखला की आवश्यकता है।

उत्तर

6

के बाद से आप कहते हैं कि आप स्क्रिप्ट ही संपादित कर सकते हैं, बस एक डाल:

ps -ef >/tmp/bash_stack_trace.$$ 
उस में

, जहां समस्या उत्पन्न हो रही है।

इससे आपकी tmp निर्देशिका में कई फ़ाइलें बनाई जाएंगी जो उस समय पूरी प्रक्रिया सूची दिखाती हैं।

फिर आप इस आउटपुट की जांच करके कौन सी प्रक्रिया को बुला सकते हैं, इस प्रक्रिया को आप कर सकते हैं। यह या तो मैन्युअल रूप से किया जा सकता है, या awk की तरह कुछ के साथ स्वचालित है, क्योंकि उत्पादन नियमित रूप से है -। तुम सिर्फ सभी प्रक्रियाओं में आपकी रुचि है के बीच संबंधों को बाहर काम करने के लिए उन PID और PPID स्तंभों का उपयोग

आप करेंगे फ़ाइलों पर नजर रखने की आवश्यकता है, क्योंकि आपको प्रति प्रक्रिया एक मिल जाएगी ताकि उन्हें प्रबंधित किया जा सके। चूंकि यह ऐसा कुछ है जो केवल डीबगिंग के दौरान किया जाना चाहिए, अधिकांश समय उस पंक्ति पर टिप्पणी की जाएगी (# से पहले), इसलिए फाइलें नहीं बनाई जाएंगी।

उन्हें साफ करने के लिए, आप बस कर सकते हैं:

rm /tmp/bash_stack_trace.* 
+0

हालांकि एक स्टैक ट्रेस नहीं है यही कारण है कि: http://wiki.bash-hackers.org/commands/builtin/caller

i=0; while caller $i ;do ((i++)) ;done 

यह करने के लिए एक और तरीका है PS4 बदल सकते हैं और xtrace सक्षम बनाना है। सबसे अच्छा यह एक निष्पादन निशान होगा। लेकिन उस pstree -pal या ps -ef --forest के लिए बेहतर अनुकूल होगा।
यह फ़ंक्शन कॉल * स्टैक * नहीं दिखाता है, और न ही यह वर्तमान कोड फ़ाइल और रेखा दिखाता है। जो आमतौर पर एक स्टैक ट्रेस का पूरा बिंदु होता है। – Evi1M4chine

+0

हां लेकिन ओपी ने कहा कि वे केवल यह जानना चाहते थे कि कौन सी स्क्रिप्ट्स स्क्रिप्ट को कॉल करती हैं, इसलिए स्क्रिप्ट के भीतर की रेखाओं के बारे में विस्तार आवश्यक नहीं है। एक बार जब आप exec-stack को जानते हैं, तो आप अधिक सुगंधित ट्रेस के लिए व्यक्तिगत स्क्रिप्ट में 'set -x' जैसे डीबग कथन जोड़ना शुरू कर सकते हैं। – paxdiablo

+0

मैं इस सवाल का जवाब नहीं मानता, कम से कम स्टैक ट्रेस की सामान्य समझ में नहीं। – akostadinov

0

जोड़ने pstree -p -u ` Whoami ` >> अपनी स्क्रिप्ट में उत्पादन शायद आप जानकारी की आवश्यकता मिल जाएगा।

6
~$ help caller 
caller: caller [EXPR] 
    Returns the context of the current subroutine call. 

    Without EXPR, returns "$line $filename". With EXPR, 
    returns "$line $subroutine $filename"; this extra information 
    can be used to provide a stack trace. 

    The value of EXPR indicates how many call frames to go back before the 
    current one; the top frame is frame 0. 
+1

हालांकि और '-x' उपयोगी हैं, ऐसा लगता है कि यह ओपी की मदद नहीं करेगा, क्योंकि यह केवल उसी स्क्रिप्ट के भीतर फ़ंक्शन कॉल पर काम करता है। – ephemient

+0

ऊपर मिरसे Vutcovici जवाब देखें। यह वही है जो मुझे चाहिए: i = 0; जबकि कॉलर $ i; do ((i ++)); –

14

एक साधारण स्क्रिप्ट मैं कुछ दिन पहले लिखा था कुछ की कोशिश कर सकते ...

# FILE  : sctrace.sh 
# LICENSE : GPL v2.0 (only) 
# PURPOSE : print the recursive callers' list for a script 
#    (sort of a process backtrace) 
# USAGE  : [in a script] source sctrace.sh 
# 
# TESTED ON : 
# - Linux, x86 32-bit, Bash 3.2.39(1)-release 

# REFERENCES: 
# [1]: http://tldp.org/LDP/abs/html/internalvariables.html#PROCCID 
# [2]: http://linux.die.net/man/5/proc 
# [3]: http://linux.about.com/library/cmd/blcmdl1_tac.htm 

#! /bin/bash 

TRACE="" 
CP=$$ # PID of the script itself [1] 

while true # safe because "all starts with init..." 
do 
     CMDLINE=$(cat /proc/$CP/cmdline) 
     PP=$(grep PPid /proc/$CP/status | awk '{ print $2; }') # [2] 
     TRACE="$TRACE [$CP]:$CMDLINE\n" 
     if [ "$CP" == "1" ]; then # we reach 'init' [PID 1] => backtrace end 
       break 
     fi 
     CP=$PP 
done 
echo "Backtrace of '$0'" 
echo -en "$TRACE" | tac | grep -n ":" # using tac to "print in reverse" [3] 

... और एक साधारण परीक्षण।

test

मैं आप इसे पसंद उम्मीद है।

+0

किया गया यह मैक ओएस एक्स पर काम नहीं करता है .((ऐसा नहीं है कि आपने दावा किया है, लेकिन केवल उन लोगों के लिए जो मैक समाधान की तलाश में हैं, ऐसा नहीं है। जबकि फोन करने वाले $ i मुझे क्या : –

+2

हाँ, यह लिनक्स सुविधाएं (सवाल सभी के बाद, लिनक्स के बारे में था) का उपयोग करता है, खेद ... –

+2

यह ऊपर जा रहा है क्या मैक ओएस एक्स (और Linux) पर मेरे लिए काम किया समाप्त हो गया = $ ((i + 1)) किया –

2

अद्यतन: नीचे दिया गया कोड काम करना चाहिए। अब मुझे पता चला है कि मेरे पास newer answer है जो एक नए कोड संस्करण के साथ है जो स्टैकट्रैक में एक संदेश डालने की अनुमति देता है।

आईआईआरसी मुझे इस समय अद्यतन करने के लिए यह उत्तर नहीं मिला। लेकिन अब तय किया गया है कि गिट में कोड बेहतर रखा गया है, इसलिए उपरोक्त का नवीनतम संस्करण इस gist में होना चाहिए।

मूल कोड-को सही जवाब नीचे:

इस कहीं के बारे में एक और उत्तर लेकिन था यहाँ जावा प्रोग्रामिंग भाषा में उदाहरण के लिए प्रयुक्त अर्थ में स्टैक ट्रेस प्राप्त करने के लिए उपयोग करने के लिए एक समारोह है। आप फ़ंक्शन को कॉल करते हैं और यह स्टैक ट्रेस को वैरिएबल $ STACK में डालता है। यह कोड बिंदु दिखाता है जो get_stack को बुलाया जाता है। यह जटिल निष्पादन के लिए अधिकतर उपयोगी होता है जहां एकल खोल एकाधिक स्क्रिप्ट स्निपेट और घोंसले स्रोत करता है।

function get_stack() { 
    STACK="" 
    # to avoid noise we start with 1 to skip get_stack caller 
    local i 
    local stack_size=${#FUNCNAME[@]} 
    for ((i=1; i<$stack_size ; i++)); do 
     local func="${FUNCNAME[$i]}" 
     [ x$func = x ] && func=MAIN 
     local linen="${BASH_LINENO[((i - 1))]}" 
     local src="${BASH_SOURCE[$i]}" 
     [ x"$src" = x ] && src=non_file_source 

     STACK+=$'\n'" "$func" "$src" "$linen 
    done 
} 
+0

प्रारंभ करने के लिए कोड का उपयोगी बिट, लेकिन इसमें बग हैं। जैसे $ {# FUNCNAME [1]} पहले फ़ंक्शन नाम की लंबाई है जो FUNCNAME सरणी में प्रविष्टियों की संख्या नहीं है, और लिनेनो के लिए "i - 1" गलत लगता है। – Eric

+0

@Eric, धन्यवाद, मुझे अपने उत्पादन संस्करण में कुछ ट्यून-अप करना याद है जो मुझे अब नहीं मिल सकता क्योंकि मैंने बहुत समय पहले इस चीज़ का उपयोग करना बंद कर दिया था। और दुर्भाग्यवश यहां कोड अपडेट करने के लिए चूक गए। मैंने 'stack_size' तय किया। LINENO एक साधारण स्थानीय परीक्षण से मुझे सही दिखता है, मुझे बताएं कि यह आपके लिए काम नहीं करता है। मुझे फ़ाइल से स्क्रिप्ट चलाने पर इंटरैक्टिव शैल से कुछ फ़ंक्शन कॉल करते समय 'stack_size' के साथ एक अंतर भी याद है। मुझे लगता है कि इसे ऑटो-अनुमान लगाया जा सकता है लेकिन अभी इसके साथ खेलने का कोई समय नहीं है। यानी इंटरैक्टिव में, आपको 'stack_size + 1' की आवश्यकता है। – akostadinov

+0

@Eric, धन्यवाद और मैं अंततः इस विषय पर अपने दो उत्तरों को जोड़ सकता हूं। ऊपर अद्यतन देखें। गिस्ट पर सहयोग करने के लिए आपका स्वागत है। मुझे लगता है कि जब हमें 'stack_size' या 'stack_size + 1' पर रुकने की आवश्यकता होती है तो एक सुधार स्वचालित रूप से होगा। – akostadinov

6

आप बैश डीबगर http://bashdb.sourceforge.net/

उपयोग कर सकते हैं या, जैसा कि पिछले टिप्पणी में उल्लेख किया है, caller बैश में निर्मित। देखें:

PS4='+$(date "+%F %T") ${FUNCNAME[0]}() $BASH_SOURCE:${BASH_LINENO[0]}+ ' 
set -o xtrace # Comment this line to disable tracing. 
+2

मुझे विशेष रूप से यह पसंद है: i = 0; जबकि कॉलर $ i; करें ((i ++)); –

+0

किया गया सबसे अच्छा जवाब! –

संबंधित मुद्दे