【问题标题】:Shell script working fine without shebang line? Why? [duplicate]没有shebang行的Shell脚本可以正常工作吗?为什么? [复制]
【发布时间】:2012-08-31 01:12:59
【问题描述】:

我正在编写一个简单的 shell 脚本,发现我的 shell 脚本不需要 shebang 行

#!/bin/sh

如果我授予脚本执行权限并使用./myscript.sh 执行。它运行良好。

我正在使用bash shell,/bin/sh 实际上指向bash

lrwxrwxrwx 1 root root /bin/sh -> bash

我知道 shebang 行用于告诉 shell 为脚本的其余部分使用哪个解释器。

如果我错过了 perl 中的 shebang 行,请授予执行权限并运行 ./myscript.pl,它不起作用。

这里实际发生了什么?如果我使用./,什么时候需要shebang line?

【问题讨论】:

    标签: linux perl bash shell unix


    【解决方案1】:

    shebang 行需要 in 文件,并且仅当它打算作为可执行文件运行时(与 sh file.sh 调用相反。脚本实际上不需要它,它是让系统知道如何找到翻译。

    编辑:抱歉误读了这个问题。如果 shebang 行丢失或无法识别,则使用 /bin/sh。但我更喜欢明确解释解释器。

    请注意,这种行为不是通用的,IIRC,只有一些 exec* 家族函数会这样做(更不用说不同的平台),所以这是在这里明确的另一个原因。

    【讨论】:

    • OP 说他以./myscript.sh 调用脚本 - 我认为这意味着他没有明确使用 shell 作为可执行文件和脚本作为参数。
    • 是的。但是脚本在没有那行的情况下运行?为什么?我正在使用./myscript.sh 运行脚本。
    • 糟糕。编辑答案,谢谢。
    • @MichaelKrelin-hacker 在运行没有扩展名的 shell 脚本时,我遇到了“执行格式错误”。添加了shebang行,错误消失了。多亏了你上面的解释,我现在知道为什么要明确了。
    • 如果 shebang 行丢失或无法识别,则使用/bin/sh 由什么使用;外壳,内核,还有什么? /bin/sh 是否因为脚本的扩展名而被使用是 sh 或者这无关紧要?这个答案严重缺乏。
    【解决方案2】:

    您输入./myscript.sh 的父shell 首先尝试execve 它,这是shebang 行如果存在就会生效的地方。当这工作时,父级不知道脚本和 ELF 之间的区别,因为内核会处理它。

    execve 失败了,所以一个古老的 unix 兼容性功能,早于 shebang 行的存在,就被激活了。它猜测一个有执行权限但未被内核识别为有效可执行文件的文件一定是一个shell脚本。

    通常父 shell 猜测脚本是为同一个 shell 编写的(最小的 Bourne-like shell 使用 /bin/sh 运行脚本,bash 将其作为 bash 子进程运行), csh 做一些基于第一个字符的更复杂的猜测,因为它也早于 shebang,并且需要与 Bourne shell 共存。

    当您知道这些猜测是错误的时(例如,shebang 是 #!/usr/bin/perl),或者当您不相信猜测能够始终如一地工作,或者当脚本需要由以下人员运行时,您需要一个 shebang 行不是 shell 本身的父进程。

    【讨论】:

    【解决方案3】:

    POSIX(单一 UNIX 规范 4)标准没有帮助:

    如果 shell 命令文件的第一行以字符“#!”开头,结果未指定。

    因此,标准意味着如果您没有 #!那么它应该运行一个 POSIX shell。但是现代 shell 不符合 POSIX。旧的 Korn Shell 88 (ksh88) 运行 Bourne shell(接近 POSIX shell),没有 #!行,但 ksh93 打破了这一点,Bash 也是如此。使用 ksh93 和 Bash,如果没有 #!线路存在。

    尽管流行的观点,Bash 和 Korn shell 不同。当您编写一个 shell 脚本时,您永远无法确定您将从哪个 shell 运行,或者即使它会从另一个 shell 运行(大多数编程语言可以运行其他程序)。一旦你使用了 Bourne/POSIX 语法之外的东西,你就会陷入困境。

    始终使用 #!行,不要碰运气。

    【讨论】:

    • 您关于外壳合规性的声明被颠倒了。像 ksh 和 bash 这样的现代 shell 符合 POSIX(或至少非常接近),而 Bourne shell 绝对不是。 shell 最初的 POSIX 标准本质上是 ksh88。当标准规定应使用符合 POSIX 的 shell 时,这使得 bash 和 ksh 自行运行是合理的。 Bash、ksh88 和 ksh93 肯定有所不同,但它们所做的领域要么是标准中未指定的行为,要么是其范围之外的行为。
    • @jlliagre:POSIX 说如果没有 #!,则运行 sh,而不是 ksh 或 bash。当 Bash 运行非#!行脚本它不以 POSIX 模式 (--posix) 或作为 sh 符号链接运行。 POSIX 可能基于 ksh88,但我特别提到了 ksh93,它与 POSIX 标准中的 sh 有很大不同(ksh88 和 POSIX 之间也存在差异,例如函数中的 typedef),但是确实,SFAIK, ksh93 是 POSIX sh 的超集(这就是函数中的 typedef 从 ksh88 更改为 93 的原因)。我坚持我的建议,始终指定 #! 行是明智的。
    • 您错误地认为 /bin/sh 始终是 POSIX。 POSIX 不会说 /bin/sh 在没有 shebang 时运行,但是当您已经在 POSIX 环境下时,POSIX shell 将解释没有 shebang 的脚本。它不要求此 shell 具有特定的路径名​​。由实现者来定义它的名称(可能是 sh)和路径,它可能不像 Solaris 10 /usr/xpg4/bin 那样是 /bin。这就是为什么我建议便携式 shell 脚本不要像标准所建议的那样使用 shebang。如果您的 shell 是以 POSIX 模式运行的 bash 并且您调用了非 #!脚本,它也将在 POSIX 模式下运行。
    • If the first line of a file of shell commands starts with the characters "#!" , the results are unspecified. 我将其读作If "#!" then unspecified.,但您的其余答案表明相反(if no "#!" present then unspecified.)。你错过了否定吗?否则,您能否解释在什么情况下 结果 指定
    • @Georges Dupéron:不,关键是 POSIX 没有指定 #! 应该发生什么。要在什么情况下指定结果来回答您的问题,我建议您阅读 POSIX 标准。
    猜你喜欢
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 2017-02-20
    • 2013-06-22
    • 1970-01-01
    • 2012-03-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多