我正在寻找一种简单可靠的方法来从脚本或源文件(而不是从命令行)中获取当前shell的名称。我本来希望这样做,$(basename "$SHELL")
但是如果我的登录外壳是zsh
且我在some_script.sh中具有以下代码
this_shell=$( basename "$SHELL" )
echo "The Shell is $this_shell"
echo "The Shell is $0"
并且我用bash some_script.sh
它运行zsh
,bash
即使使用的解释器还是列出了/bin/bash
。我不确定为什么外壳设计人员选择显示默认外壳而不是当前外壳,但这似乎就是我们所坚持的。
还有其他一些稍微相似的问题(此处和此处),但是它们的答案在许多方面都不够。
- 他们通常会假设用户试图弄清楚他们当前正在使用哪种交互式外壳,但这太疯狂了。我知道我要在其中键入命令的外壳程序-我需要可以在任何地方运行的代码,以便能够确定正在使用的外壳程序。
- 他们通常会提供几种不同的方法来尝试-就像您在命令行上一样,并且可以四处弄弄,直到了解到您正在使用bash为止-但是我需要一件在所有情况下都可靠的方法。
- 它们通常会提供脚本中完全没有用的东西,例如
echo $0
。如上面的脚本所示,该操作失败。(是的,它可以在交互式shell命令行中工作,但是为什么您不知道使用的是哪个shell?) - 他们有时会提供一些命令(在我的有限测试中),这些命令包含正确的信息,例如
ps -p $$
,但是缺少跨平台,跨外壳兼容的sed / awk命令来通过管道传递该命令以获取外壳名称,而忽略随之而来的其他信息骑。 - 它们包括只能在几个shell上使用的东西,例如
$BASH_VERSION
和$ZSH_VERSION
。我要支持尽可能多的炮弹可能,如fish
,csh
,tcsh
。
如何可靠,准确地检测到任何 当前的外壳?我正在寻找可以在各种平台,脚本和尽可能多的shell中正常运行的东西1。
更新:当我发布此问题时,我希望外壳中内置一些功能来提供此信息,但事实并非如此。由于现在看来不可避免地要依赖Shell之外的东西,因此我应该更加明确地表明,我正在寻求跨平台解决方案(尽管我对上述其他答案表示反对,但如果您不这样做的话,可能会很容易错过它。没有仔细阅读问题)。
更新2 如果由于Stéphane的回答不是仅Linux,还是有人仍然认为这是仅Linux的问题的重复,那么这里就是我所要求的与他所提供的之间的区别。(请注意,他写的东西很巧妙,我没有敲门,但这并不能解决我的问题。)
- 我在寻找的东西简单和可靠的,那
- 可以添加到任何脚本或函数的定义(将由一个被采购
.zshrc
或.bash_profile
分支或其他)。 - 您不能将他的脚本用作将解释器名称传递给调用脚本/函数的外部实用程序,因为它将始终由默认解释器解释并返回该名称。这使得很难或根本无法实现我的目的。如果可能的话,这仍然非常非常困难,答案中没有给出解决方案。因此他没有回答我的问题,因此不是重复的。
如果你想看到的东西,将工作,看看ShellDetective GitHub上。这样可以更容易地看到SE上已经存在的内容与该问题正在寻找的内容之间的差异(实际上是为了满足该问题的需求而编写的,而其他地方都未满足)。
(PS,如果您无法相信有这样的用例,请想象将这些函数派生到.zshrc
,.bash_profile
或.profile
取决于正在使用的服务器以及可用的外壳的函数。它们的来源使其没有shebang行。如果它们可以在任何外壳中工作,则非常有用,但有时他们必须知道所处的外壳才能知道如何运行。)
1我不关心“贝壳”,它不是任何传统意义上的贝壳。我不关心有人为自己编写的shell。我只关心真正出现在外壳中的真实外壳,并且可以想象有人在登录某些服务器时可能会不得不使用的外壳,而他们不能在其中安装所需的任何外壳。
sh -c "…"
,然后使用POSIX shell语法完成大部分工作。
fish
并用于运行您的脚本,您要fish
还是csh
?