如何确定我正在使用的当前shell ?

仅仅ps命令的输出就足够了吗?

如何在不同风格的Unix中实现这一点?


当前回答

不需要从"ps"的输出中Grepping PID,因为你可以从/proc目录结构中读取任何PID的相应命令行:

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

然而,这可能并不比简单地:

echo $0

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

<some_shell> --version

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

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

其他回答

Try

ps -p $$ -oargs=

or

ps -p $$ -ocomm=

你可以使用echo $SHELL|sed "s/\/bin\// g"

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

有许多方法可以找到shell及其对应的版本。下面是一些对我有用的方法。

直截了当的

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

独创性的方法

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

下面将始终给出实际使用的shell -它获得实际可执行文件的名称,而不是shell名称(即ksh93而不是ksh,等等)。对于/bin/sh,它将显示实际使用的shell,即破折号。

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

我知道有很多人说ls输出永远不应该被处理,但是您所使用的shell以特殊字符命名,或者位于以特殊字符命名的目录中的可能性有多大?如果情况仍然如此,还有很多其他不同的做法。

正如托比·斯佩特(Toby Speight)所指出的,这将是实现相同目标的更适当、更干净的方式:

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