- A+
今天和小伙伴日常在群内吹水的时候,有群友问了这样一个问题:
脚本文件第一行加个 #!/usr/bin/bash 有什么用呢?
其实,除了这种之外,还有很多其他写法,比如:
#!/bin/bash #!/usr/bin/env bash #!/bin/awk
这些写法大同小异,但很多同学像我一样,在之前编写shell脚本的时候顺手就抄过来了,而没有去想过这一行语句到底是干什么的。
#!这个东西来自早期的Unix标准,叫做“she bang”或者“hash bang”,在#!之后的被认为是加载的解释器的路径,而这个标准也这样被沿袭到了现在。当执行shell脚本时,就会根据shebang中指定的路径去寻找对应的解释器,并将shell脚本交给解释器去执行。
看到#,可能很多人第一反应是这是一行注释,但是就算把它删掉,./xx.sh依然能正常执行,这更进一步的佐证了这一点。然而,这种想法其实是不正确的。如果你将第一行的路径随便设为一个不存在的路径,或者干脆删掉这一行,此时使用./方式执行的可执行文件就找不到对应的解释器,系统会转而找到另一个默认的解释器,而在一般来说的Linux系统中这个默认解释器为bash。所以对于shell脚本来说看似不需要这一行也能正常执行。
而至于env bash,在这个过程中其实是做了一次grep查找bash解释器的工作,env命令具体细节可自行查找,参考:https://blog.csdn.net/qq_37164975/article/details/106181500
但是,从这里就产生了一个问题,让我们解释一下文本文件和解释器之间的关系:
如果你指定了某个解释器去执行这个文件时,首行是没有任何作用的。但是,在这种情况下,有一些花活可以玩。例如,你修改文件属性为可执行文件,使用./xx.sh的方式执行,就会先读第一行的shebang,将剩余的内容传递给shebang指定的解释器。
举个例子:怎么在Linux中运行python脚本?
常见的一种方法当然是python xx.py,但是,还有另一种方法。
首先将py脚本 chmod 添加可执行属性。
然后直接执行./xx.py,竟然成功运行。
打开该py文件,发现文件首行为#!/usr/bin/python或者类似写法。在Linux下,指定了/usr/bin/python作为python脚本的解释器。这种情况下,去掉后缀的.py依然能够成功执行。
在这个过程中,前一次是直接指定解释器为python,后一次则是通过shebang解析指定路径,相当于中间多中转了一次。
所以说,shell脚本、python脚本包括其他类型的脚本,在本质上都是文本文件,需要指定对应的解释器去帮助解释并执行。而./方式执行的脚本,未手动指定解释器,所以需要在首行#!指定解释器路径。
References:
https://blog.csdn.net/qq_37164975/article/details/106181500
https://m.php.cn/article/419430.html
https://blog.csdn.net/iot_flower/article/details/69055590
https://www.zhihu.com/question/333282017?sort=created&utm_id=0