bash myscript.sh 在 bash 中运行,但第一行是 #!/usr/bin/sh

Abh*_*eet 5 shell bash solaris shell-script

我有一个类似以下的脚本:

#!/usr/bin/sh

var="ABC"
if [ $var == "ABC" ]
then
   echo True
else
   echo False
fi
Run Code Online (Sandbox Code Playgroud)

以上代码在 Solaris Sparc 和 Solaris X64 中不起作用。显示==未定义。上面的代码工作正常如果我替换===.

奇怪的是,如果我通过以下方法在没有任何更改的情况下运行上面的代码,它就可以工作。

#bash test.sh
Run Code Online (Sandbox Code Playgroud)

根据我的理解,即使使用 bash 脚本也不应该工作,因为在我使用的脚本的顶部,#!/bin/sh它不支持== 作为比较运算符。

任何人都可以解释为什么当我如上所述运行脚本时它会起作用。

注意:我知道 bash 确实识别===.

Mik*_*kel 12

脚本的第一行称为#!行(有时称为“shebang”行)。

它仅在直接执行脚本时使用,如

./test.sh
Run Code Online (Sandbox Code Playgroud)

解释

当你运行一个可执行文件时,操作系统会查看前两个字节来判断它是什么类型的程序。

当你跑

./test.sh
Run Code Online (Sandbox Code Playgroud)

操作系统看到前两个字节./test.sh#!,所以它知道程序是一个脚本。

它读取该行的其余部分以查看它应该使用哪个 shell 1来运行脚本。在这种情况下,该行的其余部分是/usr/bin/sh,因此它运行/usr/bin/sh test.sh2

当你跑

bash test.sh
Run Code Online (Sandbox Code Playgroud)

它在/usr/bin/bash3 中找到 bash 。它看到 的前两个字节/usr/bin/bash不是#!,因此它/usr/bin/bash test.sh甚至没有查看 的第一行就运行test.sh.

在这两种情况下,shbash实际上忽略shebang行,因为任何与开头的行#是注释。该#只因为操作系统,而不是shell的这种神奇的效果。

更多信息:

脚注:

  1. 事实上,它可以是任何程序,它不必是一个shell。
  2. 其实更像execl("./test.sh", "/usr/bin/sh", "./test.sh", NULL)
  3. /bin/sh 在大多数 Linux 系统上,但问题是关于 Solaris。


jsb*_*ngs 6

使用 bash (running bash test.sh)运行脚本意味着使用 bash 解释脚本,而不是 Bourne shell (/bin/sh)。这就是它起作用的原因。Bash 忽略 #!/bin/sh 因为它是一个注释。如果您在没有 bash 的情况下运行 shell 脚本(例如运行),则只有您的操作系统的程序加载器会启动 /bin/sh ./test.sh