时间:2010-07-24 21:35:28

标签: bash unix shell csh tcsh

27 个答案:

答案 0 :(得分:706)

答案 1 :(得分:85)

答案 2 :(得分:35)

尝试

ps -p $$ -oargs=

ps -p $$ -ocomm=

答案 3 :(得分:23)

如果您只是想确保用户使用bash调用脚本:

if [ ! -n "$BASH" ] ;then echo Please run this script $0 with bash; exit 1; fi

答案 4 :(得分:19)

答案 5 :(得分:11)

$SHELL无需始终显示当前的shell。它只反映了要调用的默认shell。

要测试上述内容,Say bash是默认shell,请尝试echo $SHELL,然后在同一个终端中,进入其他shell(例如ksh)并尝试$SHELL,在这两种情况下,你都会看到结果为bash。

要获取当前shell的名称,请使用cat /proc/$$/cmdline以及readlink /proc/$$/exe

可执行shell的路径

答案 6 :(得分:9)

答案 7 :(得分:8)

我有一个简单的技巧来找到当前的shell。只需键入随机字符串(不是命令)。它将失败并返回"未找到"错误,但在行的开头,它将说明它是哪个shell:

ksh: aaaaa: not found [No such file or directory]
bash: aaaaa: command not found

答案 8 :(得分:7)

这将始终给出实际使用的shell - 获取实际可执行文件的名称而不是shell名称(即ksh93而不是ksh等。)/bin/sh将显示实际使用的shell:ie dash

ls -l /proc/$$/exe | sed 's%.*/%%'

我知道有很多人说ls输出应该是新处理的,但是你有一个使用特殊字符命名的shell或者放在一个用特殊字符命名的目录中的概率是多少?如果仍然是这种情况,这里还有很多其他的例子。不同的。

答案 9 :(得分:4)

我尝试了很多不同的方法,对我来说最好的方法是:

ps -p $$

它也可以在 Cygwin 下工作,并且不会产生误报作为PID grepping。通过一些清理,它只输出一个可执行文件名称(在带有路径的 Cygwin 下):

ps -p $$ | tail -1 | awk '{print $NF}'

您可以创建一个功能,这样您就不必记住它:

# print currently active shell
shell () {
  ps -p $$ | tail -1 | awk '{print $NF}'
}

...然后只执行shell

在Debian和Cygwin下测试。

答案 10 :(得分:4)

我打印父进程的变体。

ps -p $$ | awk '$1 == PP {print $4}' PP=$$

为什么运行不必要的应用程序,'awk'可以为你做什么?

答案 11 :(得分:3)

如果您的/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}'

答案 12 :(得分:2)

答案 13 :(得分:1)

我特别喜欢 Nahuel Fouilleul 的解决方案,但我必须在带有内置 Bash shell 的 Ubuntu 18.04 上运行它的以下变体:

bash -c 'shellPID=$$; ps -ocomm= -q $shellPID'

没有临时变量 shellPID,例如以下内容:

bash -c 'ps -ocomm= -q $$'

只会为我输出 ps。也许你们不是都在使用非交互模式,这会有所作为吗?

答案 14 :(得分:1)

请执行以下操作,了解您的Shell是否使用DASH / BASH。

1) ls -la / bin / sh , 如果结果是 / bin / sh - > / bin / bash ==>然后你的shell使用BASH。

如果结果是 / bin / sh - > / bin / dash ==>然后你的shell正在使用DASH。

如果您想从BASH更改为DASH,反之亦然,请使用以下代码 ln -s / bin / bash / bin / sh (将shell更改为BASH)

注意:如果上述命令导致错误,/ bin / sh已存在,请删除/ bin / sh并重试。

答案 15 :(得分:1)

有很多方法可以找到shell及其相应的版本。这里有一些对我有用。

直接前进

  1. $> echo $ 0 (给你程序名称。在我的情况下,输出是 -bash
  2. $> $ SHELL (这会带您进入shell,并在提示符中获取shell名称和版本。在我的情况下 bash3.2 $
  3. $> echo $ SHELL (这将为您提供可执行路径。在我的情况下 / bin / bash
  4. $> $ SHELL --version (这将提供有关许可证类型的shell软件的完整信息)
  5. Hackish方法

    $> *******(键入一组随机字符,在输出中你将获得shell名称。在我的情况下 -bash:chapter2-a-sample-isomorphic-app:command not found

答案 16 :(得分:1)

没有一个答案适用于fish shell(它没有变量$$$0)。

这适用于我(在shbashfishkshcshtrue,{{1}上测试}和tcsh; openSUSE 13.2):

zsh

此命令输出类似ps | tail -n 4 | sed -E '2,$d;s/.* (.*)/\1/' 的字符串。我在这里只使用bashpstail(没有GNU extes;尝试添加sed来检查它)。它们都是标准的POSIX命令。我确定--posix可以删除,但我的tail fu不够强大,无法执行此操作。

在我看来,这个解决方案不是很便携,因为它在OS X上不起作用。:(

答案 17 :(得分:1)

我的解决方案:

ps -o command | grep -v -e "\<ps\>" -e grep -e tail | tail -1

这应该可以跨不同平台和shell移植。它像其他解决方案一样使用ps,但它不依赖于sedawk并过滤掉管道和ps本身的垃圾,以便shell始终是最后一个条目这样我们就不需要依赖非便携式PID变量或选择正确的行和列。

我已经使用bash,zsh和fish在Debian和MacOS上进行了测试(这些解决方案不适用于大多数这些解决方案,而没有专门针对fish更改表达式,因为它使用了不同的PID变量)。

答案 18 :(得分:1)

这不是一个非常干净的解决方案,但可以做你想要的。

我意识到2015年这个好老的答案有点晚了,但是......

#MUST BE SOURCED..
getshell() {
    local shell="`ps -p $$ | tail -1 | awk '{print $4}'`"

    shells_array=(
    # It is important that the shells are listed by the decrease of their length name.
        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的shell。

答案 19 :(得分:1)

从&#34; ps&#34;的输出中获取PID不需要因为您可以从/ proc目录结构中读取任何PID的相应命令行:

echo $(cat /proc/$$/cmdline)

但是,这可能不仅仅是简单:

echo $0

关于运行实际上与名称不同的shell,一个想法是使用您之前获得的名称从shell请求版本:

<some_shell> --version

sh似乎失败了,退出代码2,而其他人给了一些有用的东西(但我无法验证所有,因为我没有它们):

$ sh --version
sh: 0: Illegal option --
echo $?
2

答案 20 :(得分:1)

如果您只是想检查您是否正在运行(特定版本)Bash, 最好的方法是使用$BASH_VERSINFO数组变量。 作为(只读)数组变量,它不能在环境中设置, 所以你可以确定它来自当前的shell(如果有的话)。 但是,由于Bash在调用sh时具有不同的行为, 您还需要检查$BASH环境变量以/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

你可以在第一种情况下省略对某些功能的偏执功能检查, 并假设未来的bash版本是兼容的。

答案 21 :(得分:1)

答案 22 :(得分:0)

请使用以下命令:

 # ps -p $$ | tail -1 | awk '{print $4}'

答案 23 :(得分:0)

我想出了这个

sed 's/.*SHELL=//; s/[[:upper:]].*//' /proc/$$/environ

答案 24 :(得分:0)

为什么不使用 $SHELL 变量获取它,一个简单的 sed 可以删除路径:

$ echo $SHELL | sed -E 's/^.*\/([aA-zZ]+$)/\1/g'
bash

在 MacOS、Ubuntu、CentOS 上测试

答案 25 :(得分:0)

一种方法是:

ps -p $$ -o exe=

IMO 比另一个答案中建议的使用 -o args-o comm 更好(这些可能使用例如一些符号链接,例如当 /bin/sh 指向某个特定的 shell 作为破折号或 bash) .

以上返回可执行文件的路径,但要注意,由于 /usr-merge,可能需要检查多个路径(例如 /bin/bash /usr/bin/bash )

另请注意,上述内容并不完全兼容 POSIX(POSIX ps 没有 exe)。

答案 26 :(得分:-2)

这个适用于RHEL,MacOS,BSD和一些AIXes

ps -T $$ | awk 'NR==2{print $NF}' 

或者,如果pstree可用,则下一个也应该有效,

pstree | egrep $$ | awk 'NR==2{print $NF}'