स्क्रिप्ट के बाहर से बैश निष्पादन ट्रेस (सेट -x) को दबाएं


17

मैंने इस प्रश्न का उत्तर खोजने की कोशिश की, लेकिन अब तक कोई भाग्य नहीं मिला:

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

इसलिए मैं बस नहीं लिख सकता ./script 2>/dev/null

इसके अलावा, मेरे पास उन अन्य लिपियों को संपादित करने के लिए विशेषाधिकार नहीं हैं, इसलिए मैं सेट विकल्प को मैन्युअल रूप से नहीं बदल सकता।

मैं stderr से अलग फ़ाइल में सब कुछ लॉग करने और ट्रेसिंग कमांड्स को फ़िल्टर करने के बारे में सोच रहा था, लेकिन शायद एक सरल तरीका है?


1
./script 2>some_file
सातु कटुरा

जवाबों:


25

साथ bash4.1 और उसके बाद, आप कर सकते हैं

BASH_XTRACEFD=7 ./script.bash 7> /dev/null

(यह भी काम करता है जब के bashरूप में लागू किया जाता है sh)।

असल में, हम आउटपुट को फाइल डिस्क्रिप्टर 7 के बजाय 2 के डिफॉल्ट पर bashआउटपुट करने के लिए कह रहे हैं xtrace, और उस फाइल डिस्क्रिप्टर को रीडायरेक्ट करते हैं /dev/null। एफडी संख्या मनमानी है। 2 से ऊपर एक fd का उपयोग करें जो अन्यथा आपकी स्क्रिप्ट में उपयोग नहीं किया गया है। यदि आप जिस शेल में इस कमांड में प्रवेश कर रहे हैं वह है bashया yash, आप 9 से ऊपर की संख्या का उपयोग भी कर सकते हैं (हालांकि यदि आप फ़ाइल डिस्क्रिप्टर शेल द्वारा आंतरिक रूप से उपयोग किया जाता है तो आप समस्याओं में चल सकते हैं)।

यदि आप उस bashस्क्रिप्ट को कॉल कर रहे हैं zsh, तो आप यह भी कर सकते हैं:

(export BASH_XTRACEFD; ./script.bash {BASH_XTRACEFD}> /dev/null)

चर के लिए स्वचालित रूप से 9 से ऊपर पहले मुफ्त एफडी सौंपा जाना चाहिए।

के पुराने संस्करणों के लिए bash, एक और विकल्प है, अगर xtraceसाथ चालू है set -x(के रूप में करने का विरोध किया #! /bin/bash -xया set -o xtrace) को फिर से परिभाषित करने के लिए किया जाएगा setएक निर्यात समारोह जब से पारित कर दिया है कि कुछ नहीं करता है के रूप में -x(अगर यह (या किसी अन्य यद्यपि कि स्क्रिप्ट टूट जाएगा bashस्क्रिप्ट यह आह्वान) setस्थितीय मापदंडों को निर्धारित करने के लिए उपयोग किया जाता है)।

पसंद:

set()
  case $1 in
    (-x) return 0;;
    (-[!-]|"") builtin set "$@";;
    (*) echo >&2 That was a bad idea, try something else; builtin set "$@";;
  esac

export -f set
./script.bash

एक अन्य विकल्प एक $BASH_ENVफ़ाइल में एक डीबग जाल जोड़ने के लिए है जो set +xहर कमांड से पहले होता है ।

echo 'trap "{ set +x; } 2>/dev/null" DEBUG' > ~/.no-xtrace
BASH_ENV=~/.no-xtrace ./script.bash

जब set -xउप-शेल में किया जाता है तो वह काम नहीं करेगा ।

जैसा कि @ilkkachu ने कहा, बशर्ते कि आपने फ़ाइल सिस्टम पर किसी भी फ़ोल्डर को लिखने की अनुमति दी है, आपको कम से कम स्क्रिप्ट की एक प्रतिलिपि बनाने और इसे संपादित करने में सक्षम होना चाहिए।

यदि कहीं भी आप स्क्रिप्ट की एक प्रति लिख सकते हैं, या यदि हर बार नई कॉपी बनाने और संपादित करने के लिए यह सुविधाजनक नहीं है, तो मूल स्क्रिप्ट के लिए एक अपडेट है, आप अभी भी कर सकते हैं:

 bash <(sed 's/set -x/set +x/g' ./script.bash)

वह (और कॉपी एप्रोच) ठीक से काम नहीं कर सकता है अगर स्क्रिप्ट कुछ भी $0या विशेष चर के साथ कल्पना करती है जैसे $BASH_SOURCE(जैसे कि वे फाइलें जो स्वयं स्क्रिप्ट के स्थान के सापेक्ष हैं), इसलिए आपको कुछ और संपादन करने की आवश्यकता हो सकती है जैसे $0स्क्रिप्ट के रास्ते से बदलें ...


आपका पहला जवाब वही है जो मुझे चाहिए था, स्वच्छ और सुरुचिपूर्ण। क्या आप थोड़ा समझा सकते हैं कि यह कैसे काम करता है? क्यों नंबर 7? अन्य नंबरों का उपयोग किस लिए किया जा सकता है? धन्यवाद।
मानव

@ हनुमान, देखें संपादित करें
स्टीफन चेज़लस

1
{BASH_XTRACEFD}>चाल में काम करता है bash4.1 या बाद के साथ-साथ।
चेपनर

@chepner, हाँ इस फीचर को zsh, ksh93 और bash में एक zsh डेवलपर के सुझाव पर एक ही समय में जोड़ा गया था। लेकिन, यहां यह नहीं काम करने के लिए करता है ksh93या bashमें है कि चर आदेश (तुलना के वातावरण में नहीं पहुंचेगी <shell> -c 'export fd; printenv fd {fd}> /dev/null'में zsh, bashऔर ksh93)। आप इसे दो चरणों में या संभवत: उपयोग करके ksh93/ इसमें काम bashकर सकते हैं eval, लेकिन इसके लिए bash, साइड इफेक्ट होगा यदि xtrace विकल्प चालू था।
स्टीफन चेजलस

5

चूंकि वे स्क्रिप्ट हैं, आप उनकी प्रतियां बना सकते हैं, और उन्हें संपादित कर सकते हैं।

इसके अलावा, आउटपुट को फ़िल्टर करना सरल प्रतीत होगा, आप PS4फ़िल्टरिंग फ़िल्टर बनाने के लिए स्पष्ट रूप से एकल प्लस की तुलना में कुछ अधिक असामान्य सेट कर सकते हैं :

PS4="%%%%" bash script.sh 2>&1 | grep -ve '^%%%%'

(बेशक जो स्टडआउट और स्टड को ध्वस्त कर देगा, लेकिन बैश में सिर्फ स्टेंडर को पाइपिंग करने से थोड़ा बाल निकल जाते हैं, इसलिए मैं इसे अनदेखा कर दूंगा)


1
पिपर बस स्टडर आसान है PS4="%%%%" bash script.sh 2> >(grep -ve '^%%%%'):।
पैट्रिक

4
@ पाट्रिक, ऐसा करने में bashसमस्याएँ हैं जो grepअसिंक्रोनस रूप से चलाई जाती हैं (बैश इसके लिए इंतजार नहीं कर रहा है, इसलिए यह स्क्रिप्ट में अगली कमांड शुरू होने के बाद आउटपुट चीजें कर सकता है (और अक्सर करता है)।
स्टीफन चेजलस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.