ฉันจะทดสอบเชลล์ที่ใช้ในเทอร์มินัลได้อย่างไร?


69

จะตรวจสอบว่าฉันใช้เชลล์ตัวไหนในเทอร์มินัล เชลล์ที่ฉันใช้ใน MacOS คืออะไร?


2
@xenoterracide: อย่างน้อยunix.stackexchange.com/questions/3645/... คำตอบของ geekosaur นั้นสมบูรณ์กว่าดังนั้นฉันจึงโหวตให้ปิดคำถามก่อนหน้านี้
Gilles

1
echo $ SHELL ไม่ใช่หรือ
โลกไร้เดียงสา

@ ผู้บริสุทธิ์ในโลกไม่echo #SHELLไม่ได้เป็นอย่างนั้น ดูอันดับ 3 ในคำตอบโดย geekosaur
Basil Bourque

ฉันไม่แน่ใจว่า "shell" มีความหมายที่ชัดเจน ตัวอย่างเช่นคุณอาจทำงานxterm -e /bin/cat แต่ฉันไม่มีความสุขที่จะเรียก/bin/catเชลล์
Basile Starynkevitch

นอกจากนี้เชลล์บางตัว (เช่นscsh ) อย่าใช้ POSIX เชลล์เช่นไวยากรณ์
Basile Starynkevitch

คำตอบ:


71

หลายวิธีจากมากไปน้อยเชื่อถือได้ (และมากไปน้อย):

  1. ps -p$$ -ocmd=. (บน Solaris สิ่งนี้อาจจำเป็นต้องใช้fnameแทนcmdบน OSX และ BSD ควรเป็นcommandแทนที่จะเป็นcmd)
  2. ตรวจสอบ$BASH_VERSION, $ZSH_VERSIONและตัวแปรเปลือกเฉพาะอื่น ๆ
  3. ตรวจสอบ$SHELL; นี่เป็นทางเลือกสุดท้ายเนื่องจากมันระบุเชลล์เริ่มต้นของคุณและไม่จำเป็นต้องเป็นเชลล์ปัจจุบัน

4
คุณควรพูดถึง$0เช่นกัน?
Mikel

ฉันไม่ชอบ$0เพราะมันซับซ้อนกว่า: (1) อาจเป็นเพียงชื่อฐาน (2) อาจมี '-' อยู่ด้านหน้าเพื่อระบุว่าเป็นเชลล์การเข้าสู่ระบบ
geekosaur

ps -p$$ -ocmd=""is prettier :-)
asoundmove

1
@geekosaur: อาจจะเป็นเช่นนั้น แต่$0ก็ดูเหมือนว่ามีประโยชน์มากกว่า$SHELL: คุณไม่เห็นด้วยไหม คุณสามารถไปป์ได้ตลอดsedเพื่อลบ '-'
iconoclast

2
หากคุณกำลังใช้tcsh, $tcshและ$versionจะถูกตั้งค่า นี่คือตัวแปรเชลล์ไม่ใช่ตัวแปรสภาพแวดล้อม หากคุณใช้เวอร์ชันที่ไม่ใช่ tcsh cshฉันไม่คิดว่าจะมีตัวแปรที่โดดเด่นใด ๆ และแน่นอนว่าไวยากรณ์ที่ใช้ในการตรวจสอบตัวแปรต่างกันระหว่าง csh / tcsh บนมือข้างหนึ่งและ sh / ksh / bash / zsh อีกด้านหนึ่ง
Keith Thompson

41

ฉันพบว่างานต่อไปนี้ในสี่เชลล์ที่ฉันติดตั้งบนระบบของฉัน (bash, dash, zsh, csh):

$ ps -p $$

การทำงานต่อไปนี้บน zsh, bash และ dash แต่ไม่ได้อยู่ใน csh:

$ echo $0

2
ยังไม่ทำงานกับปลา
Ron E

ฉันคิดว่าคำตอบของ @ jiliagre อาจเป็นไปได้ว่าฉันจะใช้ในวันนี้ ในปลา%selfสามารถใช้แทน$$
Steven D

8

เมื่อคำถามถามถึงเชลล์ที่ใช้และไม่ได้พูดถึงข้อโต้แย้งที่อาจเกิดขึ้นผ่านไปนี่เป็นวิธีที่หลีกเลี่ยงการแสดง:

$ ps -o comm= -p $$
ksh93 

6

หมายเหตุเกี่ยวกับการใช้งานที่เบากว่า (โทรศัพท์ Android, busybox ฯลฯ ): psไม่ได้รับการสนับสนุนสำหรับ-pสวิตช์เสมอไป แต่คุณสามารถค้นหาได้ด้วยคำสั่งเช่นps | grep "^$$ "นั้น ( grepregex นี้จะระบุ PID ที่ไม่ซ้ำกันดังนั้นจะไม่มีผลบวกใด ๆ


7
ps | grep $$ยังคงสามารถให้ผลบวกปลอมตัวอย่างเช่นถ้ากระบวนการปัจจุบันของคุณและมีกระบวนการ1234 12345
Keith Thompson

4

มีสองวิธีที่ง่ายจริงๆ:

  • ใช้คำสั่งps :

    ps -o comm= $$

    หรือ

    ps -h -o comm -p $$

    ที่อยู่:

    • -hหรือจบตัวเลือกทั้งหมดด้วย=การไม่แสดงส่วนหัวใด ๆ
    • -o commสำหรับแสดงเฉพาะชื่อกระบวนการ ( bashแทน/bin/bash)
    • -p <PID> รายการเท่านั้นดำเนินการกับรายการแบบฟอร์ม PID ที่ให้มา
  • การใช้ระบบไฟล์หลอกข้อมูลกระบวนการ/ proc :

    cat /proc/$$/comm

    ตัวเลือกนี้ทำงานตรงตามpsคำสั่งด้านบน

    หรือ

    readlink /proc/$$/exe

    /proc/PID/exeลิงก์นี้ไปยังไฟล์ที่กำลังดำเนินการซึ่งในกรณีนี้จะชี้ไปที่ / bin / bash, / bin / ksh ฯลฯ

    เพื่อให้ได้ชื่อของเชลล์ที่คุณสามารถใช้ได้

    basename $(readlink /proc/$$/exe)

    นี่เป็นตัวเลือกเดียวที่จะให้ผลลัพธ์เดียวกันเสมอแม้ว่าคุณจะอยู่ในสคริปต์รหัสที่มาหรือเทอร์มินัลเป็นลิงก์ไปยังไบนารีของตัวแปลเชลล์ที่ใช้งานอยู่

    คำเตือนคุณต้องระวังว่าสิ่งนี้จะแสดงไบนารีที่ดีที่สุดดังนั้น ksh อาจเชื่อมโยงกับ ksh93 หรือ sh เพื่อทุบตี

การใช้งาน/procมีประโยชน์จริง ๆ ผ่านทาง/proc/selfซึ่งเชื่อมโยงไปยัง PID ของคำสั่งปัจจุบัน


3

การผสมผสานของคำตอบอื่น ๆ ทั้งหมดเข้ากันได้กับ Mac (comm), Solaris (fname) และ Linux (cmd):

ps -p$$ -o cmd="",comm="",fname="" 2>/dev/null | sed 's/^-//' | grep -oE '\w+' | head -n1

สิ่งนี้ทำให้ฉันชื่อไดเรกทอรีปัจจุบันของฉัน; นอกจากนี้ภายใต้cshและtcshมันให้ฉันAmbiguous output redirect.
iconoclast

2

หากคุณบันทึกไว้ในตัวแปรสภาพแวดล้อมของคุณคุณสามารถใช้สิ่งต่อไปนี้:

echo $SHELL

ซึ่งน่าจะส่งคืนชื่อพา ธ ของเชลล์ที่สามารถเรียกใช้งานได้ของเชลล์ล็อกอินของคุณ ไม่แน่ใจว่าล็อกอินเชลล์คืออะไรในขณะนี้
Kusalananda

1

pid ของเชลล์ที่รันอยู่จะได้รับจาก var $$ (ในเชลล์ส่วนใหญ่)

whichsh="`ps -o pid,args| awk '$1=='"$$"'{print $2}'`"
echo "$whichsh"

การใช้ backticks เพื่อทำให้ jsh (เชลล์ Heirlomm) ทำงานได้

ในหลาย ๆ เชลล์การทดสอบโดยตรงของps -o args= -p $$งาน แต่busybox ashล้มเหลวในเรื่องนั้น (แก้ไข)

การตรวจสอบที่$1จะต้องเท่ากับการ$$ลบบวกปลอมมากที่สุด

อันสุดท้าย;:ถูกใช้เพื่อให้เชลล์รันสำหรับ ksh และ zsh

การทดสอบระบบเพิ่มเติมจะช่วยได้โปรดแสดงความคิดเห็นหากไม่ได้ผลสำหรับคุณ

ไม่ทำงานในcshประเภทของกระสุน


ใน OS / X ในการทดสอบของฉันฉันได้รับอย่างน้อย 3 บรรทัดหนึ่งรายการสำหรับเชลล์หนึ่งรายการสำหรับ/usr/lib/dyldหนึ่ง/private/var/db/dyld/dyld_shared_cache_x86_64รายการ
Stéphane Chazelas

ใช่ตอนนี้จะเลือกเฉพาะรายการใน / bin และ / usr / bin
Stéphane Chazelas

@ StéphaneChazelasบางทีตอนนี้มันดีกว่าไหม?

0

ฉันตั้งค่า$MYSHELLสำหรับการทดสอบในอนาคตในผู้ไม่เชื่อเรื่องพระเจ้าเปลือกของฉัน~/.aliases:

unset MYSHELL
if [ -n "$ZSH_VERSION" ] && type zstyle >/dev/null 2>&1; then        # zsh
  MYSHELL=`command -v zsh`
elif [ -x "$BASH" ] && shopt -q >/dev/null 2>&1; then                # bash
  MYSHELL=`command -v bash`
elif [ -x "$shell" ] && which setenv |grep builtin >/dev/null; then  # tcsh
  echo "DANGER: this script is likely not compatible with C shells!"
  sleep 5
  setenv MYSHELL "$shell"
fi

# verify
if [ ! -x "$MYSHELL" ]; then
  MYSHELL=`command -v "$(ps $$ |awk 'NR == 2 { print $NF }')"`
  [ -x "$MYSHELL" ] || MYSHELL="${SHELL:-/bin/sh}"  # default if verify fails
fi

tcshส่วนมีแนวโน้มที่จะไม่ฉลาดที่จะม้วนเป็นสคริปต์ POSIX สไตล์ตั้งแต่มันจึงแตกต่างกันอย่างสิ้นเชิง (ดังนั้นคำเตือนและห้าวินาที) (สำหรับหนึ่งcsh- กระสุนสไตล์ไม่สามารถทำได้2>/dev/nullหรือ>&2ตามที่ระบุไว้ในการเขียนโปรแกรม Csh ที่มีชื่อเสียงถือว่าเป็นคำพูดที่เป็นอันตราย )


-1

คุณสามารถใช้echo $0คำสั่งเพื่อตรวจสอบว่าคุณใช้เชลล์ตัวใดและ<name_of_the_shell> --versionตรวจสอบเวอร์ชั่นของเชลล์ (เช่น. bash --version)


Steven D พูดถึงมันแล้ว
:)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.