我正在编写bash脚本,在Ubuntu中使用“sh”命令时会引发错误(似乎与破折号不兼容,我正在学习此主题)。因此,我想检测是否使用破折号而不是bash引发错误。
如何在脚本上下文中检测到它?可能吗?
最佳答案
您可以检查是否存在特定于 shell 的变量:
例如,bash
定义$BASH_VERSION
。
由于在dash
中运行时不会定义该变量,因此可以使用它来进行区分:
[ -n "$BASH_VERSION" ] && isBash=1
事后思考:如果要避免依赖于变量(很可能设置不正确),则可以尝试获得运行脚本的shell可执行文件的最终名称,方法是确定调用的可执行文件,如果确定,是一个符号链接(symbolic link),紧跟其(最终)目标。
下面的 shell函数
getTrueShellExeName()
做到了;例如,对于使用'dash'
运行的脚本(无论是显式还是通过shebang sh
),它将在Ubuntu上返回#!/bin/sh
,因为在那里sh
被符号链接(symbolic link)到dash
。请注意,该函数的目标是双重的:
通过作为文件名参数传递给Shell可执行文件来执行
通过将其内容通过stdin传递到Shell可执行文件
注意事项:
sh
不是符号链接(symbolic link),即使它实际上是bash
。在那里,该函数将在使用'sh'
运行的脚本中返回sh
。 readlink
,虽然不是由POSIX强制要求的,但它在大多数现代平台上都存在-尽管语法和功能不同。因此,不能使用GNU readlink
的-f
选项来找到符号链接(symbolic link)的最终目标。(我个人知道的唯一没有
readlink
实用程序的现代平台是HP-UX-有关在所有POSIX平台上都可以使用的递归读取链接实现,请参见https://stackoverflow.com/a/24114056/45375。)which
实用程序(zsh
除外,它是内置的),该功能虽然不是POSIX强制要求的,但在大多数现代平台上都存在。 函数使用示例:
[ "$(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")"
}
关于bash - 如何识别脚本中是否使用了bash或破折号?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23011370/