2010-07-08 24 views
8

परिदृश्य यह है कि उपयोगकर्ताओं को एक स्क्रिप्ट फ़ाइल स्रोत करने के लिए कहा जाता है:कैसे करें: खोल स्क्रिप्ट से बैश का पता लगाएं

$ source envsetup.sh 

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

अन्य शैल के लिए जो सामान्य सिंटैक्स को बैश के साथ साझा करते हैं, उदाहरण के लिए, sh, zsh, ksh, मैं एक चेतावनी की रिपोर्ट करना चाहता हूं।

लिनक्स, सिगविन, ओएस एक्स में वर्तमान खोल का पता लगाने का सबसे विश्वसनीय तरीका क्या है?

मुझे पता है कि $ BASH है, लेकिन मैं सोच रहा हूं कि यह असफल हो सकता है।

उत्तर

13

पर्यावरण चर के एक समूह हैं जिन्हें आप देख सकते हैं लेकिन उनमें से कई पता नहीं लगाएंगे कि एक अलग खोल बाश से उत्पन्न होता है या नहीं। निम्नलिखित पर विचार करें:

bash$ echo "SHELL: $SHELL, shell: $shell, ARGV[0]: $0, PS1: $PS1, prompt: $prompt" 
SHELL: /bin/bash, shell: , ARGV[0]: -bash, PS1: bash$ , prompt: 

bash$ csh 
[lorien:~] daveshawley% echo "SHELL: $SHELL, shell: $shell, \$0: $0, PS1: $PS1, prompt: $prompt" 
SHELL: /bin/bash, shell: /bin/tcsh, ARGV[0]: csh, PS1: bash$ , prompt: [%m:%c3] %n%# 

[lorien:~] daveshawley% bash -r 
bash$ echo "SHELL: $SHELL, shell: $shell, ARGV[0]: $0, PS1: $PS1, prompt: $prompt" 
SHELL: /bin/bash, shell: , ARGV[0]: sh, PS1: bash$ , prompt: 

bash$ zsh 
% echo "SHELL: $SHELL, shell: $shell, ARGV[0]: $0, PS1: $PS1, prompt: $prompt" 
SHELL: /bin/bash, shell: , ARGV[0]: zsh, PS1: % , prompt: % 

% ksh 
$ echo "SHELL: $SHELL, shell: $shell, ARGV[0]: $0, PS1: $PS1, prompt: $prompt" 
SHELL: /bin/bash, shell: , ARGV[0]: ksh, PS1: bash$ , prompt: 

सिवाय इसके कि वे उप गोले द्वारा विरासत में मिला जा रहा है जो वह जगह है जहाँ पर्यावरण बात वास्तव में टूट जाता है की एक आदत है कि विभिन्न गोले के लिए विशिष्ट चर का एक संख्या में हैं। लगभग एक चीज जो लगभग काम करती है ps -o command -p $$ है। यह तकनीकी रूप से आपको कमांड नाम देता है जिसे खोल चल रहा है। ज्यादातर मामलों में यह काम करेगा ... चूंकि एप्लिकेशन exec सिस्टम कॉल के कुछ प्रकार के साथ शुरू किए गए हैं और यह कमांड के नाम और निष्पादन योग्य के लिए अनुमति देता है, इसके लिए भी असफल होना संभव है। पर विचार करें:

bash$ exec -a "-csh" bash 
bash$ echo "$0, $SHELL, $BASH" 
-csh, /bin/bash, /bin/bash 
bash$ ps -o command -p $$ 
COMMAND 
-csh 
bash$ 

एक और चाल lsof -p $$ | awk '(NR==2) {print $1}' उपयोग करने के लिए है। यह शायद उतना करीब है जितना आप प्राप्त कर सकते हैं यदि आप भाग्यशाली हैं lsof आसान है।

2

SHELL पर्यावरण परिवर्तक आपको बताएगा कि लॉगिन शेल चल रहा है।

इसके अलावा, आप मौजूदा शेल को खोजने के लिए ps $$ का उपयोग कर सकते हैं, जिसका उपयोग आप जानना चाहते हैं कि स्क्रिप्ट किस शैल के अंतर्गत चल रही है (आवश्यक रूप से लॉगिन खोल नहीं है)। ps आउटपुट को खोलने के लिए केवल शेल नाम: ps o command= $$ (यह सुनिश्चित न करें कि क्रॉस-प्लेटफॉर्म सुरक्षित कैसे है, लेकिन यह मैक ओएस एक्स पर काम करता है)।

+0

'$ SHELL' पर भरोसा करने से पहले इसे बैश के भीतर से आज़माएं: 'csh -c 'echo" $ SHELL "' –

+0

प्रश्न का मेरा प्रभाव यह है कि स्क्रिप्ट को लॉगिन खोल जानने की आवश्यकता है। लॉगिन खोल के रूप में बैश का उपयोग करके, उस कमांड को चलाने से बैश वापस आना चाहिए, जिसकी अपेक्षा की जाती है। – Jeff

+0

लॉगिन खोल नहीं है। यदि आप बैश का उपयोग लॉगिन करते हैं तो सीएसएच में बदलें, $ SHELL बैश बनी हुई है, लेकिन 'स्रोत' विफल हो जाएगी। –

10

यह भी काम करता है

[ -z "$BASH_VERSION" ] && return 
+1

यह zsh के लिए भी कर सकता है, इसलिए यदि [-n "$ {BASH_VERSION}"]; तो ... elif [-n "$ {ZSH_VERSION}"]; तो ... fi' –

+0

में स्क्रिप्ट है: '#!/bin/sh \ n $ BASH_VERSION' गूंजें और इसे बाश खोल से sh या csh के साथ भी चलाएं:' $ sh।/test.sh' और आपको मिलेगा उपयोगकर्ता से env var prefered bash संस्करण ....चल रहे स्क्रिप्ट को पूरी तरह से भ्रामक – gcb

1

क्या आप पोर्टेबल (यानी। खोल स्वतंत्र) स्क्रिप्ट लिखने से रोकता है?

+0

क्योंकि अपस्ट्रीम इस पर बहुत दृढ़ता से निर्भर करता है। यह वह नहीं है जिसे मैं नियंत्रित कर सकता हूं ;-) –

+0

तो क्या आप कुछ वितरण के लिए मौजूदा स्क्रिप्ट को थोड़े से पैच कर रहे हैं? –

+0

जिज्ञासा से, 'envsetup.sh' द्वारा क्या बाश-विशिष्ट विशेषताओं का उपयोग किया जा सकता है? मैं कल्पना करता हूं कि इसमें केवल कुछ 'निर्यात ए = बी' कथन शामिल हैं ... –

0

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

2

मुझे लगता है कि यह संगत सबसे अधिक व्यावहारिक और पार खोल होगा

/proc/self/exe --version 2>/dev/null | grep -q 'GNU bash' && USING_BASH=true || USING_BASH=false 

स्पष्टीकरण:

/proc/self हमेशा वर्तमान को क्रियान्वित करने की प्रक्रिया को इंगित करेंगे, उदाहरण के लिए, निम्नलिखित चल पीआईडी ​​का पता चलता है readlink का यह स्वयं (शेल जो कि रीडलिंक निष्पादित नहीं किया गया)

$ bash -c 'echo "The shell pid = $$"; echo -n "readlink (subprocess) pid = "; readlink /proc/self; echo "And again the running shells pid = $$"' 

परिणाम में:

The shell pid = 34233 
readlink (subprocess) pid = 34234 
And again the running shells pid = 34233 

अब: में

bash -c 'echo -n "readlink binary = "; readlink /proc/self/exe; echo -n "shell binary = "; readlink /proc/$$/exe' 

परिणाम::

readlink binary = /bin/readlink 
shell binary = /bin/bash 

यहाँ और है /proc/self/exe चल निष्पादन करने के लिए एक प्रतीकात्मक कड़ी

उदाहरण है परिणाम डैश और zsh में चल रहे हैं, और चल रहे बैश thr एक symlink, और एक प्रति के माध्यम से भी।

[email protected]:~$ cp /bin/bash ./my_bash_copy 
[email protected]:~$ ln -s /bin/bash ./hello_bash 
[email protected]:~$ 

[email protected]:~$ dash -c '/proc/self/exe -c "readlink /proc/$$/exe"; zsh -c "/proc/self/exe --version"; ./hello_bash --version | grep bash; ./my_bash_copy --version | grep bash' 
/bin/dash 
zsh 5.0.7 (x86_64-pc-linux-gnu) 
GNU bash, version 4.3.30(1)-release (x86_64-pc-linux-gnu) 
GNU bash, version 4.3.30(1)-release (x86_64-pc-linux-gnu) 
[email protected]:~$ dash -c '/proc/self/exe -c "readlink /proc/$$/exe"; zsh -c "/proc/self/exe --version"; ./hello_bash --version | grep bash; ./my_bash_copy --version | grep bash' 
4

यहाँ एक अच्छा तरीका है:

if test -z "$(type -p)" ; then echo bash ; else echo sh ; fi 

और आप निश्चित रूप से कुछ भी आप चाहते हैं के साथ "गूंज" बयान बदल सकते हैं।

=================

चर्चा:

  • $SHELL चर उपयोगकर्ता की पसंदीदा खोल इंगित करता है ... जो आप कुछ नहीं कहता है इस समय चल रहे खोल के बारे में।

  • परीक्षण $BASH_VERSION 99% अच्छा विचार है, लेकिन कुछ बुद्धिमान व्यक्ति उस नाम के चर को पर्यावरण के रूप में चिपकाने में विफल हो सकता है। इसके अलावा, यह आपको के बारे में बहुत कुछ नहीं बताता है जो गैर-बैश खोल चल रहा है।

  • $(type -p) विधि अति-आसान है, और कुछ बुद्धिमान व्यक्ति आपके $PATH में "-p" नामक फ़ाइल बनाता है, भले ही काम करता है। इसके अलावा, इसे 4-तरफा भेदभाव के आधार के रूप में या 5-तरफा भेदभाव का 80% के रूप में उपयोग किया जा सकता है, जैसा कि नीचे चर्चा की गई है।

  • अपनी स्क्रिप्ट के शीर्ष पर एक हैश-बैंग यानि #! लाना नहीं गारंटी नहीं है कि यह अपनी पसंद का दुभाषिया को खिलाया जा जाएगा करता है। उदाहरण के लिए, मेरे ~/.xinitrc को /bin/sh द्वारा व्याख्या किया जाता है इससे कोई फर्क नहीं पड़ता कि शीर्ष पर हैश-बैंग (यदि कोई है) दिखाई देता है।

  • अच्छा अभ्यास कुछ ऐसी सुविधाओं का परीक्षण करना है जो दोनों भाषाओं में विश्वसनीय रूप से मौजूद हैं, लेकिन अलग-अलग व्यवहार करते हैं। इसके विपरीत, यह नहीं सामान्य रूप से उस सुविधा को आजमाने के लिए सुरक्षित रहें और देखें कि यह विफल रहता है या नहीं।उदाहरण के लिए, यदि आप अंतर्निहित declare सुविधा का उपयोग करना चाहते हैं और यह मौजूद नहीं है, तो यह एक प्रोग्राम चला सकता है, और इसमें असीमित नकारात्मक क्षमता है।

  • कभी-कभी सबसे कम-आम-denominator सुविधा सेट का उपयोग करके संगत कोड लिखना उचित है ... लेकिन कभी-कभी यह नहीं होता है। उनमें से अधिकतर विशेषताओं को एक कारण के लिए जोड़ा गया था। चूंकि ये दुभाषिया «लगभग» ट्यूरिंग-पूर्ण हैं, यह लगभग «लगभग» एक दूसरे के साथ अनुकरण करने के लिए संभव होने की गारंटी है ... संभव है, लेकिन उचित नहीं है।
  • असंगतता की दो परतें हैं: वाक्यविन्यास और अर्थशास्त्र। उदाहरण के लिए, सीएसएच के लिए if-then-else वाक्यविन्यास बैश से इतना अलग है कि संगत कोड लिखने का एकमात्र तरीका बिना किसी और के बयान के करना होगा। यह संभव है, लेकिन यह एक उच्च लागत लगाता है। अगर वाक्यविन्यास गलत है, तो स्क्रिप्ट निष्पादित नहीं होगी। एक बार जब आप उस बाधा से गुजरते हैं, तो दर्जनों तरीके हैं जिनमें उचित दिखने वाला कोड अलग-अलग परिणाम उत्पन्न करता है, इस पर निर्भर करता है कि दुभाषिया की कौन सी बोली चल रही है।
  • एक बड़े, जटिल प्रोग्राम के लिए, दो संस्करणों को लिखना समझ में नहीं आता है। अपनी पसंद की भाषा में इसे एक बार लिखें। अगर कोई गलत दुभाषिया के तहत इसे शुरू करता है, तो आप इसका पता लगा सकते हैं और बस exec सही दुभाषिया का पता लगा सकते हैं।

  • एक 5 तरीका डिटेक्टर यहां पाया जा सकता:

    https://www.av8n.com/computer/shell-dialect-detect

    यह भेदभाव कर सकते हैं:

    • बैश
    • bsd-csh
    • पानी का छींटा
    • ksh93
    • zsh5

    इसके अलावा, मेरी उबंटू Xenial बॉक्स पर, 5-जिस तरह से जांच भी शामिल किया गया है जो निम्न:

    • राख पानी का छींटा
    • csh के लिए/bin/bsd एक सिमलिंक है एक सिमलिंक है -csh
    • ksh को/bin एक सिमलिंक है/ksh93
    • श पानी का छींटा
एक सिमलिंक है
संबंधित मुद्दे