以三种不同方式打开的相同脚本会产生三种不同的结果 为什么?

我有一个示例脚本(功劳归于kos ):

#!/bin/bash cat <(cat /etc/lsb-release) 

我将此脚本保存为myname.sh在我的主目录中。

现在,我尝试以三种不同的方式打开此文件:

 sh somename.sh bash somename.sh ./somename.sh 

所以,我有两个问题:

  1. 为什么上述命令的输出虽然运行相同的脚本但却不同?

    • sh产生语法错误

    • bash输出所需的结果

    • ./给出了Permission Denied错误

  2. 为什么仅在使用./运行脚本时才提供脚本可执行权限,而在其他情况下则不需要?

提前致谢!

编辑 :第一部分可能类似于重复链接的一部分,但我也有第二个问题。

正如我们在聊天中讨论的那样:

  1. sh script产生错误,因为直接调用解释器(在本例中为sh )忽略了shebang,脚本在sh运行; sh不支持进程替换( <([...]) ),它们是Bash-isms,因此脚本在出错时退出。

    bash script不会产生错误,因为尽管shebang被忽略,脚本仍然在Bash中运行,它支持进程替换。

    ./script会产生错误,因为script不可执行。

  2. 要使用./运行脚本,您必须在脚本上设置用户设置的执行位,这是操作系统的约束。

    所以问题实际上是: 为什么bash script不需要在script上为用户设置执行位

    这是因为在运行bash script时,Bash会读取脚本,而Bash 为您的用户设置执行位。

    这意味着拥有执行代码权限的Bash可以“绕过”该脚本上的操作系统约束,并且Bash可以读取所有脚本需求。

  • sh是spml shell的符号链接并产生语法错误,因为sh语法中没有<( . . .) 。 它只在bash中(如果我没记错的话,在zshksh )。

  • bash输出所需的结果,因为它采用正确的bash语法,没有任何错误

  • ./给出一个Permission Denied错误,因为你基本上说“嘿,shell,查看该文件的权限,然后查看我当前目录中的第一行( #!/bin/bash )”并弄清楚如何运行这个脚本对我来说“。 (旁注:如果您的脚本位于$PATH变量中包含的位置,那么您只需运行myScriptName.sh ,但想法是一样的,我们需要检查exec权限以及解释器的内容使用)

在运行bashdash并告诉他们从文件中读取命令之前。 bashdash这次是可执行的,而不是脚本。 脚本现在是命令的来源,一个参数。 总是为所有用户设置读取权限,因此shell将读取它。

一般来说, shashdashbashcshtcshzsh ……都是具有自己语法和特征的shell。 有一些兼容性,但它们是面向 [ 1 ] :一个bash shell将执行一个sh脚本,但它不是反之亦然sh调用比bash调用所需资源少。 对于一个单一实例来说,这不是一个问题,应该是成千上万。

如何执行。
要在Linux下执行文件作为程序,无论是脚本还是编译程序,都必须设置执行位 [ 2 ]并且必须包含在$PATH某个目录中。

如果它是一个脚本,它可以作为参数传递给相对shell( shbashmyfile.whatever ):如果它被传递给错误的shell你可以获得一个不正确的行为, 如果你幸运的话,一个错误 ; 在这种情况下, 它不需要是可执行的,因为它就像是你正在调用的新shell中直接编写脚本中编写的行。 要在同一个shell中执行,您可以使用source myfile. myfile . myfile相当于在当前shell中逐行写入脚本的内容。

地点
如果路径中未包含可执行程序,则必须指定可以找到的位置。

  • 在你的情况下,。 ./表示只有shell的当前目录,以及~/myfile.whatever应该在你的home ~/目录中找到文件myfile.whatever
  • 您可以从其他位置调用它,例如使用/home/$USER/dir/myfile.whatever
  • 如果此文件位于路径中包含的目录中,则可以使用简单的myfile.whatever调用它。

如果多个可执行文件共享相同的名称,则指定完整路径将确定您要执行的是哪一个。 which mycommand能够告诉你现在将执行哪一个(一个函数,一个别名,一个内置的或你的路径中找到的第一个),但它不能说将来会执行哪一个或者来自另一个用户。 如果你明确写出完整的路径,你将解决这个模糊性。 当同时安装多个程序时执行特定版本的程序是很有用的…并且避免木马。 在脚本中,总是建议写/bin/bash而不是bash