哈嘍大家好,我是鹹魚
不知道小夥伴們在寫 Bash 指令碼或者說看別人的 Bash 指令碼的時候有沒有注意過指令碼的第一行
#!/bin/bash
Bash 指令碼的第一行往往以 #!
開頭,這一行稱作 shebang 行
在 類 UNIX 系統中,shebang 行用來指定指令碼的直譯器路徑,通常出現在第一行,格式如下
#! interpreter_path
shebang 行中開頭 #!
字元的作用是告訴作業系統這不是一個普通二進位制檔案,而是需要透過直譯器執行的東西
而這個直譯器則透過 #!
字元後面來指定。例如 /bin/bash
表示使用 bash 直譯器來執行該指令碼檔案
下面則是一些 Bash 指令碼的 shebang 行,指定了不同的直譯器
#! /usr/bin/perl
#! /usr/bin/awk
#! /usr/bin/python
那麼這時候小夥伴們可能就會有疑問:我忘了加 shebang 行,指令碼為什麼還能執行?
如果一個指令碼沒有新增 shebang 行來指定直譯器路徑,則預設情況下系統會使用預設的 shell 來執行指令碼,系統預設的 shell 可以透過下面的命令來檢視
# 一般情況下預設的 shell 為bash
echo $SHELL
現在我們知道了 shebang 行的作用,那麼我們現在來編寫一個指令碼並修改 shebang 行試試
test.sh 內容如下:
#!/bin/bash
echo Hello
先給 test.sh 指令碼新增一下執行許可權
chmod +x test.sh
接下來我們用幾種方式來執行這個指令碼
可以看到指令碼都成功執行了
下面我們來改一下 shebang 行,將其改成其他命令
#!/usr/bin/ls -l
echo Hello
然後我們分別用幾種方式來執行這個指令碼
上面指令碼執行的結果是不是看的一臉懵逼,說實話我一開始看到的時候也是很懵
我們先來看下這四種指令碼執行方式的區別
- bash tesh.sh
這種方式執行指令碼的原理是將 test.sh 作為引數傳給 bash 直譯器(命令)來執行,而不是 test,sh 自己來執行
這種方式執行指令碼不需要給指令碼檔案新增執行許可權、不需要寫 shebang 行指定直譯器路徑,因為指令碼是作為引數被傳給 bash 來執行
- sh test.sh
這種執行指令碼的方式跟上面的方式原理一樣,都是將指令碼作為引數傳進去,只不過是這個方式用的是 sh 直譯器(命令),而不是 bash
- /root/test.sh
這種是透過絕對路徑去執行指令碼,透過絕對路徑來執行指令碼就需要指令碼擁有執行許可權
當使用絕對路徑來執行指令碼時,作業系統需要知道該指令碼檔案所使用的直譯器型別,這就需要依靠指令碼檔案中的 shebang 行
實際上你用絕對路徑執行指令碼的時候,如果裡面定義了 shebang 行(例如 #! /bin/bash
)
那麼實際上跟下面的命令是一樣的
/bin/bash /root/test.sh
在執行指令碼的時候,作業系統會讀取指令碼的 shebang 行
如果你的 shebang 行是其他 Linux 命令而不是直譯器,那麼就會導致作業系統將你的 shebang 行當作命令,而你的指令碼則是命令的引數
就好比上面的例子,我將 shebang 行改成了 #! /usr/bin/ls -l
,當我執行指令碼的時候其實就是下面這樣的
/usr/bin/ls -l /root/test.sh
這樣會導致指令碼無法執行
- ./test.sh
這種是透過相對路徑去執行指令碼,跟上面用絕對路徑執行指令碼方式是一樣的,只不過區別是一個是相對路徑一個是絕對路徑
總結:
- shebang 行通常出現在 UNIX 系統的指令碼當中,用來指定指令碼的直譯器路徑,出現在第一行,以
#!
開頭 - 如果指令碼里面沒有定義 shebang 行,系統會去找預設的直譯器,預設直譯器用
echo $SHELL
檢視 - 用 bash 或者 sh 命令執行指令碼的時候,其實是把指令碼作為引數傳給 bash 或 sh 命令了,這時候指令碼可以不新增執行許可權、可以不需要 shebang 行
- 如果用絕對路徑或者相對路徑的方式來執行指令碼,需要指令碼擁有執行許可權,如果 shebang 行定義的不是直譯器而是其他命令,就會導致指令碼無法執行