Bash Shebang 與 Script 執行方式指南

Bash Shebang 與 Script 執行方式指南

Shebang 是 Shell Script 第一行的特殊宣告,用來告訴作業系統應該使用哪一個 Interpreter 執行這份檔案。

它最常用於:


1. Shebang 是什麼?

Shebang 的基本格式是:

#!<interpreter 路徑>

例如 Bash Script 常見的寫法:

#!/usr/bin/env bash

其中:

部分 說明
#! Shebang 標記
/usr/bin/env 從目前的 PATH 尋找程式
bash 要使用的 Interpreter

當執行:

./script.sh

作業系統會讀取 Script 第一行,並將檔案交給指定的 Interpreter。

例如:

#!/usr/bin/env bash

大致相當於:

/usr/bin/env bash ./script.sh

Shebang 必須位於檔案的第一行,前面不能有空白或空行。


2. Script 的三種執行方式

常見的執行方式有:

./script.sh
bash script.sh
sh script.sh

它們的差異如下:

執行方式 使用的 Interpreter 使用 Shebang 需要執行權限
./script.sh 由 Shebang 決定
bash script.sh 強制使用 Bash
sh script.sh 強制使用 sh

3. 使用 ./script.sh

執行:

./script.sh

系統會根據 Script 第一行的 Shebang 選擇 Interpreter。

例如:

#!/usr/bin/env bash

代表使用 Bash 執行。

直接執行前,需要先設定執行權限:

chmod +x script.sh

接著執行:

./script.sh

如果沒有執行權限,可能會出現:

Permission denied

可以查看檔案權限:

ls -l script.sh

具有執行權限時,通常會看到:

-rwxr-xr-x

其中的 x 代表可執行。


4. 使用 bash script.sh

執行:

bash script.sh

代表直接要求 Bash 讀取並執行 Script。

這種方式:

即使 Script 沒有 Shebang,仍然可以執行:

bash script.sh

但仍建議在正式 Script 中加入 Shebang,讓檔案的執行需求更清楚。


5. 使用 sh script.sh

執行:

sh script.sh

代表強制使用 sh 解讀 Script。

即使第一行寫著:

#!/usr/bin/env bash

Shebang 也會被忽略。

如果 Script 使用 Bash 專屬語法,可能會出現錯誤:

syntax error near unexpected token `<'

例如以下 Process Substitution 是 Bash 語法:

while read -r line; do
    echo "$line"
done < <(printf '%s\n' one two three)

使用 Bash 執行:

bash script.sh

通常可以正常運作。

使用 sh 執行:

sh script.sh

則可能出現語法錯誤。


6. 常見 Bash 專屬語法

以下語法不保證能在一般 sh 中使用。

條件判斷

[[ -f "$file" ]]

POSIX sh 通常使用:

[ -f "$file" ]

Process Substitution

done < <(some_command)

Here String

read -r value <<< "$text"

ANSI-C Quoting

separator=

### 陣列

```bash
items=("one" "two" "three")

關聯式陣列

declare -A config

如果 Script 使用這些功能,應該明確使用 Bash:

#!/usr/bin/env bash

並使用以下方式執行:

./script.sh

或:

bash script.sh

7. 常見 Bash Shebang

使用 /bin/bash

#!/bin/bash

直接指定系統中的 /bin/bash

優點:

缺點:


使用 /usr/bin/env bash

#!/usr/bin/env bash

透過目前的 PATH 尋找 Bash。

優點:

缺點:

一般跨平台 Script 常使用:

#!/usr/bin/env bash

使用 /usr/bin/bash

#!/usr/bin/bash

直接指定 /usr/bin/bash

這個路徑不是所有作業系統都有,因此通常不適合作為跨平台 Script 的預設值。

可以使用以下指令查看 Bash 的實際位置:

command -v bash

可能輸出:

/bin/bash

或:

/opt/homebrew/bin/bash

8. /bin/bash/usr/bin/env bash 的差異

項目 #!/bin/bash #!/usr/bin/env bash
Bash 來源 固定 /bin/bash PATH 尋找
可攜性 較低 較高
執行版本 較固定 依環境而定
是否受 PATH 影響
適合情境 固定 Server、Container 開發工具、跨平台專案

如果執行環境完全可控,可以使用:

#!/bin/bash

如果 Script 需要在不同 Linux、macOS 或開發環境中使用,可以考慮:

#!/usr/bin/env bash

9. macOS 的 Bash 版本

macOS 內建的 Bash 通常位於:

/bin/bash

但內建版本可能較舊。

使用 Homebrew 安裝新版 Bash:

brew install bash

Apple Silicon Mac 常見路徑:

/opt/homebrew/bin/bash

Intel Mac 常見路徑:

/usr/local/bin/bash

檢查目前 Bash 位置:

command -v bash

檢查 Bash 版本:

bash --version

如果使用:

#!/bin/bash

通常會執行 macOS 內建 Bash。

如果使用:

#!/usr/bin/env bash

則會執行 PATH 中最先找到的 Bash。


10. Shebang 與 Script 參數

不建議在 Shebang 中加入多個參數:

#!/usr/bin/env bash -e

部分系統可能會將:

bash -e

視為完整的程式名稱,而不是 bash 加上 -e 參數。

比較穩定的方式是將選項放在 Script 內容中:

#!/usr/bin/env bash

set -Eeuo pipefail

各選項的作用:

選項 說明
-e 指令執行失敗時停止
-u 使用未定義變數時報錯
-o pipefail Pipeline 中任一指令失敗即視為失敗
-E ERR Trap 可以在函式等環境中繼承

11. 推薦的 Bash Script 開頭

跨平台開發工具可以使用:

#!/usr/bin/env bash

set -Eeuo pipefail

固定 Linux、Server 或 Container 環境可以使用:

#!/bin/bash

set -Eeuo pipefail

簡單的 Script 不一定需要啟用所有嚴格模式。

例如:

#!/usr/bin/env bash

set -e

echo "Starting script..."

應依照 Script 的錯誤處理需求選擇適合的設定。


12. 常見問題

為什麼 ./script.sh 可以,但 sh script.sh 不行?

因為:

./script.sh

會根據 Shebang 使用 Bash。

sh script.sh

則會忽略 Shebang,強制使用 sh

如果 Script 包含 Bash 專屬語法,使用 sh 就可能失敗。

.sh 副檔名會決定使用哪個 Shell 嗎?

不會。

以下檔名都可以是 Bash Script:

script.sh
script
deploy
backup

真正決定 Interpreter 的是:

為什麼 bash script.sh 不需要執行權限?

因為真正被執行的是 bash

script.sh 只是 Bash 讀取的輸入檔案,因此只需要讀取權限。

為什麼 ./script.sh 需要執行權限?

因為作業系統會將 script.sh 視為可執行檔案,讀取其 Shebang 後再啟動對應的 Interpreter。


13. 語法檢查與除錯

在執行前檢查 Bash 語法:

bash -n script.sh

如果沒有輸出,通常代表沒有發現語法錯誤。

顯示實際執行的指令:

bash -x script.sh

也可以在 Script 中暫時加入:

set -x

停止顯示執行指令:

set +x

確認 Script 第一行:

head -n 1 script.sh

查看是否包含 Windows 換行字元:

file script.sh

如果 Script 使用 CRLF,Shebang 可能被解析成:

/usr/bin/env: ‘bash\r’: No such file or directory

可以轉換為 Unix 換行格式:

dos2unix script.sh

重點整理


延伸閱讀


### 陣列

{{CODE_BLOCK_26}}

### 關聯式陣列

{{CODE_BLOCK_27}}

如果 Script 使用這些功能,應該明確使用 Bash:

{{CODE_BLOCK_28}}

並使用以下方式執行:

{{CODE_BLOCK_29}}

或:

{{CODE_BLOCK_30}}

---

## 7. 常見 Bash Shebang

### 使用 `/bin/bash`

{{CODE_BLOCK_31}}

直接指定系統中的 `/bin/bash`。

優點:

- Bash 路徑明確
    
- 不受使用者 `PATH` 影響
    
- 適合固定的 Linux、Docker 或 CI 環境
    

缺點:

- Bash 不一定存在於 `/bin/bash`
    
- 在部分特殊系統中可攜性較低
    

---

### 使用 `/usr/bin/env bash`

{{CODE_BLOCK_32}}

透過目前的 `PATH` 尋找 Bash。

優點:

- 跨環境可攜性較高
    
- 可以使用 Homebrew、Nix 等工具安裝的 Bash
    
- 適合開源專案與開發工具
    

缺點:

- 實際執行的 Bash 取決於 `PATH`
    
- 不同使用者可能執行到不同版本的 Bash
    

一般跨平台 Script 常使用:

{{CODE_BLOCK_33}}

---

### 使用 `/usr/bin/bash`

{{CODE_BLOCK_34}}

直接指定 `/usr/bin/bash`。

這個路徑不是所有作業系統都有,因此通常不適合作為跨平台 Script 的預設值。

可以使用以下指令查看 Bash 的實際位置:

{{CODE_BLOCK_35}}

可能輸出:

{{CODE_BLOCK_36}}

或:

{{CODE_BLOCK_37}}

---

## 8. `/bin/bash` 與 `/usr/bin/env bash` 的差異

|項目|`#!/bin/bash`|`#!/usr/bin/env bash`|
|---|---|---|
|Bash 來源|固定 `/bin/bash`|從 `PATH` 尋找|
|可攜性|較低|較高|
|執行版本|較固定|依環境而定|
|是否受 `PATH` 影響|否|是|
|適合情境|固定 Server、Container|開發工具、跨平台專案|

如果執行環境完全可控,可以使用:

{{CODE_BLOCK_38}}

如果 Script 需要在不同 Linux、macOS 或開發環境中使用,可以考慮:

{{CODE_BLOCK_39}}

---

## 9. macOS 的 Bash 版本

macOS 內建的 Bash 通常位於:

{{CODE_BLOCK_40}}

但內建版本可能較舊。

使用 Homebrew 安裝新版 Bash:

{{CODE_BLOCK_41}}

Apple Silicon Mac 常見路徑:

{{CODE_BLOCK_42}}

Intel Mac 常見路徑:

{{CODE_BLOCK_43}}

檢查目前 Bash 位置:

{{CODE_BLOCK_44}}

檢查 Bash 版本:

{{CODE_BLOCK_45}}

如果使用:

{{CODE_BLOCK_46}}

通常會執行 macOS 內建 Bash。

如果使用:

{{CODE_BLOCK_47}}

則會執行 `PATH` 中最先找到的 Bash。

---

## 10. Shebang 與 Script 參數

不建議在 Shebang 中加入多個參數:

{{CODE_BLOCK_48}}

部分系統可能會將:

{{CODE_BLOCK_49}}

視為完整的程式名稱,而不是 `bash` 加上 `-e` 參數。

比較穩定的方式是將選項放在 Script 內容中:

{{CODE_BLOCK_50}}

各選項的作用:

|選項|說明|
|---|---|
|`-e`|指令執行失敗時停止|
|`-u`|使用未定義變數時報錯|
|`-o pipefail`|Pipeline 中任一指令失敗即視為失敗|
|`-E`|讓 `ERR` Trap 可以在函式等環境中繼承|

---

## 11. 推薦的 Bash Script 開頭

跨平台開發工具可以使用:

{{CODE_BLOCK_51}}

固定 Linux、Server 或 Container 環境可以使用:

{{CODE_BLOCK_52}}

簡單的 Script 不一定需要啟用所有嚴格模式。

例如:

{{CODE_BLOCK_53}}

應依照 Script 的錯誤處理需求選擇適合的設定。

---

## 12. 常見問題

### 為什麼 `./script.sh` 可以,但 `sh script.sh` 不行?

因為:

{{CODE_BLOCK_54}}

會根據 Shebang 使用 Bash。

{{CODE_BLOCK_55}}

則會忽略 Shebang,強制使用 `sh`。

如果 Script 包含 Bash 專屬語法,使用 `sh` 就可能失敗。

### `.sh` 副檔名會決定使用哪個 Shell 嗎?

不會。

以下檔名都可以是 Bash Script:

{{CODE_BLOCK_56}}

真正決定 Interpreter 的是:

- 使用 `./script` 時的 Shebang
    
- 命令列明確指定的 `bash` 或 `sh`
    

### 為什麼 `bash script.sh` 不需要執行權限?

因為真正被執行的是 `bash`。

`script.sh` 只是 Bash 讀取的輸入檔案,因此只需要讀取權限。

### 為什麼 `./script.sh` 需要執行權限?

因為作業系統會將 `script.sh` 視為可執行檔案,讀取其 Shebang 後再啟動對應的 Interpreter。

---

## 13. 語法檢查與除錯

在執行前檢查 Bash 語法:

{{CODE_BLOCK_57}}

如果沒有輸出,通常代表沒有發現語法錯誤。

顯示實際執行的指令:

{{CODE_BLOCK_58}}

也可以在 Script 中暫時加入:

{{CODE_BLOCK_59}}

停止顯示執行指令:

{{CODE_BLOCK_60}}

確認 Script 第一行:

{{CODE_BLOCK_61}}

查看是否包含 Windows 換行字元:

{{CODE_BLOCK_62}}

如果 Script 使用 CRLF,Shebang 可能被解析成:

{{CODE_BLOCK_63}}

可以轉換為 Unix 換行格式:

{{CODE_BLOCK_64}}

---

## 重點整理

- Shebang 是 Script 第一行的 `#!` 宣告。
- Shebang 用來指定執行 Script 的 Interpreter。
- `./script.sh` 會根據 Shebang 執行。
- `bash script.sh` 會強制使用 Bash。
- `sh script.sh` 會強制使用 `sh` 並忽略 Shebang。
- `.sh` 副檔名不會決定使用哪一個 Shell。
- Bash Script 不應隨意使用 `sh script.sh` 執行。
- 跨平台 Script 通常使用 `#!/usr/bin/env bash`。
- 固定 Linux 環境可以使用 `#!/bin/bash`。
- Script 執行選項建議寫在內容中,不要放在 Shebang。
- 可以使用 `bash -n script.sh` 進行語法檢查。

---

## 延伸閱讀

- sh script.sh vs ./script.sh Execution Differences — `sh script.sh` 與 `./script.sh` 執行差異的精簡版整理。
- shell 快捷鍵指南 — 終端機日常操作快捷鍵。