如何识别脚本中使用的是bash还是dash?
我正在写一个bash脚本,在Ubuntu中使用“sh”命令时,它会抛出一个错误(它似乎与dash不兼容,我正在学习这个主题)。所以我想检测是否使用dash而不是bash来抛出错误如何识别脚本中使用的是bash还是dash?,bash,dash-shell,Bash,Dash Shell,我正在写一个bash脚本,在Ubuntu中使用“sh”命令时,它会抛出一个错误(它似乎与dash不兼容,我正在学习这个主题)。所以我想检测是否使用dash而不是bash来抛出错误 如何在脚本上下文中检测它?。甚至可能吗?您可以检查是否存在特定于shell的变量: 例如,bash定义了$bash\u版本。 由于在dash中运行时不会定义该变量,因此可以使用它进行区分: [ -n "$BASH_VERSION" ] && isBash=1 事后思考:如果希望避免依赖变量(可以想象
如何在脚本上下文中检测它?。甚至可能吗?您可以检查是否存在特定于shell的变量: 例如,
bash
定义了$bash\u版本
。
由于在dash
中运行时不会定义该变量,因此可以使用它进行区分:
[ -n "$BASH_VERSION" ] && isBash=1
事后思考:如果希望避免依赖变量(可以想象,变量设置可能不正确),可以尝试获取运行脚本的shell可执行文件的最终名称,方法是确定调用的可执行文件,如果它是符号链接,则跟随它到其(最终)目标 下面的shell函数
getrueshellexename()
就是这样做的;例如,对于使用sh
运行的脚本,它会在Ubuntu上返回'dash'
(无论是显式还是通过shebang#!/bin/sh
),因为sh
与dash
有符号链接
请注意,该函数的目标有两个:
- 便于携带:
- 使用所有与POSIX兼容的(Bourne-like)外壳
- 至少在大多数平台上,关于所使用的实用程序和选项,请参见下面的注意事项
- 在所有调用场景中工作:
- 来源(无论是否来自登录shell)
- 通过shebang线独立执行
- 通过作为文件名参数传递给shell可执行文件来执行
- 通过将其内容通过stdin管道传输到shell可执行文件来执行
- 至少在一个平台上,OSX-
不是符号链接,即使它实际上是sh
。在那里,函数将在使用bash
运行的脚本中返回sh
'sh'
- 该函数使用的是
,虽然POSIX没有强制要求,但在大多数现代平台上都可以使用,尽管语法和功能有所不同。因此,使用GNUreadlink
的readlink
选项来查找符号链接的最终目标不是一个选项。-f
(我个人所知的唯一一个没有
实用程序的现代平台是HP-UX-请参阅,以了解可在所有POSIX平台上运行的递归readlink实现。)readlink
- 该函数使用
,该
实用程序(除了在
中,它是一个内置的),它虽然不是POSIX强制要求的,但在大多数现代平台上都存在zsh
[ "$(getTrueShellExeName)" = 'bash' ] && isBash=1
Shell函数getTrueShellExeName()
:
使用$0(即正在调用的shell的可执行文件的名称)
echo $0
给予
/usr/bin/dash
为了冲刺和
/bin/bash
对于bash。参数替换
${0##*/}
只给出“破折号”或“猛击”。这可以在测试中使用。另一种方法可能是测试shell功能是否可用,例如给出一个想法
[[ 1 ]] 2>/dev/null && echo could be bash || echo not bash, maybe dash
可能是bash | | echo而不是bash,也许bash为我运行Ubuntu 19工作
在学校时曾学习过Pascal、Fortran和C语言,但需要熟练使用shell脚本 您可以做的是在脚本的第一行定义解释器:
#/当使用/script.sh
调用时,bin/bash
将使其使用/bin/bash
执行。还有,很高兴看到平克·弗洛伊德在附近:)你下一步在哪里进行直播?bash
的功能是dash
功能的超集dash
更小更快,但主要局限于POSIX功能—请看,这不可靠。如果脚本是可执行的,并作为/script
调用,该怎么办?如果脚本是源代码呢?$0被调用shell的任何程序设置为任意字符串。这几乎总是正确的……您可以使用readlink-f
来获取符号链接的最终目的地,因此在源代码shell脚本(以。/script
开始)中,可以使用BIN=“$(readlink-f$0)”;BIN=“${BIN##*/}”
获取shell的名称,而不包含其路径。在执行的脚本(从/script
开始)中,必须提取shebang,然后再提取符号链接…@zrajm:my shell函数的目的有两个:(a)可移植性和(b)在所有调用场景中工作。我已经更新了我的答案来澄清。您的建议不符合(a),因为例如,readlink-f
是一个GNU扩展,它在OSX上不起作用。它不满足(b),因为分析shebang行是不够的-例如,您的脚本可以作为直接参数传递给任何shell可执行文件。@zrajm:此外,据我所知,没有简单的、与shell无关的方法来确定脚本是否正在源代码中(请告诉我您是否知道一种方法)。此外,例如,OSX将-
前置到登录shell中$0
中报告的shell可执行文件名(在OSX上,终端中创建的所有shell都是登录shell),因此您必须对此进行说明(这是最简单的部分)。
[[ 1 ]] 2>/dev/null && echo could be bash || echo not bash, maybe dash
echo $0 and [[ 1 ]] 2>/dev/null && echo