रनटाइम के दौरान स्क्रिप्ट में शेल का निर्धारण करें


22

मेरे ज्ञान के अनुसार, शेल में वर्तमान शेल का उपयोग करने echo $0के लिए। बल्कि मैं चाहता हूं कि मेरी स्क्रिप्ट यह जांच करे कि वह किस खोल में चल रही है। इसलिए, मैंने $0स्क्रिप्ट में प्रिंट करने की कोशिश की और यह स्क्रिप्ट का नाम उसी रूप में लौटाता है जैसा इसे चाहिए। तो, मेरा सवाल यह है कि मैं कैसे खोज सकता हूं कि मेरी स्क्रिप्ट रनटाइम के दौरान चल रही है?


आप किस स्क्रिप्टिंग भाषा का उपयोग कर रहे हैं? इसके अलावा, बदतर स्थिति, आप स्क्रिप्ट के अंदर "इको $ 0" परिणाम प्राप्त करने के लिए हमेशा एक सिस्टम कमांड खोल सकते हैं।
ब्रिग्य

echo $0यहां कोई विकल्प नहीं है, क्योंकि स्क्रिप्ट कई अलग-अलग मशीनों पर चलेगी, जहां पहली चीज मुझे जांचनी होगी, वह है शेल।
g4ur4v

तो फिर स्क्रिप्टिंग भाषा क्या है?
बृजगय

@BriGuy: यह एक यूनिक्स खोल स्क्रिप्ट है।
g4ur4v

3
ठीक है, यदि आप #! /bin/sh -शीर्ष पर जोड़ते हैं, तो यह अंदर चलेगा sh। क्या आपका मतलब है कि shयह किस प्रकार का है?
स्टीफन चेज़लस

जवाबों:


28

लिनक्स पर आप उपयोग कर सकते हैं /proc/PID/exe

उदाहरण:

# readlink /proc/$$/exe
/bin/zsh

3
यह मेरे लिए थोड़ा विशिष्ट है (जैसे डेबियन पर यह zsh4 या ksh93 प्रिंट करता है)। /bin/sed -r -e 's/\x0.*//' /proc/$$/cmdlineइसके बजाय zsh या ksh देता है। (यह $ 0 होगा यदि गोले जादुई तरीके से स्क्रिप्ट नाम देने के लिए इसे ठीक नहीं करते हैं)।
ठंढकुट्ज़

@frostschutz तुम्हारा सबसे अच्छा जवाब है, +500 के लिए भागो!
टेरेसा ई जूनियर

5
यह खूंखार दुनिया के सभी लिनक्स बॉक्स रोग से ग्रस्त है। /procयह उतना ही बदसूरत और असम्भव है जितना इसे मिलता है।
जेन्स

7
@ यही कारण है कि मैंने निर्दिष्ट किया कि यह केवल लिनक्स पर लागू होता है। /proc'बदसूरत' नहीं है। /procअक्सर एक बहुत ही सुंदर समाधान है। हां, हां, लेकिन कुछ न कुछ होने के कारण यह बदसूरत नहीं है।
पैट्रिक

3
@Patrick को मैं /procबदसूरत मानता हूं क्योंकि इसमें फाइलें डेवलपर्स के चक्कर में आ सकती हैं और फाइलों की सामग्री बिना किसी नोटिस के बदलने का खतरा है, जिससे बिट्रोट के कारण अंतहीन दर्द होता है और लक्ष्य फ़ाइल स्वरूपों को हिलाना पड़ता है।
जेन्स

48

हो सकता है कि आप जो नहीं पूछ रहे हों, लेकिन यह कुछ हद तक दुभाषिया की पहचान करने के लिए काम करना चाहिए, जो वर्तमान में थोम्पसन (ओश), बॉर्न, बॉर्न-फिर (बैश), कॉर्न (ksh88, kh93, pdksh, mksh) की व्याख्या कर रहा है ), zsh, पॉलिसी-कंप्लेंट ऑर्डिनरी (पॉश), फिर भी एक और (यश), आरसी, आकांक्षा, es शेल्स, विश, टैल्श, उम्मीद, पर्ल, पाइथन, रूबी, php, जावास्क्रिप्ट (नोड्ज, स्पाइडरमंकी शेल और JSPL कम से कम) , MS / शराब cmd.exe, कमोडिटी (MSDOS, FreeDOS ...)।

'echo' +"'[{<?php echo chr(13)?>php <?php echo PHP_VERSION.chr(10);exit;?>}\
@GOTO DOS [exit[set 1 [[set 2 package] names];set 3 Tcl\ [info patchlevel];\
if {[lsearch -exact $1 Expect]>=0} {puts expect\ [$2 require Expect]\ ($3)} \
elseif {[lsearch -exact $1 Tk]>=0} {puts wish\ ($3,\ Tk\ [$2 require Tk])} \
else {puts $3}]]]' >/dev/null ' {\">/dev/null \
">"/dev/null" +"\'";q="#{",1//2,"}";a=+1;q='''=.q,';q=%{\"
'echo' /*>/dev/null
echo ">/dev/null;status=0;@ {status=1};*=(" '$' ");~ $status 1&&{e='"\
"';eval catch $2 ^'&version {eval ''echo <='^ $2 ^'&version''}';exit};e='"\
"';if (eval '{let ''a^~a''} >[2] /dev/null'){e='"\
"';exec echo akanga};eval exec echo rc $2 ^ version;\" > /dev/null
: #;echo possibly pre-Bourne UNIX V1-6 shell;exit
if (! $?version) set version=csh;exec echo $version
:DOS
@CLS
@IF NOT "%DOSEMU_VERSION%"=="" ECHO DOSEMU %DOSEMU_VERSION%
@ECHO %OS% %COMSPEC%
@VER
@GOTO FIN
", unless eval 'printf "perl %vd\n",$^V;exit;'> "/dev/null";eval ': "\'';
=S"';f=false e=exec\ echo n=/dev/null v=SH_VERSION;`(eval "f() { echo :
};f")2>$n` $f||$e Bourne-like shell without function
case `(: ${_z_?1}) 2>&1` in 1) $e ash/BSD sh;;esac;t(){
eval "\${$1$v+:} $f &&exec echo ${2}sh \$$1$v";};t BA ba;t Z z;t PO po;t YA ya
case `(typeset -Z2 b=0;$e $b)2>$n` in 00) (eval ':${.}')2>$n&&eval '
$e ksh93 ${.sh.version}';t K pdk;$e ksh88;;esac;case `(eval '$e ${f#*s}$($e 1
)$((1+1))')2>$n` in e12)$e POSIX shell;;esac;$e Bourne-like shell;: }
print "ruby ",RUBY_VERSION,"\n";exit;' ''';import sys
print("python "+sys.version);z='''*/;
s="";j="JavaScript";if(typeof process=="object"){p=console.log;p(process.title
,process.version)}else{p=print;p((f="function")==(t=typeof version)?"string"==
typeof(v=version())?v:(typeof build!=f?"":s= "SpiderMonkey ")+j+" "+v:(t==
"undefined"?j+"?":version)+"\n");if(s)build()}/*
:FIN } *///'''

मैंने usnet पर that_interpreter script circa 2004 का आरंभिक संस्करण पोस्ट किया । स्वेन मास्कचेक के पास (संभवतः आपके लिए अधिक उपयोगी) स्क्रिप्ट है जिसे व्हाट्सएप कहा जाता है जो बॉर्न जैसे गोले की पहचान करने पर केंद्रित है। आप वहां हमारी दो लिपियों का मर्ज किया गया संस्करण भी पा सकते हैं ।


3
यह पायथन 3 की पहचान नहीं कर सकता है, केवल पायथन 2। इसे ठीक करने के लिए, printफ़ंक्शन करने के लिए बदलें ।
क्रिस डाउन

39
यह साल का अब तक का सबसे बड़ा डब्ल्यूटीएफ क्षण है। पवित्रता अतीत की पवित्रता लेने के लिए +1।
l0b0

1
यह अच्छा होगा अगर वह मछली के खोल को पहचान ले।
कोनराड बोरोस्की

2
@ xfix, मुझे याद है कि php और जावास्क्रिप्ट जोड़ने से पहले भी कोशिश कर रहा था, लेकिन तब कोई समाधान नहीं मिला। यह जटिलता भाषाओं की संख्या के साथ तेजी से बढ़ती है, ताकि सभी समर्थित भाषाओं में (या कम से कम आपके द्वारा जोड़ा जाने वाला सब कुछ मान्य हो)। मैं यह नहीं कह रहा हूं कि यह असंभव है लेकिन इसका मतलब शायद कुछ अन्य भाषाओं के लिए समर्थन छोड़ देना होगा।
स्टीफन चेजालस

4
@ डायनोकॉस्ट, इसलिए यह सही ढंग से पहचान bash 3.2.53(1)-releaseकरता है कि दुभाषिया इसकी व्याख्या कर रहा है।
स्टीफन चेजलस

12

यह वही है जो मैं अपने .profile में उपयोग करता हूं उन प्रणालियों पर विभिन्न गोले की जांच करने के लिए जिन पर मैं काम करता हूं। यह ksh88 और ksh93 के बीच ठीक अंतर नहीं करता है, लेकिन इसने मुझे कभी विफल नहीं किया।

ध्यान दें कि इसके लिए एकल कांटा या पाइप की आवश्यकता नहीं है।

# Determine what (Bourne compatible) shell we are running under. Put the result
# in $PROFILE_SHELL (not $SHELL) so further code can depend on the shell type.

if test -n "$ZSH_VERSION"; then
  PROFILE_SHELL=zsh
elif test -n "$BASH_VERSION"; then
  PROFILE_SHELL=bash
elif test -n "$KSH_VERSION"; then
  PROFILE_SHELL=ksh
elif test -n "$FCEDIT"; then
  PROFILE_SHELL=ksh
elif test -n "$PS3"; then
  PROFILE_SHELL=unknown
else
  PROFILE_SHELL=sh
fi

1
ध्यान दें कि केवल बहुत हाल के संस्करण ksh93हैं $KSH_VERSION। वह चर से आता है pdkshऔर एटी एंड टी ksh88 से कभी नहीं बना।
स्टीफन चेजलस

सही है, यही वजह है कि मेरे पास दूसरा टेस्ट है FCEDIT
जेन्स

1
सही। ध्यान दें कि posh(अधिकांश गैर-पॉसिक्स सुविधाओं के साथ pdksh हटा दिया गया है ताकि आप शायद इसे "श" कहलाना चाहें) इसमें कोई FCEDIT नहीं है और न ही KSH_VERSION है, लेकिन इसमें PS3 (शायद लंबे समय तक नहीं है), हालांकि इसे एक लॉगिन शेल के रूप में रखने की संभावना नहीं है। । यह भी ध्यान रखें कि इसके बाद के संस्करण कोड है कि क्या प्रतिबिंबित नहीं होता bashया zshमें हैं shअनुकरण मोड है, जो एक समस्या हो सकती है यदि आप का उपयोग कर रहे $PROFILE_SHELLहैं या नहीं, इस या उस सुविधा को सक्षम करने का फैसला करने के। यह भी देखें कि स्वेन मैस्कैच का व्हाट्सएप अधिक आप जांचना चाहते हैं (या नहीं)।
स्टीफन चेज़लस

6

तुम कोशिश कर सकते हो

ps -o args= -p "$$"

जो आपको स्क्रिप्ट की पिड से जुड़ी कमांड का नाम देगा।


जब तक मैं बता सकता हूं, शेबंग का उपयोग करने पर काम नहीं करता है। sprunge.us/QeHD
क्रिस डाउन

क्षमा करें, @ क्रिसडाउन, फ्लॉप। मेरा बुरा, मैंने गलत तरीके से अनुवाद cmdकिया था commजब जवाब POSIXifying के लिए।
स्टीफन चेजलस

1

यदि lsofआपके सिस्टम पर कमांड उपलब्ध है, तो आप पेरेंट पीआईडी ​​प्राप्त करके psऔर उसके आउट होने के पार्स को प्राप्त करके पेरेंट शेल के पूर्ण पथ को प्राप्त कर सकते हैं lsof -p $ppid(देखें कि वर्तमान शेल कैसे काम कर रहा है? )।

#!/bin/sh
ppid="`ps -p "$$" -o ppid=`"
lsof -nP -p "$ppid" | awk 'NR==3 {print $NF; exit}'

अपने सिस्टम पर यह वापस लौटता है /, अगर मैं उपयोग करता NR==4हूं तो मुझे गोले माता-पिता के लिए रास्ता मिलता है।
थोर

ध्यान दें कि POSIX के shपास $PPIDचर है। पर Linux, आप उपयोग कर सकते हैं readlink -f "/proc/$PPID/exe"
स्टीफन चेजलस

1

लिनक्स भूमि के बाहर या / proc फाइल सिस्टम के लिए पहुँच की कमी या समान, आप pstree का उपयोग कर सकते हैं:

मान लिया कि आप के पास है

एक मैक पर:

./test.sh 
16012
-+= 00001 root /sbin/launchd
 \-+= 00245 wingwong /sbin/launchd
   \-+= 04670 wingwong /Applications/Utilities/Terminal.app/Contents/MacOS/Terminal -psn_0_2052597
     \-+= 11816 root login -pf wingwong
       \-+= 11817 wingwong -bash
         \-+= 16012 wingwong ksh ./test.sh
           \-+- 16013 wingwong pstree -p 16012

लिनक्स बॉक्स पर:

./test.sh 
14981
bash(14981)---pstree(14982)

Pstree से आउटपुट का प्रारूप और शैली आपके पर्यावरण के आधार पर भिन्न होती है, लेकिन आप ASCII आउटपुट और फिर sed / tr / awk / etc को लागू कर सकते हैं। स्क्रिप्ट चलाने वाले शेल को प्राप्त करने के लिए आउटपुट को फ़िल्टर करें।

तो एक साफ किया गया आउटपुट संस्करण (मैक या लिनक्स ओएस के लिए काम करता है):

#!/usr/bin/env sh
pstree  -p $$  | tr ' ()' '\012\012\012' | grep -i "sh$" | grep -v "$0" | tail -1

पैदावार पर:

./test.sh 
sh

और जब एक अलग शेल के साथ चलाया जाता है:

#!/usr/bin/env ksh
pstree  -p $$  | tr ' ()' '\012\012\012' | grep -i "sh$" | grep -v "$0" | tail -1

पैदावार:

./test.sh 
ksh

कोई रूट या विशेष फाइल सिस्टम की आवश्यकता नहीं है। ध्यान दें, मेरा फ़िल्टरिंग मानता है कि शेल बाइनरी नाम श के साथ समाप्त होता है और कोई मध्यवर्ती प्रविष्टियाँ नहीं होती हैं जो श के साथ समाप्त होती हैं। यह भी मानता है कि आपने अपनी स्क्रिप्ट "sh" या कुछ दुर्भाग्यपूर्ण grep पैटर्न का नाम नहीं दिया है जो जानकारी को अनपढ़ कर देगा। :) अपने स्वयं के वातावरण के लिए कुछ अनुकूलन की आवश्यकता होगी ताकि उच्च स्तर की मूर्खता सुनिश्चित हो सके।


-2

आप कमांड का उपयोग कर सकते हैं:

$ echo $SHELL

स्क्रिप्ट के भीतर से शेल का पता लगाने के लिए।


18
नंबर $SHELLउपयोगकर्ता की पसंद का खोल है। उपयोगकर्ता के लॉगिन शेल से आरंभिक। वर्तमान में चल रहे शेल से कोई लेना देना नहीं है।
स्टीफन चेजलस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.