我正在写一个简单的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行在文件中是必须的,只有当它是以可执行文件的形式运行(而不是sh file.sh
调用sh file.sh
需要),脚本实际上不需要它,系统知道如何找到解释器。
编辑 :抱歉误解的问题。 如果shebang行缺失或未被识别,则使用/bin/sh
。 但我更喜欢对口译员进行明确的表述。
请注意,这种行为是不通用的,IIRC,只有一些exec*
家庭功能(更不用说不同的平台),所以这是在这里明确的另一个原因。
在你输入./myscript.sh
的父shell中,首先尝试执行它,这是shebang行将会生效的地方。 当这样做的时候,父母并不知道脚本和ELF之间的区别,因为内核会照顾它。
execve
失败了,所以一个古老的unix兼容性特征,在shebang线的存在之前被激活。 它猜测具有执行权限但不被内核识别为有效可执行文件的文件必须是一个shell脚本。
通常,父shell会猜测脚本是为同一个shell编写的(最小的Bourne-like shell使用/bin/sh
运行脚本,bash运行它作为bash子进程),csh根据第一个字符做了一些更复杂的猜测因为它早于shebang也需要与Bourne shell共存)。
当你知道这些猜测是错误的(例如,shebang是#!/usr/bin/perl
),或者当你不相信猜测工作一致,或者脚本需要时可以由不是shell本身的父进程运行。
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语法之外的东西的时候,你将会被困住。
始终使用#! 行,不要放弃它。