如何识别脚本中是否使用了bash或破折号?

Rog*_* W. 4 bash dash-shell

我正在编写bash脚本,在Ubuntu中使用“ sh”命令时会引发错误(似乎与破折号不兼容,我正在学习此主题)。因此,我想检测是否使用破折号而不是bash引发错误。

如何在脚本上下文中检测到它?可能吗?

mkl*_*nt0 5

您可以检查是否存在特定于shell的变量

例如,bash定义$BASH_VERSION。由于在中运行时不会定义该变量dash,因此可以使用它来进行区分:

[ -n "$BASH_VERSION" ] && isBash=1
Run Code Online (Sandbox Code Playgroud)

事后思考:如果您想避免依赖变量(很可能设置不正确),则可以通过确定调用的可执行文件(如果它是符号链接)来尝试获取运行脚本的Shell可执行文件最终名称。跟随其(最终)目标。

下面的shell函数可以getTrueShellExeName()做到这一点;例如,它将'dash'在Ubuntu上返回运行的脚本sh(无论是显式的还是通过shebang #!/bin/sh),因为它sh是符号链接到dash那里的。

请注意,该函数的目标是双重的:

  • 便于携带
    • 与所有POSIX兼容(类似于伯恩)的外壳一起使用,
    • 关于使用哪些实用程序和选项,至少在大多数平台上均是如此-请参见以下注意事项。
  • 所有调用方案中工作
    • 来源(无论是否来自登录shell)
    • 通过shebang行独立执行
    • 通过作为文件名参数传递给Shell可执行文件来执行
    • 通过将其内容通过stdin传递到Shell可执行文件来执行

注意事项

  • 在至少一个平台上sh,即使OSX 有效,它也不是符号链接bash。在那里,该函数将'sh'在使用运行的脚本中返回sh
  • 该功能使用readlink了POSIX并未强制要求的功能,但在大多数现代平台上都存在该功能-尽管语法和功能有所不同。因此,使用GNU readlink-f选项,找到一个符号链接的最终目标是不是一种选择。
    (唯一的现代化平台,我个人知道的,它具有readlink实用程序是HP-UX -请参阅/sf/answers/1687983951/一个递归的readlink实施,应该在工作的所有 POSIX平台。 )
  • 该函数使用该which实用程序(除外zsh,它是内置的),虽然不是POSIX强制要求的,但在大多数现代平台上都存在。

函数使用示例:

[ "$(getTrueShellExeName)" = 'bash' ] && isBash=1 
Run Code Online (Sandbox Code Playgroud)

外壳功能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")"
}
Run Code Online (Sandbox Code Playgroud)


Fri*_*ner 5

使用 $0(即被调用的 shell 的可执行文件的名称)。例如命令

echo $0
Run Code Online (Sandbox Code Playgroud)

/usr/bin/dash
Run Code Online (Sandbox Code Playgroud)

对于破折号和

/bin/bash
Run Code Online (Sandbox Code Playgroud)

对于 bash. 参数替换

${0##*/}
Run Code Online (Sandbox Code Playgroud)

只给出 'dash' 或 'bash'。这可以在测试中使用。

  • 这不可靠。如果脚本可执行并作为“./script”调用怎么办?如果脚本有源怎么办? (3认同)