我正在编写一个简单的shell脚本,发现我的shell脚本不需要shebang line
#!/bin/sh
如果我给我的脚本赋予执行权限并使用./myscript.sh
执行。它运行良好。
我正在使用bash
shell而/bin/sh
实际上指的是bash
。
lrwxrwxrwx 1 root root /bin/sh -> bash
我知道shebang line用于告诉shell哪个解释器用于你的其余脚本。
如果我错过了perl中的shebang行,请提供执行权限并运行./myscript.pl
,它不起作用。
这里到底发生了什么?如果我使用./
,何时需要shebang线?
答案 0 :(得分:18)
您输入./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本身。
答案 1 :(得分:12)
文件中只需要 文件中的,并且只有当它意味着作为可执行文件运行时(而不是sh file.sh
调用。)脚本实际上并不需要它,它用于系统知道如何找到翻译。
编辑:很抱歉误读了这个问题。如果shebang行丢失或无法识别,则使用/bin/sh
。但我更喜欢明确解释翻译。
请注意,这种行为不是通用的,IIRC,只有一些exec*
家庭功能可以做到这一点(更不用说不同的平台),所以这是明确的另一个原因。
答案 2 :(得分:3)
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语法之外的那一刻,您将被打破。
始终使用#!一句话,不要遗憾。