我正在编写一个bash脚本,但在使用" sh"时会出错。 Ubuntu中的命令(看起来它与破折号不兼容,我正在学习这个主题)。所以我想检测是否正在使用dash而不是bash来抛出错误。
如何在脚本上下文中检测到它?它甚至可能吗?
答案 0 :(得分:4)
您可以检查是否存在特定于shell的变量:
例如,bash
定义$BASH_VERSION
。
由于该变量在dash
中运行时无法定义,因此您可以使用它来区分:
[ -n "$BASH_VERSION" ] && isBash=1
事后补充:如果您想避免依赖变量(可以想象,可能设置不正确),您可以尝试获取终极名称shell可执行文件运行您的脚本,通过确定调用可执行文件,如果是符号链接,则将其跟踪到(最终)目标。
下面的 shell函数getTrueShellExeName()
就是这样做的;例如,对于使用'dash'
运行的脚本(无论是明确地还是通过shebang sh
),它会在Ubuntu上返回#!/bin/sh
,因为sh
符号链接到dash
那里。
请注意,该功能的目标有两个:
注意事项:
sh
不是符号链接,即使它是有效的bash
。在那里,该函数将在使用'sh'
的脚本中返回sh
。readlink
,尽管大多数现代平台上都存在,但它不是POSIX强制要求的 - 尽管具有不同的语法和功能。因此,使用GNU readlink
-f
选项查找符号链接的终极目标是不选项。<登记/>
(我个人都知道的唯一现代平台不具有readlink
实用程序是HP-UX - 请参阅https://stackoverflow.com/a/24114056/45375以获取递归读取链接实现在所有 POSIX平台上工作。)which
实用程序(zsh
除外,其中内置),虽然不是由POSIX强制执行的,但在< em>大多数现代平台。该功能的使用示例:
[ "$(getTrueShellExeName)" = 'bash' ] && isBash=1
Shell函数getTrueShellExeName()
:
getTrueShellExeName() {
local trueExe nextTarget 2>/dev/null # ignore error in shells without `local`
# Determine the shell executable filename.
trueExe=$(ps -o comm= $$) || return 1
# Strip a leading "-", as added e.g. by OSX for login shells.
[ "${trueExe#-}" = "$trueExe" ] || trueExe=${trueExe#-}
# Determine full executable path.
[ "${trueExe#/}" != "$trueExe" ] || trueExe=$([ -n "$ZSH_VERSION" ] && which -p "$trueExe" || which "$trueExe")
# If the executable is a symlink, resolve it to its *ultimate*
# target.
while nextTarget=$(readlink "$trueExe"); do trueExe=$nextTarget; done
# Output the executable name only.
printf '%s\n' "$(basename "$trueExe")"
}
答案 1 :(得分:4)
使用$ 0(即被调用的shell的可执行文件的名称)。例如
的命令echo $0
给出
/usr/bin/dash
表示短划线和
/bin/bash
表示bash。参数替换
${0##*/}
只给出'破折号'或'bash'。这可以用于测试。
答案 2 :(得分:1)
另一种方法可能是测试shell功能是否可用,例如给出一个想法......
[[ 1 ]] 2>/dev/null && echo could be bash || echo not bash, maybe dash
答案 3 :(得分:-1)
echo $0 and [[ 1 ]] 2>/dev/null && echo
可能是bash ||回声不是bash,也许bash对运行Ubuntu 19的我有用。
在学校做过轻微的Pascal,Fortran和C,但需要精通Shell脚本。