如何确定当前运行的shell是bash还是zsh?
(能够在额外的shell之间消除歧义是一个额外的奖励,但只有bash&zsh是100%必要的(
我已经看到了一些应该做到这一点的方法,但它们都有问题(见下文(。
我能想到的最好的办法是运行一些对其中一个有效而对另一个无效的语法,然后检查错误/输出,看看哪个shell正在运行。如果这是最好的解决方案,那么什么命令最适合此测试?
最简单的解决方案是,如果每个shell都包含一个标识该shell的同名只读参数。然而,如果存在这种情况,我还没有听说过
确定当前运行的shell的非决定性方法:
# default shell, not current shell
basename "${SHELL}"
# current script rather than current shell
basename "${0}"
# BASH_VERSINFO could be defined in any shell, including zsh
if [ -z "${BASH_VERSINFO+x}" ]; then
echo 'zsh'
else
echo 'bash'
fi
# executable could have been renamed; ps isn't a builtin
shell_name="$(ps -o comm= -p $$)"
echo "${shell_name##*[[:cntrl:][:punct:][:space:]]}"
# scripts can be sourced / run by any shell regardless of shebang
# shebang parsing
虽然没有100%万无一失的方法来实现它,但进行可能会有所帮助
echo $BASH_VERSINFO
echo $ZSH_VERSION
两者都是shell变量(而不是环境变量(,由各自的shell设置。在相应的另一个外壳中,它们是空的。
当然,如果有人故意创建这个名称的变量,或者导出这样的变量,然后创建不同类型的子shell,即
# We are in a non-bash here (ksh, zsh, dash, ...)
export BASH_VERSINFO=5
zsh # the new zah subshell will see BASH_VERSION even though it is zsh
这种方法将失败;但我认为,如果有人真的在做这样的事情,他想故意破坏你的代码。
在$prompt上,运行:
echo $0
但是不能在脚本中使用$0
,因为$0
将成为script's name
本身。
如果shebang/magic number可执行文件是脚本中的#!/bin/bash
,则查找当前shell(比如BASH(:
#!/bin/bash
echo "Script is: $0 running using $$ PID"
echo "Current shell used within the script is: `readlink /proc/$$/exe`"
script_shell="$(readlink /proc/$$/exe | sed "s/.*///")"
echo -e "nSHELL is = ${script_shell}n"
if [[ "${script_shell}" == "bash" ]]
then
echo -e "nI'm BASHn"
fi
输出:
Script is: /tmp/2.sh running using 9808 PID
Current shell used within the script is: /usr/bin/bash
SHELL is = bash
I'm BASH
如果shebang是:#!/bin/zsh
(也是(,这将起作用。
然后,您将获得SHELL的输出:
SHELL is = zsh
这应该适用于大多数Linux系统:
cat /proc/$$/comm
快速而简单。
根据@ruakh的评论工作@oguzismail,我想我有一个解决方案。
shopt -u lastpipe 2> /dev/null
shell_name='bash'; : | shell_name='zsh'