我如何*可靠*和*简单*获得当前的shell解释器名称?

ico*_*ast 12 shell bash zsh

我正在寻找一种简单可靠的方法来从脚本或源文件(而不是从命令行)中获取当前 shell 的名称。我本来希望这样做,$(basename "$SHELL")但是如果我的登录 shell 是zsh并且我在 some_script.sh 中有以下代码

this_shell=$( basename "$SHELL" )
echo "The Shell is $this_shell"
echo "The Shell is $0"
Run Code Online (Sandbox Code Playgroud)

我用 运行它bash some_script.sh,它仍然列出zsh而不是bash即使使用的解释器是/bin/bash. 我不确定为什么外壳设计者选择显示默认外壳而不是当前外壳,但这似乎是我们所坚持的。

还有一些其他稍微相似的问题(这里这里),但他们的答案在很多方面都不够。

  1. 他们经常假设用户试图找出他们当前使用的交互式 shell,但这太疯狂了。我知道我正在向哪个 shell 输入命令——我需要可以在任何地方运行的代码,以便能够确定正在使用什么 shell 。
  2. 他们经常提供几种不同的尝试——再次就像你在命令行上一样,在你学会使用 bash 之前可以随意摆弄——但我需要一件在所有上下文中都可靠的东西。
  3. 他们经常提供脚本中完全无用的东西,比如echo $0. 如上面的脚本所示,这失败了。(是的,它可以在交互式 shell 命令行中使用,但是您为什么不知道您使用的是什么 shell?)
  4. 他们有时会给出(在我有限的测试中)包含正确信息的命令,例如ps -p $$,但缺乏跨平台、跨外壳兼容的 sed/awk 命令来通过管道传递它以获取外壳名称并忽略随之而来的其他信息为骑行。
  5. 它们包括只能在几个 shell 上工作的东西,比如$BASH_VERSION$ZSH_VERSION。我想支持尽可能多的 shell,例如fish, csh, tcsh.

如何可靠准确地检测出任何 当前的壳呢?我正在寻找可以跨平台、在脚本中以及尽可能多且合理的 shell 中工作的东西1

更新:当我发布这个问题时,我希望 shell 中内置了一些工具来为我们提供这些信息,但事实并非如此。由于现在似乎不可避免地依赖于shell之外的东西,我应该更明确地表明我要求一个跨平台的解决方案(虽然我对上述其他答案的反对暗示了这一点,但如果你不这样做,可能很容易错过'不仔细阅读问题)。

更新 2 如果有人仍然认为这是 Linux-only 问题的重复,因为 Stéphane 的回答不是 Linux-only,这里是我要求的和他提供的之间的区别。(请注意,他写的东西很巧妙,我不是在敲它,但它并没有解决我的问题。)

  1. 我在寻找的东西简单可靠的,那
  2. 可以添加到任何脚本或函数的定义(将由一个被采购.zshrc.bash_profile分支或其他)。
  3. 您不能将他的脚本用作将解释器名称传递给调用脚本/函数的外部实用程序,因为它将始终由默认解释器解释并返回。这使得它很难或不可能用于我的目的。如果可能的话,还是非常非常困难的,答案中也没有给出解决办法。因此他没有回答我的问题,因此它不是重复的。

如果你想看到的东西,工作,看看ShellDetective GitHub上。这可能更容易看出 SE 上已经存在的内容与这个问题正在寻找的内容之间的差异(实际上是为了满足这个问题的需求而编写的,这些需求在其他任何地方都没有得到满足)。


(PS,如果你不相信有这样的用例,想象一下这些函数被引入.zshrc, .bash_profile,或者.profile取决于正在使用的服务器和它有哪些可用的外壳。它们是来源所以他们没有shebang线。他们如果它们可以在任何 shell 中工作,则最有用,但有时他们必须知道它们在哪个 shell 中才能知道如何表现。)


1我不关心在任何传统意义上都不是贝壳的“贝壳”。我不关心某个人为自己写的一些 shell。我只关心实际发生在野外的真实 shell,可以想象,有人在登录到某些服务器时可能不得不使用它们,而在这些服务器上他们不能只安装他们想要的任何 shell。

小智 6

我用这种组合取得了很好的结果:

ps -p $$ | awk '$1 != "PID" {print $(NF)}'
Run Code Online (Sandbox Code Playgroud)

在 Tru64 (OSF/1) 上,输出在外壳周围有括号。钉在tr -d '()'删除它们。

ps -p $$ | awk '$1 != "PID" {print $(NF)}' | tr -d '()'  
Run Code Online (Sandbox Code Playgroud)

似乎适用于所有 shell,在 Solaris 10 和 RHEL 5.7 / 6.4 上。没有测试其他发行版,例如 Debian、Ubuntu 或 Mint,但我认为它们应该都可以正常工作;我也不知道 FreeBSD 是否可以工作。

在此处输入图片说明

  • 在脚本中不起作用(将返回脚本的名称) (5认同)

gwi*_*lie -2

使用以下风险自负的免责声明

tmp=`head -n 1 $0`
SHELL_BIN=`readlink -f ${tmp#*!}`
SHELL=${SHELL_BIN##*/}
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

6012 次

最近记录:

5 年,3 月 前