$ BASH_COMMAND चर किसके लिए अच्छा है?


25

बैश मैनुअल के अनुसार , पर्यावरण चर BASH_COMMANDमें शामिल है

कमांड को वर्तमान में निष्पादित किया जा रहा है या निष्पादित किया जा रहा है, जब तक कि शेल कमांड को ट्रैप के परिणाम के रूप में निष्पादित नहीं कर रहा है, जिस स्थिति में यह ट्रैप के समय निष्पादित कमांड है।

उस जाल कोने के मामले को एक तरफ ले जाना, अगर मैं सही ढंग से समझता हूं इसका मतलब है कि जब मैं एक कमांड निष्पादित करता हूं, तो चर BASH_COMMANDमें वह कमांड होता है। यह पूरी तरह स्पष्ट नहीं है कि क्या उस चर आदेश निष्पादन के बाद सेट नहीं होने पर (यानी, केवल avaialble है , जबकि , आदेश चल रहा है, लेकिन उसके बाद नहीं) हालांकि एक तर्क कर सकता है कि क्योंकि यह है "कमांड वर्तमान में मार डाला या जा रहा है के बारे में किए जाने की मार डाला" , यह कमांड नहीं है जिसे अभी निष्पादित किया गया था

लेकिन आइए देखें:

$ set | grep BASH_COMMAND=
$ 

खाली करें। मुझे देखने की उम्मीद होगी BASH_COMMAND='set | grep BASH_COMMAND='या शायद BASH_COMMAND='set', लेकिन खाली ने मुझे आश्चर्यचकित कर दिया।

चलो कुछ और कोशिश करते हैं:

$ echo $BASH_COMMAND
echo $BASH_COMMAND
$ 

खैर यह समझ में आता है। मैं कमांड निष्पादित करता हूं echo $BASH_COMMANDऔर इसलिए चर BASH_COMMANDमें स्ट्रिंग शामिल है echo $BASH_COMMAND। इस बार क्यों काम किया, लेकिन पहले नहीं?

चलो setफिर बात करते हैं:

$ set | grep BASH_COMMAND=
BASH_COMMAND='echo $BASH_COMMAND'
$

तो इंतज़ार करो। यह सेट किया गया था जब मैंने उस echoकमांड को निष्पादित किया था , और यह बाद में परेशान नहीं था। लेकिन जब मैंने setफिर से निष्पादित किया, तो कमांड के लिए सेट BASH_COMMAND नहीं किया गया थाset । कोई फर्क नहीं पड़ता कि मैं setयहां कितनी बार कमांड निष्पादित करता हूं , परिणाम वही रहता है। तो, निष्पादित करते समय चर सेट है echo, लेकिन निष्पादित करते समय नहीं set? चलो देखते हैं।

$ echo Hello AskUbuntu
Hello AskUbuntu
$ set | grep BASH_COMMAND=
BASH_COMMAND='echo $BASH_COMMAND'
$

क्या? जब मैं निष्पादित किया गया था तो चर सेट किया गया था echo $BASH_COMMAND, लेकिन जब मैंने निष्पादित नहीं किया था echo Hello AskUbuntu? अब फर्क कहां है? क्या वैरिएबल केवल तब सेट होता है जब करंट कमांड ही वास्तव में शेल को मूल्यांकन करने के लिए मजबूर करता है? चलिए कुछ अलग करने की कोशिश करते हैं। हो सकता है कि कुछ बाहरी आदेश इस बार, एक बदलाव के लिए बैश बिलिन नहीं।

$ /bin/echo $BASH_COMMAND
/bin/echo $BASH_COMMAND
$ set | grep BASH_COMMAND=
BASH_COMMAND='/bin/echo $BASH_COMMAND'
$

हम्म, ठीक है ... फिर से, चर सेट किया गया था। तो क्या मेरा वर्तमान अनुमान सही है? क्या चर केवल तब निर्धारित किया जाता है जब उसका मूल्यांकन करना होता है? क्यूं कर? क्यूं कर? प्रदर्शन कारणों से? चलो एक और कोशिश करते हैं। हम $BASH_COMMANDएक फ़ाइल के लिए grep करने का प्रयास करेंगे , और $BASH_COMMANDतब से एक grepकमांड सम्‍मिलित grepहोनी चाहिए , उस grepकमांड के लिए grep चाहिए (जैसे, अपने लिए)। तो चलो एक उपयुक्त फ़ाइल बनाते हैं:

$ echo -e "1 foo\n2 grep\n3 bar\n4 grep \$BASH_COMMAND tmp" > tmp
$ grep $BASH_COMMAND tmp
grep: $BASH_COMMAND: No such file or directory
tmp:2 grep                                      <-- here, the word "grep" is RED
tmp:4 grep $BASH_COMMAND tmp                    <-- here, the word "grep" is RED
tmp:2 grep                                      <-- here, the word "grep" is RED
tmp:4 grep $BASH_COMMAND tmp                    <-- here, the word "grep" is RED
$ set | grep BASH_COMMAND=
BASH_COMMAND='grep --color=auto $BASH_COMMAND tmp'
$

ठीक है, दिलचस्प है। कमांड grep $BASH_COMMAND tmpका विस्तार हो गया grep grep $BASH_COMMAND tmp tmp(वैरिएबल का विस्तार केवल एक बार, निश्चित रूप से हो जाता है), और इसलिए मैंने grepएक बार फाइल में $BASH_COMMANDमौजूद नहीं है, और फ़ाइल में दो बार के लिए grepped किया है tmp

Q1: क्या मेरी वर्तमान धारणा सही है:

  • BASH_COMMANDकेवल तभी सेट होता है जब कोई कमांड वास्तव में इसका मूल्यांकन करने की कोशिश करता है; तथा
  • यह एक आदेश के निष्पादन के बाद परेशान नहीं है , भले ही विवरण हमें ऐसा करने के लिए प्रेरित कर सकता है?

Q2: यदि हाँ, तो क्यों? प्रदर्शन? यदि नहीं, तो उपरोक्त आदेश अनुक्रम में व्यवहार को और कैसे समझाया जा सकता है?

Q3: अंत में, क्या ऐसा कोई परिदृश्य है जिसमें इस चर का वास्तव में सार्थक उपयोग किया जा सकता है? मैं वास्तव में इसका उपयोग करने की कोशिश कर रहा था $PROMPT_COMMANDताकि कमांड का विश्लेषण किया जा सके (और उसके आधार पर कुछ सामान किया जा सके), लेकिन मैं नहीं कर सकता, क्योंकि जैसे ही मेरे भीतर $PROMPT_COMMAND, मैं चर को देखने के लिए एक कमांड निष्पादित करता हूं , $BASH_COMMANDचर उस कमांड पर सेट हो जाता है। यहां तक ​​कि जब मैं MYVARIABLE=$BASH_COMMANDअपनी शुरुआत में सही करता हूं $PROMPT_COMMAND, तो MYVARIABLEस्ट्रिंग शामिल होती है MYVARIABLE=$BASH_COMMAND, क्योंकि एक असाइनमेंट एक कमांड भी है। (यह सवाल इस बारे में नहीं है कि मैं एक $PROMPT_COMMANDनिष्पादन के भीतर वर्तमान कमांड कैसे प्राप्त कर सकता हूं । अन्य तरीके भी हैं, मुझे पता है।)

यह हाइजेनबर्ग के अनिश्चितता सिद्धांत के साथ थोड़ा सा है। बस चर को देखकर, मैं इसे बदल देता हूं।


5
अच्छा है, लेकिन शायद unix.stackexchange.com के लिए बेहतर अनुकूल है ... वहां असली bashüber- gurus हैं ।
रमनो

अच्छा, क्या इसे वहाँ ले जाना संभव है? मॉड?
माल्ट स्कोर्पुपा

मुझे यकीन नहीं है कि यह कैसे करना है --- मुझे लगता है कि यह एक मॉड विशेषाधिकार है। दूसरी ओर मुझे नहीं लगता कि इसे फहराना समझदारी है --- आइए देखें कि कोई व्यक्ति क्लोज फ़्लैग पर कार्य करता है या नहीं।
रमनो

1
तीसरे बिंदु के लिए, यह वही है जो आप खोज रहे हैं। शायद उस लेख के आधार पर आप पहले दो बिंदुओं के लिए भी उत्तर पा सकते हैं।
रादु राईडेनू

2
+1 ने मुझे बाहर निकालने की उलझन में डाल दिया, लेकिन यह पढ़ने में मजेदार था!
जो

जवाबों:


15

तीसरे प्रश्न का उत्तर: निश्चित रूप से इसका उपयोग बाश मैनुअल में स्पष्ट रूप से संकेत के रूप में किया जा सकता है - एक निशान में, उदाहरण के लिए:

$ trap 'echo ‘$BASH_COMMAND’ failed with error code $?' ERR
$ fgfdjsa
fgfdjsa: command not found
fgfdjsa failed with error code 127
$ cat /etc/fgfdjsa
cat: /etc/fgfdjsa: No such file or directory
cat /etc/fgfdjsa failed with error code 1

आह, वास्तव में अच्छा है। तो क्या आप कहेंगे कि एक जाल एकमात्र संदर्भ है जिसमें यह चर समझ में आता है? यह मैनुअल में एक कोने के मामले की तरह लग रहा था: "कमांड को निष्पादित किया जा रहा है (...), जब तक कि शेल एक जाल के परिणामस्वरूप एक कमांड को निष्पादित नहीं कर रहा है, ..."
माल्टे स्कॉरुप्पा

@DocSalvager द्वारा उत्तर में लिंक किए गए लेखों को पढ़ने के बाद, यह स्पष्ट है कि $BASH_COMMANDवास्तव में एक जाल के अलावा संदर्भों में भी सार्थक रूप से उपयोग किया जा सकता है। फिर भी, आपके द्वारा वर्णित उपयोग संभवतः सबसे विशिष्ट और सीधे-आगे है। तो आपका जवाब, और डॉकस्लेवजर द्वारा एक, मेरे क्यू 3 का सबसे अच्छा जवाब देना , और यह मेरे लिए सबसे महत्वपूर्ण था। Q1 और Q2 के लिए, जैसा कि @zwets द्वारा इंगित किया गया है, वे चीजें अपरिभाषित हैं। ऐसा हो सकता है कि $BASH_COMMANDप्रदर्शन के लिए एक्सेस किए जाने पर ही मान दिया जाए - या फिर कुछ अजीब आंतरिक कार्यक्रम की स्थिति उस व्यवहार को जन्म दे सकती है। क्या पता?
माल्टे स्कॉरप्पा

1
एक वाक्य पर, मुझे पता चला कि आप प्रत्येक कमांड के पहले मूल्यांकन के लिए मजबूर करके, हमेशा सेट होने के लिए मजबूर कर सकते हैं । ऐसा करने के लिए हम DEBUG ट्रैप का उपयोग कर सकते हैं, जिसे हर एक कमांड (सभी एमएम) से पहले निष्पादित किया जाता है। यदि हम जारी करते हैं, उदाहरण के लिए , तो हमेशा प्रत्येक कमांड से पहले मूल्यांकन किया जाएगा (और उस का मान असाइन किया गया है )। इसलिए अगर मैं उस जाल को सक्रिय करते हुए निष्पादित करता हूं ... तो आप क्या जानते हैं? अब आउटपुट उम्मीद के $BASH_COMMAND$BASH_COMMANDtrap 'echo "$BASH_COMMAND" > /dev/null' DEBUG$BASH_COMMAND$COMMANDset | grep BASH_COMMAND=BASH_COMMAND=set
मुताबिक है

6

अब जब कि Q3 का उत्तर दिया गया है (सही रूप में, मेरी राय में: BASH_COMMANDजाल में और शायद ही कहीं और उपयोगी है), चलो Q1 और Q2 को एक शॉट दें।

Q1 का उत्तर यह है: आपकी धारणा की शुद्धता अस्पष्ट है। न तो बुलेट बिंदुओं की सच्चाई स्थापित की जा सकती है, क्योंकि वे अनिर्दिष्ट व्यवहार के बारे में पूछते हैं। इसके विनिर्देश द्वारा, BASH_COMMANDउस कमांड के निष्पादन की अवधि के लिए एक कमांड के पाठ पर मान निर्धारित किया जाता है। युक्ति यह नहीं बताती है कि किसी अन्य स्थिति में इसका मूल्य क्या होना चाहिए, अर्थात जब कोई आदेश निष्पादित नहीं किया जा रहा है। इसका कोई मूल्य या कोई भी नहीं हो सकता है।

Q2 का उत्तर "यदि नहीं, तो उपरोक्त कमांड अनुक्रम में व्यवहार को और कैसे समझाया जा सकता है?" इसके बाद तार्किक रूप से (यदि कुछ हद तक): यह इस तथ्य से समझाया जाता है कि मूल्य BASH_COMMANDअपरिभाषित है। चूंकि इसका मूल्य अपरिभाषित है, इसलिए इसका कोई भी मूल्य हो सकता है, जो कि वास्तव में अनुक्रम दिखाता है।

परिशिष्ट भाग

एक बिंदु है जहां मुझे लगता है कि आप वास्तव में कल्पना में एक नरम स्थान मार रहे हैं। यह आप कहते हैं:

यहां तक ​​कि जब मैं अपने $ PROMPT_COMMAND की शुरुआत में MYVARIABLE = $ BASH_COMMAND सही करता हूं, तब MYVARIABLE में स्ट्रिंग MYVARIABLE = $ BASH_COMMAND शामिल है, क्योंकि एक असाइनमेंट एक कमांड भी है

जिस तरह से मैं बैश मैन पेज पढ़ता हूं, इटैलिक में बिट सही नहीं है। अनुभाग SIMPLE COMMAND EXPANSIONबताता है कि कमांड लाइन पर पहले चर असाइनमेंट को एक तरफ कैसे सेट किया जाता है, और फिर

यदि कोई आदेश नाम परिणाम नहीं है [दूसरे शब्दों में, केवल चर असाइनमेंट थे], चर असाइनमेंट वर्तमान शेल वातावरण को प्रभावित करते हैं।

इससे मुझे पता चलता है कि चर असाइनमेंट BASH_COMMANDअन्य प्रोग्रामिंग भाषाओं की तरह कमांड नहीं हैं (और इसलिए दिखाने से छूट दी गई है )। इसके बाद यह भी समझाया जाएगा कि BASH_COMMAND=setआउटपुट में कोई लाइन क्यों नहीं है set, setअनिवार्य रूप से वेरिएबल असाइनमेंट के लिए सिंटेक्टिक 'मार्कर' है।

OTOH, उस खंड के अंतिम पैराग्राफ में कहता है

यदि विस्तार के बाद कोई कमांड नाम बचा है, तो निष्पादन कार्यवाही नीचे बताई गई है। अन्यथा, कमांड से बाहर निकलता है।

... जो अन्यथा सुझाव देता है, और चर असाइनमेंट भी कमांड हैं।


1
सिर्फ इसलिए कि कुछ धारणा को स्थापित नहीं किया जा सकता है इसका मतलब यह नहीं है कि यह गलत है। आइंस्टीन ने माना कि प्रकाश की गति किसी भी पर्यवेक्षक के लिए समान है (किसी भी गति पर) सापेक्षता के सिद्धांत के लिए एक मौलिक परिकल्पना के रूप में; यह स्थापित नहीं किया जा सकता है, फिर भी इसका मतलब यह नहीं है कि यह गलत है। गुण "स्थापित किया जा सकता है" और "सही है" ऑर्थोगोनल हैं। सबसे अच्छी तरह से आप कह सकते हैं "हम नहीं जानते कि क्या यह सही है, क्योंकि यह स्थापित नहीं किया जा सकता है"। इसके अलावा, यह है निर्दिष्ट: यह निष्पादन के दौरान वर्तमान आदेश है। इसलिए अगर मैं टाइप करता setहूं तो मुझे BASH_COMMAND='set'उस आउटपुट में कहीं दिखना चाहिए , जो
माल्टे स्कॉरप्पा

... हालाँकि ऐसा नहीं है। भले ही वह कमांड के निष्पादन के दौरान होset । इसलिए, चश्मे के अनुसार यह काम करना चाहिए। तो क्या यह है कि कार्यान्वयन ईमानदारी से चश्मे का पालन नहीं करता है, या क्या मैं चश्मे को गलत समझता हूं? उस प्रश्न का उत्तर खोजना Q1 के उद्देश्य की तरह है। +1 आपकी पोस्टस्क्रिप्ट के लिए :)
माल्टे स्कॉरप्पा

@MalteSkoruppa अच्छे अंक। तदनुसार जवाब तय किया, और के बारे में एक टिप्पणी जोड़ी set
13

1
यह संभव है कि बैश दुभाषिया में, setएक "कमांड" नहीं है। जिस तरह =एक "कमांड" नहीं है। उन टोकन के बाद / आसपास के पाठ का प्रसंस्करण "कमांड" के प्रसंस्करण की तुलना में पूरी तरह से अलग तर्क हो सकता है।
DocSalvager

आप दोनों से अच्छे अंक। :) यह अच्छी तरह से हो सकता है कि set"कमांड" के रूप में नहीं गिना जाता है। मैंने सोचा नहीं होगा कि $BASH_COMMANDकई परिस्थितियों में यह इतना कम हो जाएगा। मुझे लगता है कि हमने बहुत कम से कम यह स्थापित किया है कि आदमी पृष्ठ निश्चित रूप से इसके बारे में स्पष्ट हो सकता है;)
माल्टे स्कॉरुप्पा

2

$ BASH_COMMAND के लिए एक आविष्कारशील उपयोग

हाल ही में मैक्रो जैसी कार्यक्षमता को लागू करने में $ BASH_COMMAND का यह प्रभावशाली उपयोग पाया गया ।

यह उपनाम की मुख्य चाल है और DEBUG जाल के उपयोग को प्रतिस्थापित करता है। यदि आप DEBUG के जाल के बारे में पिछली पोस्ट में हिस्सा पढ़ते हैं, तो आप $ BASH_COMMAND चर को पहचान लेंगे। उस पोस्ट में मैंने कहा था कि यह डीबग जाल में प्रत्येक कॉल से पहले कमांड के पाठ पर सेट किया गया था। ठीक है, यह पता चलता है कि यह हर कमांड के निष्पादन से पहले सेट किया गया है, DEBUG जाल या नहीं (जैसे रन 'गूंज "यह कमांड = $ BASH_COMMAND" यह देखने के लिए कि मैं किस बारे में बात कर रहा हूं)। इसे एक चर (केवल उस पंक्ति के लिए) असाइन करके हम BASH_COMMAND को कमांड के सबसे बाहरी दायरे में कैप्चर करते हैं, जिसमें संपूर्ण कमांड होगी।

लेखक का पिछला लेख DEBUG का उपयोग करके तकनीक को लागू करते समय कुछ अच्छी पृष्ठभूमि भी प्रदान करता है traptrapउन्नत संस्करण में समाप्त हो रहा है।


+1 मैं अंत में उन दो लेखों को पढ़ने के लिए इधर-उधर हो गया। वाह! क्या पढ़ा! बहुत ज्ञानवर्धक है। वह आदमी बैश गुरु है ! कुडोस! यह दिमित्री के जवाब पर मेरी टिप्पणी का भी जवाब देता है कि क्या $BASH_COMMANDएक के अलावा अन्य संदर्भ में इसका सार्थक उपयोग किया जा सकता है trap। और इसका क्या उपयोग है! इसका उपयोग मैश कमांड को बैश में लागू करने के लिए - जिसने यह संभव सोचा होगा? सूचक के लिए धन्यवाद।
माल्टे स्कॉरप्पा

0

जाल के लिए एक समान रूप से सामान्य उपयोग ... डिबग का शीर्षक "विंडो" का उपयोग करते समय विंडोलिस्ट (^ ए) में दिखाई देने वाले शीर्षकों को सुधारना है।

मैं "स्क्रीन", "विंडोलिस्ट" को अधिक उपयोगी बनाने की कोशिश कर रहा था, इसलिए मैंने "ट्रैप ... डीबग" का संदर्भ देने वाले लेख खोजने शुरू किए।

मैंने पाया कि "नल शीर्षक अनुक्रम" भेजने के लिए PROMPT_COMMAND का उपयोग करने की विधि इतनी अच्छी तरह से काम नहीं करती है, इसलिए मैं जाल ... डीबग विधि पर वापस लौट आया।

इसे कैसे करना है इसके बारे में यहां बताया गया है:

1 "स्क्रीन" को एस्केप सीक्वेंस के लिए देखें (इसे सक्षम करें) "शेल्टिटल '$ | bash:'" को "$ HOME / .rcrc" में डालकर।

2 डिबग ट्रैप के उप-गोले में प्रसार को बंद करें। यह महत्वपूर्ण है, क्योंकि यदि यह सक्षम है, तो सब कुछ गड़बड़ हो जाता है, उपयोग करें: "सेट + ओ फंक्शनल"।

3 व्याख्या करने के लिए "स्क्रीन" के लिए शीर्षक एस्केप अनुक्रम भेजें: ट्रैप 'प्रिंटफ' \ ek $ (दिनांक +% Y% m% d% H% M% S) $ (whoami) @ $ (hostname): $ (pwd) $ {BASH_COMMAND} \ e \ "" DEBUG "

यह सही नहीं है, लेकिन यह मदद करता है, और आप इस पद्धति का उपयोग कर सकते हैं शाब्दिक रूप से कुछ भी जिसे आप शीर्षक में पसंद करते हैं

निम्नलिखित "विंडो सूची" (5 स्क्रीन) देखें:

न्यूम नाम झंडे

1 बैश: 20161115232035 mcb @ ken007: / home / mcb / ken007 RSYNCCMD = "sudo rsync" myrsync.sh -R -r "$ {1}" "$ {BACKUPDIR} $ {2: +" / $ {2} ""। } "$ 2 bash: 20161115230434 mcb @ ken007: / home / mcb / ken007 ls --color = auto -la $ 3 bash: 20161115230504 mcb / ken007: / home / mcb / ken007 cat bin / psg.sh $ 4 bash 20161115222415 mcb @ ken007: / home / mcb / ken007 ssh ken009 $ 5 bash: 20161115222450 mcb @ ken007: / home / mbb / ken007 mycommoncleanup $

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