今天和小伙伴日常在群內吹水的時候,有群友問了這樣一個問題: 腳本文件第一行加個 #!/usr/bin/bash 有什麼用呢? 其實,除了這種之外,還有很多其他寫法,比如: #!/bin/bash #!/usr/bin/env bash #!/bin/awk 這些寫法大同小異,但很多同學像我一樣,在之 ...
今天和小伙伴日常在群內吹水的時候,有群友問了這樣一個問題:
腳本文件第一行加個 #!/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