मैं जिस वर्तमान शेल पर काम कर रहा हूं, उसका निर्धारण कैसे कर सकता हूं?
क्या ps
अकेले कमांड का आउटपुट पर्याप्त होगा?
यह यूनिक्स के विभिन्न स्वादों में कैसे किया जा सकता है?
मैं जिस वर्तमान शेल पर काम कर रहा हूं, उसका निर्धारण कैसे कर सकता हूं?
क्या ps
अकेले कमांड का आउटपुट पर्याप्त होगा?
यह यूनिक्स के विभिन्न स्वादों में कैसे किया जा सकता है?
जवाबों:
नाम खोजने के लिए तीन दृष्टिकोण हैंवर्तमान शेल के निष्पादन योग्य का :
कृपया ध्यान दें कि शेल के निष्पादन योग्य होने पर सभी तीन दृष्टिकोणों को मूर्ख बनाया जा सकता है /bin/sh
, लेकिन यह वास्तव में एक नया नाम हैbash
, उदाहरण के लिए (जो अक्सर होता है)।
इस प्रकार आपका दूसरा सवाल यह है कि क्या ps
आउटपुट " हमेशा नहीं " के साथ उत्तर दिया जाएगा ।
echo $0
- प्रोग्राम का नाम प्रिंट करेगा ... जो कि शेल के मामले में वास्तविक शेल है।
ps -ef | grep $$ | grep -v grep
- यह चल रही प्रक्रियाओं की सूची में वर्तमान प्रक्रिया आईडी के लिए दिखेगा। चूंकि वर्तमान प्रक्रिया शेल है, इसलिए इसे शामिल किया जाएगा।
यह 100% विश्वसनीय नहीं है, क्योंकि आपके पास अन्य प्रक्रियाएं हो सकती हैं जिनकी ps
सूची में शेल की प्रक्रिया आईडी के समान संख्या शामिल है, खासकर यदि वह आईडी एक छोटी संख्या है (उदाहरण के लिए, यदि शेल की पीआईडी "5" है, तो आप प्रक्रियाएं कह सकते हैं। एक ही grep
आउटपुट में "java5" या "perl5" ! शेल नाम पर भरोसा करने में सक्षम नहीं होने के शीर्ष पर "पीएस" दृष्टिकोण के साथ यह दूसरी समस्या है।
echo $SHELL
- वर्तमान शेल का पथ SHELL
किसी भी शेल के लिए चर के रूप में संग्रहीत किया जाता है । इस के लिए चेतावनी यह है कि यदि आप एक शेल को स्पष्ट रूप से एक उपप्रकार के रूप में लॉन्च करते हैं (उदाहरण के लिए, यह आपका लॉगिन शेल नहीं है), तो आपको इसके बजाय अपने लॉगिन शेल का मान मिलेगा। यदि यह एक संभावना है, ps
या $0
दृष्टिकोण का उपयोग करें ।
यदि, हालांकि, निष्पादन योग्य आपके वास्तविक शेल से मेल नहीं खाता (जैसे /bin/sh
कि वास्तव में बैश या ksh है), तो आपको हेयुरिस्टिक्स की आवश्यकता है। यहाँ विभिन्न गोले के लिए विशिष्ट कुछ पर्यावरणीय चर दिए गए हैं:
$version
tcsh पर सेट किया गया है
$BASH
बैश पर सेट है
$shell
(लोअरकेस) को csh या tsh में वास्तविक शेल नाम पर सेट किया जाता है
$ZSH_NAME
zsh पर सेट है
ksh के पास $PS3
और $PS4
सेट है, जबकि सामान्य बॉर्न शेल ( sh
) में केवल $PS1
और $PS2
सेट है। यह आम तौर पर की तरह लगता है सबसे मुश्किल भेद करने के लिए - केवल के बीच वातावरण चर के पूरे सेट में अंतर sh
और ksh
हम सोलारिस बंध पर स्थापित किया है $ERRNO
, $FCEDIT
, $LINENO
, $PPID
, $PS3
, $PS4
, $RANDOM
, $SECONDS
, और $TMOUT
।
echo ${.sh.version}
"खराब प्रतिस्थापन" लौटाता है। ऊपर मेरा समाधान देखें
ps -ef | grep …
... यह 100% के रूप में विश्वसनीय नहीं है ..." के माध्यम से एक सरल नियमित अभिव्यक्ति का उपयोग करना egrep
या grep -e
आसानी से सभी-इरादों और उद्देश्यों के लिए 100% तक विश्वसनीयता ला सकता है ps -ef | egrep "^\s*\d+\s+$$\s+"
:। ^
बनाता है यकीन है कि हम लाइन की शुरुआत से शुरू कर रहे हैं, \d+
यूआईडी को खाती है, $$
पीआईडी से मेल खाता है, और \s*
और \s+
खाते के लिए और अन्य भागों के बीच खाली स्थान के करता है।
ps -ef | awk '$2==pid' pid=$$
ps -p $$
कहीं भी काम करना चाहिए जिसमें शामिल समाधान ps -ef
और grep
करते हैं (किसी भी यूनिक्स संस्करण पर जो पोसिक्स विकल्पोंps
का समर्थन करता है ) और अंकों के अनुक्रम के लिए grepping द्वारा प्रस्तुत झूठी सकारात्मकता से ग्रस्त नहीं होंगे जो कहीं और दिखाई दे सकते हैं।
ps
जो -p
आपको समझ में नहीं आ सकते हैं इसलिए आपको उपयोग करने की आवश्यकता हो सकती है /bin/ps -p $$
।
$$
, सिवाय के लिए fish
जिसके साथ आप उपयोग करने के लिए होगा ps -p %self
।
/bin/ps
। ps
आसानी से (वास्तव में यह आजकल काफी सामान्य है) में स्थापित किया जा सकता है /usr/bin
। $(which ps) -p $$
एक बेहतर तरीका है। बेशक, यह मछली में काम नहीं करेगा, और संभवतः कुछ अन्य गोले। मुझे लगता है कि यह (which ps) -p %self
मछली में है।
readlink /proc/$$/exe
sh
द्वारा अनुकरण किया जाता है bash
, तो ps -p आपको /usr/bin/bash
यहां तक कि आप इसे चलाते हैंsh
प्रयत्न
ps -p $$ -oargs=
या
ps -p $$ -ocomm=
ps -o fname --no-headers $$
।
test `ps -p $$ -ocomm=` == "bash" && do_something_that_only_works_in_bash
। (मेरी लिपि में अगली पंक्ति csh के बराबर है।)
-q
इसके बजाय का उपयोग करता हूं -p
:SHELL=$(ps -ocomm= -q $$)
यदि आप केवल यह सुनिश्चित करना चाहते हैं कि उपयोगकर्ता बैश के साथ एक स्क्रिप्ट का उपयोग कर रहा है:
if [ ! -n "$BASH" ] ;then echo Please run this script $0 with bash; exit 1; fi
#!/bin/bash
: if [ ! -n "$BASH" ] ;then exec bash $0; fi
। इस लाइन के साथ स्क्रिप्ट को bash का उपयोग करके चलाया जाता है, भले ही ksh या sh का उपयोग शुरू किया गया हो। मेरे उपयोग के मामले में कमांड लाइन तर्क की आवश्यकता नहीं है, लेकिन $0
यदि आवश्यक हो तो उन्हें जोड़ा जा सकता है।
तुम कोशिश कर सकते हो:
ps | grep `echo $$` | awk '{ print $4 }'
या:
echo $SHELL
/pattern/ { action }
करेंगे?
$SHELL
पर्यावरण चर में एक शेल होता है, जिसे वर्तमान उपयोगकर्ता के लिए डिफ़ॉल्ट रूप से कॉन्फ़िगर किया गया है। यह एक शेल को प्रतिबिंबित नहीं करता है, जो वर्तमान में चल रहा है। ps -p $$
झूठी सकारात्मकता के कारण $ $ का उपयोग करना बेहतर है ।
awk
,ps | awk '$1=='$$' { n=split($4,a,"/"); print a[n] }'
$SHELL
हमेशा वर्तमान शेल दिखाने की आवश्यकता नहीं है। यह केवल डिफ़ॉल्ट शेल को लागू करने के लिए दर्शाता है।
उपरोक्त परीक्षण करने के लिए, मान लेंbash
कि डिफ़ॉल्ट शेल है, कोशिश करें echo $SHELL
, और फिर उसी टर्मिनल में, उदाहरण के लिए कुछ अन्य शेल ( KornShell (ksh)) में जाएं और प्रयास करें $SHELL
। आप परिणाम को दोनों मामलों में बैश के रूप में देखेंगे।
वर्तमान शेल का नाम पाने के लिए, का उपयोग करें cat /proc/$$/cmdline
। और शेल द्वारा निष्पादन योग्य पथ readlink /proc/$$/exe
।
/proc
।
वर्तमान शेल को खोजने के लिए मेरे पास एक सरल चाल है। बस एक यादृच्छिक स्ट्रिंग टाइप करें (जो एक कमांड नहीं है)। यह विफल हो जाएगा और "नहीं मिली" त्रुटि लौटाएगा, लेकिन लाइन के प्रारंभ में यह कहेगा कि यह कौन सा शेल है:
ksh: aaaaa: not found [No such file or directory]
bash: aaaaa: command not found
echo 'aaaa' > script; chmod +x script; ./script
देता है./script.sh: 1: aaaa: not found
निम्नलिखित हमेशा उपयोग किए जाने वाले वास्तविक शेल को देगा - इसे वास्तविक निष्पादन योग्य का नाम मिलता है, न कि शेल नाम (अर्थात , आदि के ksh93
बजाय ksh
)। के लिए /bin/sh
, यह वास्तविक शेल का उपयोग करेगा, अर्थात dash
।
ls -l /proc/$$/exe | sed 's%.*/%%'
मुझे पता है कि कई ऐसे हैं जो कहते हैं कि ls
आउटपुट को कभी संसाधित नहीं किया जाना चाहिए, लेकिन आपके द्वारा उपयोग किए जा रहे शेल में क्या संभावना है कि इसे विशेष वर्णों के साथ नाम दिया गया है या विशेष वर्णों के साथ नामित निर्देशिका में रखा गया है? यदि यह अभी भी है, तो इसे अलग तरीके से करने के कई अन्य उदाहरण हैं।
जैसा कि टोबी स्पाइट द्वारा बताया गया है , यह उसी को प्राप्त करने का एक अधिक उचित और क्लीनर तरीका होगा:
basename $(readlink /proc/$$/exe)
/proc
। दुनिया के सभी लिनक्स बॉक्स नहीं।
basename $(readlink /proc/$$/exe)
को प्राथमिकता देंगे । ls
sed
echo
ash -> /bin/busybox
, यह / बिन / व्यस्त बॉक्स देगा।
मैंने कई अलग-अलग तरीकों की कोशिश की है और मेरे लिए सबसे अच्छा है:
ps -p $$
यह साइगविन के तहत भी काम करता है और पीआईडी ग्रेपिंग के रूप में झूठी सकारात्मकता उत्पन्न नहीं कर सकता है। कुछ सफाई के साथ, यह सिर्फ एक निष्पादन योग्य नाम (पथ के साथ Cygwin के तहत) आउटपुट करता है:
ps -p $$ | tail -1 | awk '{print $NF}'
आप एक समारोह बना सकते हैं ताकि आपको इसे याद रखने की आवश्यकता न हो:
# Print currently active shell
shell () {
ps -p $$ | tail -1 | awk '{print $NF}'
}
... और फिर अमल करें shell
।
यह डेबियन और साइगविन के तहत परीक्षण किया गया था।
ps
, tail
और gawk
, cmd परिभाषित नहीं करता है $$
क्योंकि यह PID है तो यह निश्चित रूप से सादे cmd के तहत काम नहीं कर सकता है।
ps -p$$ -o comm=
? POSIX का कहना है कि सभी हेडर को निर्दिष्ट करने से हेडर पूरी तरह से दब जाता है। ps
जब हम एक सीधे निष्पादित स्क्रिप्ट (जैसे #!/bin/sh
) द्वारा सॉर्ट किए जाते हैं तब भी हम (सभी उत्तरों की तरह ) विफल हो रहे हैं ।
मूल प्रक्रिया को मुद्रित करने पर मेरा प्रकार:
ps -p $$ | awk '$1 == PP {print $4}' PP=$$
जब AWK आपके लिए यह कर सकता है तो अनावश्यक एप्लिकेशन न चलाएं।
awk
, ps -p "$$" -o 'comm='
यह आपके लिए कब हो सकता है?
शेल और इसके संबंधित संस्करण का पता लगाने के कई तरीके हैं। यहाँ कुछ हैं जो मेरे लिए काम किया है।
सरल
Hackish दृष्टिकोण
$> ******* (यादृच्छिक अक्षरों का एक सेट टाइप करें और आउटपुट में आपको शेल नाम मिलेगा। मेरे मामले में -बेश: Chapter2-a-sample-isomorphic-app: कमांड नहीं मिला )
बशर्ते कि आपका /bin/sh
POSIX मानक का समर्थन करता है और आपके सिस्टम में lsof
कमांड स्थापित है - lsof
इस मामले में हो सकने वाला एक संभावित विकल्प pid2path
- आप निम्न स्क्रिप्ट का उपयोग (या अनुकूलन) कर सकते हैं जो पूर्ण पथ प्रिंट करता है:
#!/bin/sh
# cat /usr/local/bin/cursh
set -eu
pid="$$"
set -- sh bash zsh ksh ash dash csh tcsh pdksh mksh fish psh rc scsh bournesh wish Wish login
unset echo env sed ps lsof awk getconf
# getconf _POSIX_VERSION # reliable test for availability of POSIX system?
PATH="`PATH=/usr/bin:/bin:/usr/sbin:/sbin getconf PATH`"
[ $? -ne 0 ] && { echo "'getconf PATH' failed"; exit 1; }
export PATH
cmd="lsof"
env -i PATH="${PATH}" type "$cmd" 1>/dev/null 2>&1 || { echo "$cmd not found"; exit 1; }
awkstr="`echo "$@" | sed 's/\([^ ]\{1,\}\)/|\/\1/g; s/ /$/g' | sed 's/^|//; s/$/$/'`"
ppid="`env -i PATH="${PATH}" ps -p $pid -o ppid=`"
[ "${ppid}"X = ""X ] && { echo "no ppid found"; exit 1; }
lsofstr="`lsof -p $ppid`" ||
{ printf "%s\n" "lsof failed" "try: sudo lsof -p \`ps -p \$\$ -o ppid=\`"; exit 1; }
printf "%s\n" "${lsofstr}" |
LC_ALL=C awk -v var="${awkstr}" '$NF ~ var {print $NF}'
-i
(-> पर्यावरण को अनदेखा) विकल्प के env
कारण लाइन में जहाँ आप lsof
उपलब्ध होने के लिए जाँच करते हैं। यह विफल रहता है: env -i PATH="${PATH}" type lsof
->env: ‘type’: No such file or directory
यदि आप बस यह जांचना चाहते हैं कि आप (बैश का एक विशेष संस्करण) चला रहे हैं, तो ऐसा करने का सबसे अच्छा तरीका $BASH_VERSINFO
सरणी चर का उपयोग करना है। एक (केवल पढ़ने के लिए) सरणी चर के रूप में इसे पर्यावरण में सेट नहीं किया जा सकता है, इसलिए आप यह सुनिश्चित कर सकते हैं कि यह (यदि सभी में) चालू शेल से आ रहा है।
हालाँकि, जब बैश को एक अलग व्यवहार किया जाता है sh
, जैसा कि आपको बताया जाता है , तो आपको $BASH
पर्यावरण के चर के साथ समाप्त होने की भी जाँच करने की आवश्यकता है /bash
।
एक स्क्रिप्ट में मैंने लिखा था कि -
अंडरस्कोर (नहीं अंडरस्कोर) के साथ फ़ंक्शन नामों का उपयोग करता है , और साहचर्य सरणियों पर निर्भर करता है (बैश 4 में जोड़ा गया), मेरे पास निम्नलिखित सैनिटरी चेक (सहायक उपयोगकर्ता त्रुटि संदेश के साथ) है:
case `eval 'echo $BASH@${BASH_VERSINFO[0]}' 2>/dev/null` in
*/bash@[456789])
# Claims bash version 4+, check for func-names and associative arrays
if ! eval "declare -A _ARRAY && func-name() { :; }" 2>/dev/null; then
echo >&2 "bash $BASH_VERSION is not supported (not really bash?)"
exit 1
fi
;;
*/bash@[123])
echo >&2 "bash $BASH_VERSION is not supported (version 4+ required)"
exit 1
;;
*)
echo >&2 "This script requires BASH (version 4+) - not regular sh"
echo >&2 "Re-run as \"bash $CMD\" for proper operation"
exit 1
;;
esac
आप पहले मामले में सुविधाओं के लिए कुछ हद तक पागल कार्यात्मक जांच को छोड़ सकते हैं, और बस यह मान लें कि भविष्य के बैश संस्करण संगत होंगे।
कोई भी उत्तर fish
शेल के साथ काम नहीं करता है (इसमें चर नहीं हैं $$
या $0
)।
मेरे लिए यह काम करता है (पर परीक्षण किया sh
, bash
, fish
, ksh
, csh
, true
, tcsh
, और zsh
, openSUSE 13.2):
ps | tail -n 4 | sed -E '2,$d;s/.* (.*)/\1/'
यह कमांड एक स्ट्रिंग को आउटपुट करता है जैसे bash
। यहाँ मैं केवल उपयोग कर रहा हूँ ps
, tail
और sed
(जीएनयू extesions के बिना, जोड़ने की कोशिश --posix
यह जाँच करने के लिए)। वे सभी मानक POSIX कमांड हैं। मुझे यकीन है कि tail
हटाया जा सकता है, लेकिन sed
ऐसा करने के लिए मेरा फू इतना मजबूत नहीं है।
यह मुझे लगता है, कि यह समाधान बहुत पोर्टेबल नहीं है क्योंकि यह ओएस एक्स पर काम नहीं करता है। :(
sed: invalid option -- 'E'
बैश 3.2.51 और tcsh 6.15.00
मेरा समाधान:
ps -o command | grep -v -e "\<ps\>" -e grep -e tail | tail -1
यह विभिन्न प्लेटफार्मों और गोले में पोर्टेबल होना चाहिए। यह ps
अन्य समाधानों की तरह उपयोग करता है , लेकिन यह निर्भर नहीं करता है sed
या awk
पाइपिंग से जंक को फ़िल्टर करता है और ps
खुद को खोल देता है ताकि शेल हमेशा अंतिम प्रविष्टि हो। इस तरह हमें गैर-पोर्टेबल पीआईडी वैरिएबल पर निर्भर होने या सही लाइनों और कॉलम को चुनने की आवश्यकता नहीं है।
मैंने बैश, जेड शेल ( zsh
) के साथ डेबियन और मैकओएस पर परीक्षण किया है , और मछली (जो विशेष रूप से मछली के लिए अभिव्यक्ति को बदलने के बिना इनमें से अधिकांश समाधानों के साथ काम नहीं करता है, क्योंकि यह एक अलग पीआईडी चर का उपयोग करता है)।
echo $$ # Gives the Parent Process ID
ps -ef | grep $$ | awk '{print $8}' # Use the PID to see what the process is.
grep $$
अविश्वसनीय है। ps -ef | awk -v pid=$$ '$2==pid { print $8 }'
बेहतर है, लेकिन सिर्फ उपयोग क्यों नहीं ps -p $$
?
Mac OS X (और FreeBSD) पर:
ps -p $$ -axco command | sed -n '$p'
zsh
, और यह मुझे दिया -bash
।
mutt
...: -बी
"पीएस" के आउटपुट से ग्रेपिंग पीआईडी की आवश्यकता नहीं है, क्योंकि आप / खरीद संरचना से किसी भी पीआईडी के लिए संबंधित कमांड लाइन पढ़ सकते हैं:
echo $(cat /proc/$$/cmdline)
हालाँकि, यह किसी भी तरह से बेहतर नहीं हो सकता है:
echo $0
नाम की तुलना में वास्तव में एक अलग शेल चलाने के बारे में, एक विचार यह है कि आपको पहले प्राप्त नाम का उपयोग करके शेल से संस्करण का अनुरोध करना है:
<some_shell> --version
sh
बाहर निकलने के कोड 2 के साथ विफल होने के लिए लगता है जबकि अन्य कुछ उपयोगी देते हैं (लेकिन मैं सभी को सत्यापित करने में सक्षम नहीं हूं क्योंकि मेरे पास नहीं है):
$ sh --version
sh: 0: Illegal option --
echo $?
2
यह बहुत साफ समाधान नहीं है, लेकिन यह वही करता है जो आप चाहते हैं।
# MUST BE SOURCED..
getshell() {
local shell="`ps -p $$ | tail -1 | awk '{print $4}'`"
shells_array=(
# It is important that the shells are listed in descending order of their name length.
pdksh
bash dash mksh
zsh ksh
sh
)
local suited=false
for i in ${shells_array[*]}; do
if ! [ -z `printf $shell | grep $i` ] && ! $suited; then
shell=$i
suited=true
fi
done
echo $shell
}
getshell
अब आप उपयोग कर सकते हैं $(getshell) --version
।
यह काम करता है, हालांकि, केवल कोर्नशेल -जैसे गोले (ksh) पर।
dash
, yash
आदि आम तौर पर अगर आप उपयोग कर रहे हैं bash
, zsh
, ksh
, जो कुछ भी - आप इस तरह की चीजों के बारे में परवाह नहीं करनी चाहिए।
ksh
सुविधाओं का एक सेट ज्यादातर सुविधाओं का एक सबसेट bash
है (यह पूरी तरह से जाँच नहीं की है)।
यह जानने के लिए कि क्या आपका शेल डैश / बैश का उपयोग कर रहा है, निम्नलिखित करें।
ls –la /bin/sh
:
यदि परिणाम /bin/sh -> /bin/bash
==> है तो आपका शेल बैश का उपयोग कर रहा है।
यदि परिणाम /bin/sh ->/bin/dash
==> तो आपका शेल डैश का उपयोग कर रहा है।
यदि आप बैश से डैश या इसके विपरीत बदलना चाहते हैं, तो नीचे दिए गए कोड का उपयोग करें:
ln -s /bin/bash /bin/sh
(बैश को शेल बदलें)
नोट : यदि उपरोक्त कमांड में यह कहते हुए त्रुटि है, कि / bin / sh पहले से मौजूद है, / bin / sh को हटा दें और पुनः प्रयास करें।
कृपया नीचे दिए गए आदेश का उपयोग करें:
ps -p $$ | tail -1 | awk '{print $4}'
echo $SHELL
वह करता है जो आप करने की कोशिश कर रहे हैं और इसे अच्छी तरह से करते हैं। दूसरा भी अच्छा नहीं है, क्योंकि $SHELL
पर्यावरण चर में वर्तमान उपयोगकर्ता के लिए डिफ़ॉल्ट शेल होता है, वर्तमान में चल रहे शेल में नहीं। अगर मुझे उदाहरण के लिए bash
डिफ़ॉल्ट शेल के रूप में सेट करना है, तो निष्पादित करें zsh
और echo $SHELL
, इसे प्रिंट करेंगे bash
।
echo $SHELL
बकवास हो सकता है: ~ $ echo $SHELL /bin/zsh ~ $ bash bash-4.3$ echo $SHELL /bin/zsh bash-4.3$
यह Red Red Linux (RHEL), macOS , BSD और कुछ AIXes पर अच्छा काम करता है :
ps -T $$ | awk 'NR==2{print $NF}'
वैकल्पिक रूप से, निम्नलिखित को भी काम करना चाहिए यदि pstree उपलब्ध है,
pstree | egrep $$ | awk 'NR==2{print $NF}'
!
प्रतिस्थापन करता है ?) संभवतः शेल के नाम को खोजने की तुलना में अधिक पोर्टेबल है। स्थानीय रिवाज हो सकता है कि आप कुछ नाम/bin/sh
रख लें, जो वास्तव में राख, पानी का छींटा, बैश आदि हो सकता है