為什么會想到寫 和 的區(qū)別呢?還要從一次裝插件的過程說起。
由于剛開始接觸 Shell Script 不久,對一些語法用法等還不是很熟悉,所以,當(dāng)時在 IDE 上裝了一些 Shell 的插件,包括 Shellcheck、Shell Process、BashSupport 等一大堆。然后呢,我的 IDE 就多了很多之前沒有的功能,于是,滿懷激動的我準(zhǔn)備嘗試一下。
新建一個 Shell 腳本 -> 寫 Shebang、 咦?
在寫 Shebang 的時候出現(xiàn)了一個奇怪的事,如下圖:
IDE 居然給我提示了這么多!
zsh、bash、csh、ksh 這些解釋器雖然有些我沒用過,但是我知道它們的含義。可是,在我的印象里,Shell 腳本的 Shebang 不是應(yīng)該這樣寫嗎(以前的認(rèn)知)???
or
為什么 IDE 給我的提示是這樣的??:
這是個什么寫法?我有點疑惑。
但是,雖然很疑惑,可是我當(dāng)時并沒有深究,而是開始試驗我新裝的插件了,于是,這個疑惑被壓箱底了。
再次看到這個問題呢,是前幾天在公眾號上看到一個文章,對這個問題做出了解釋,至此,我才恍然大悟。
而今天,剛好無事,也就想著把這個問題記錄一下。
對于 呢,我想大多數(shù)寫過腳本的應(yīng)該都知道,這是一個命令解釋器的聲明,通常位于腳本的第一行,同時,該行還有個專業(yè)的名字,叫做 Shebang 。(不知道 Shebang 的可以去查一下)
作為對命令解釋器的聲明, 聲明了 bash 程序所在的位置,如下:??
而有了命令解釋器的位置聲明,那么,當(dāng)執(zhí)行該腳本時,系統(tǒng)就知道該去哪里找這個命令解釋器,也就是 Shebang 中指定的 bash 。
同理, 也是一樣的,包括非 Shell 腳本,如 也是同理,都是聲明命令解釋器的位置。
對于 ,說實話,剛開始我真不知道這是個什么寫法,關(guān)鍵是我之前沒見過。
而在看了 !/usr/bin/python與#!/usr/bin/env python的區(qū)別 這篇文章后,我總算是弄明白了,具體如下:??
-
首先,來看一下命令 的位置
也就是說, 確實是使用了 命令做了一些事!
但是,在我通常的用法中,我使用 都是用來查看一些環(huán)境變量的啊!難道說, 命令還有別的用法? -
查看一下 命令的定義及用法
我常用的一個 Linux 命令網(wǎng)站上對 是這么解釋的:env 命令用于顯示系統(tǒng)中已存在的環(huán)境變量,以及在定義的環(huán)境中執(zhí)行指令
那也就是說, 命令后面確實可以接一些指令!
那么, 就是這個所謂的指令?
可是, 聲明了 bash 所在位置,所以系統(tǒng)知道該去哪里找 bash !
那 呢?該語句只聲明了 env 的所在位置,并沒有聲明 bash 的位置啊,那系統(tǒng)去哪里找 bash 呢? -
原來,系統(tǒng)是去 里找 bash 的位置了!
文章中這樣提到:當(dāng)你執(zhí)行 時,它其實會去 里(也就是 /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin)這幾個路徑里去依次查找名為 python 的可執(zhí)行文件。
那么,我們來看一下 吧:??
可以看到,在 的內(nèi)容中有很多的目錄位置,而其中,bash 所在的 赫然在列!
所以說, 就是在 中挨個目錄依次去找 bash 的。
看到這里,對于 我就徹底搞明白了。也就是說:??
- 是直接指定了應(yīng)該去哪里找 bash
- 則是告訴系統(tǒng)去 包含的目錄中挨個去找吧,先找到哪個,就用哪個
文章 !/usr/bin/python與#!/usr/bin/env python的區(qū)別 的作者認(rèn)為,應(yīng)該優(yōu)先使用 這種寫法!
但是,我并不確定作者說的到底對不對,于是我又找了幾篇文章:
- Why is it better to use “#!/usr/bin/env NAME” instead of “#!/path/to/NAME” as my shebang?
- What is the difference between “#!/usr/bin/env bash” and “#!/usr/bin/bash”?
這兩個問答可以說寫的非常全面,不僅解釋了 和 的區(qū)別,還同時說明了應(yīng)該在何種場景下使用哪種寫法,并詳細(xì)闡述了其原因。
下面,就對這兩篇問答中提到的內(nèi)容及原因做一些說明:
-
優(yōu)點
- 不必在系統(tǒng)的特定位置查找命令解釋器,為多系統(tǒng)間的移植提供了極大的靈活性和便利性(某些系統(tǒng)的一些命令解釋器并不在 /bin 或 一些約定的目錄下,而是一些比較奇怪的目錄)
- 在不了解主機(jī)的環(huán)境時, 寫法可以使開發(fā)工作快速地展開
-
缺點
- 在對安全性比較看重時,該寫法會出現(xiàn)安全隱患
從 中查找命令解釋器所在的位置并匹配第一個找到的位置,這意味著可以偽造一個假的命令解釋器(如自己寫一個假的 bash),并將偽造后的命令解釋器所在目錄寫入 PATH 環(huán)境變量中并位于靠前位置,這樣,就形成了安全隱患
而 由于一般只有 root 用戶才有操作權(quán)限,所以, 這種寫法相對較為安全 - 無法傳遞多個參數(shù)(這是由于 Shebang 解析造成的,并非 env 命令的緣故)
如:
而如果使用 這種寫法的話, 會被當(dāng)成一個參數(shù),于是,根本找不到 這個命令解釋器,就會出錯 - 某些系統(tǒng) 命令的位置也比較奇怪,這種寫法會找不到 env 命令
- 在對安全性比較看重時,該寫法會出現(xiàn)安全隱患
-
優(yōu)點
- 準(zhǔn)確指出所需命令解釋器的位置
- 安全性相對較高
- 可以傳遞多個參數(shù)
-
缺點
- 移植性相對較差,很多系統(tǒng)的命令解釋器位置不一致
- 一些命令解釋器的位置記不住
- 兩個都可以
- 如果對安全性比較看重,使用
- 如果對安全性不是很看重,但對移植性(靈活性)比較看重,使用
- 看自己的意愿,喜好
- !/usr/bin/python與#!/usr/bin/env python的區(qū)別
- What is the difference between “#!/usr/bin/env bash” and “#!/usr/bin/bash”?
- Why is it better to use “#!/usr/bin/env NAME” instead of “#!/path/to/NAME” as my shebang?