如何测试终端中使用的shell?


69

如何检查终端中使用的shell?我在MacOS中使用的外壳是什么?


2
@xenoterracide:至少是unix.stackexchange.com/questions/3645/…。geekosaur的答案较为完整,因此我投票决定结束先前的问题。
吉尔斯

1
回显$ SHELL,不是吗?
innocent-world

@ innocent-world不,echo #SHELL不是吗。请参阅geekosaur答案中的#3 。
罗勒·布尔克

我不太确定“外壳”的定义是否明确。例如,您可能会运行,xterm -e /bin/cat 但我不满意调用/bin/catShell。
巴西尔·斯塔林凯维奇

同样,某些外壳程序(例如scsh)不使用POSIX shell语法。
巴西尔·斯塔林凯维奇

Answers:


71

从最可靠到最不可靠(以及最不重要)的几种方法:

  1. ps -p$$ -ocmd=。(在Solaris上,可能需要用fname代替cmd。在OSX和BSD上应该用command代替cmd。)
  2. 检查$BASH_VERSION$ZSH_VERSION以及其他特定壳的变量。
  3. 检查$SHELL; 这是不得已的方法,因为它指定了默认的 Shell,而不必指定当前的 Shell。

4
$0也要提吗?
Mikel

我不喜欢,$0因为它更复杂:(1)它可能只是基本名称,(2)可能在其前面带有“-”以将其指定为登录外壳。
geekosaur 2011年

ps -p$$ -ocmd=""更漂亮:-)
2011年

1
@geekosaur:也许是这样,但$0似乎比$SHELL:还有用:您不同意吗?您始终可以通过管道将sed其删除以删除“-”。
iconoclast

2
如果你正在运行tcsh$tcsh并且$version将被设置。这些是外壳变量,而不是环境变量。如果您运行的是非tcsh版本的csh,我认为没有任何明显的变量。当然,一方面,用于检查变量的语法在csh / tcsh和另一方面在sh / ksh / bash / zsh之间是不同的。
基思·汤普森

41

我发现以下内容可以在我的系统上安装的四个shell(bash,dash,zsh,csh)中起作用:

$ ps -p $$

以下内容适用于zsh,bash和破折号,但不适用于csh:

$ echo $0

2
对鱼也无效。
罗恩E

我认为@jiliagre的答案可能是我今天要使用的。在鱼上%self可以代替$$
Steven D

8

由于该问题要求使用所使用的外壳程序,并且不讨论传递给它的潜在参数,因此可以采用以下方法避免显示它们:

$ ps -o comm= -p $$
ksh93 

6

关于一些较轻便的实现(Android手机,busybox等)的注释:ps并不总是支持该-p开关,但是您可以使用来完成搜索ps | grep "^$$ "。(此grep正则表达式将唯一标识PID,因此不会出现误报。


7
ps | grep $$例如,如果您当前的流程存在1234并且存在某个流程,则仍然可以给出误报12345
基思·汤普森

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)

    这是唯一的选项,即使您位于脚本,源代码或终端中,也始终会得到与使用中的Shell解释器二进制文件链接相同的结果。

    警告您必须注意,这将显示最终二进制文件,因此ksh可能链接到ksh93或sh链接到bash。

/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

这给了我我当前的目录名;同样,在下面cshtcsh它给了我Ambiguous output redirect.
iconoclast 2015年

2

如果将其保存在环境变量中,则可以使用以下命令:

echo $SHELL

这很可能返回您登录shell的shell可执行文件的路径名。不能确定登录shell是您当前正在运行的。
库萨兰达

1

正在运行的shell的pid由var $$(在大多数shell中)给出。

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

使用反引号使jsh(Heirlomm shell)起作用。

在许多外壳中,直接测试是ps -o args= -p $$可行的,但busybox ash在此方面却失败了(解决)。

$1必须等于的支票$$会删除大多数误报。

最后一个;:用于使shell在ksh和zsh上运行。

在更多系统上进行测试会有所帮助,如果对您不起作用,请发表评论。

csh外壳类型中不起作用。


在OS / X上,在我的测试中,我至少获得3行,其中1行用于shell,1行用于/usr/lib/dyld,1行用于/private/var/db/dyld/dyld_shared_cache_x86_64
斯特凡Chazelas

是的,现在只选择位于/ bin和/ usr / bin中的条目
斯特凡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编程认为有害之类中所述,csh-style的shell不能2>/dev/null或。)>&2


-1

您可以简单地使用echo $0command来检查您正在使用哪个shell并<name_of_the_shell> --version检查shell的版本。(例如bash --version)。


史蒂文·D(Steven D)已经提到过它
:)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.