Shell脚本在没有shebang行的情况下运行良好?为什么?



我正在写一个简单的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线路?

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

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

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

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

文件中需要shebang行,并且只有当它作为可执行文件运行时(与sh file.sh调用相反)。脚本实际上并不需要它,而是让系统知道如何找到解释器。

编辑

:很抱歉误读了这个问题。如果shebang线丢失或无法识别,则使用/bin/sh。但我更喜欢对口译员直言不讳。

注意,这种行为并不是通用的,IIRC,只有一些exec*家族函数才能做到这一点(更不用说不同的平台了),所以这是这里要明确的另一个原因。

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

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

所以,这个标准意味着,如果你没有#!那么它应该运行POSIX shell。但现代shell并不符合POSIX。旧的Korn Shell 88(ksh88)运行的Bourne Shell(接近POSIX Shell)没有#!但ksh93打破了这条线,Bash也是。对于ksh93和Bash,如果没有#,它们将运行自己的shell!行存在。

尽管舆论普遍认为,Bash和Korn的炮弹各不相同。当你编写一个shell脚本时,你永远无法确定你将从哪个shell运行,甚至无法确定它是否会从另一个shell运行(大多数编程语言都可以运行其他程序)。一旦你使用了Bourne/POSIX语法之外的东西,你就会被破坏。

始终使用#!行,不要听之任之。

相关内容

最新更新