iT邦幫忙

2026 iThome 鐵人賽

DAY 2
0
Software Development

30 天學會做一個 CLI:打造人類與 AI 都友善的現代 CLI 應用系列 第 2

命令進入 CLI 程式前:終端機、Shell 與 OS 的運作原理

  • 分享至 

  • xImage
  •  

動手建立專案前,我們先追蹤一行命令從按下 Enter 到程式被啟動前的完整流程,釐清終端機、Shell 與作業系統各自做了什麼準備,才把控制權交給 CLI 程式。

當我們在終端機輸入一行命令並按下 Enter:

$ git commit -m "fix bug"

這段「進入程式前」的準備工作由三個系統角色分工完成:

  • 終端機 (Terminal):負責接收鍵盤輸入,將輸入的純文字字串傳給 Shell,並維護畫面顯示。
  • Shell:負責解析命令語法、切分純文字參數,並在磁碟中尋找執行檔位置。
  • 作業系統 (OS):負責建立 Child Process、打包執行環境資源,正式將控制權交給 CLI 程式。

https://ithelp.ithome.com.tw/upload/images/20260913/20111896jFaFANghax.png

本系列的命令以 macOS、Linux 上的 bash 或 zsh 語法為主。Windows 讀者可以在 WSL 中使用相同命令。

階段一:終端機接收與 Shell 語法拆解

按下 Enter 後,終端機會把整行字串傳給 Shell。Shell 的第一項工作是純文字語法解析:辨識要執行的命令名稱,並處理引號、跳脫字元、變數與萬用字元,拆解出要傳給程式的參數清單。

git commit -m "fix bug" 這個例子中,Shell 的解析結果如下:

https://ithelp.ithome.com.tw/upload/images/20260913/20111896ph5WZFkkvV.png

"fix bug" 被雙引號包住,因此 Shell 會把它拆成單一參數 fix bug,而不是按空白切成 fixbug 兩個參數。引號是寫給 Shell 看的語法,解析完後不會成為參數內容本身。

此時 Shell 只知道 git 是命令名稱,後面跟著三個文字參數;Shell 完全不知道 commit 代表建立提交,也不知道 -m 代表指定提交訊息。

階段二:Shell 搜尋 PATH 尋找執行檔

確定要執行的命令名稱是 git 後,Shell 需要找到這個執行檔在磁碟上的實際位置。如果輸入的是完整路徑(如 /usr/bin/git)或相對路徑(如 ./my-cli),Shell 會直接開啟該路徑;如果只輸入檔名 git,Shell 就會按照 PATH 環境變數列出的目錄依序搜尋。

PATH 是一組以冒號分隔的目錄清單:

$ printenv PATH
/usr/local/bin:/usr/bin:/bin

當我們輸入 git 時,Shell 會由左至右依序檢查各目錄中是否存在名為 git 的可執行檔:

  1. /usr/local/bin/git
  2. /usr/bin/git
  3. /bin/git

只要在其中一個目錄(例如 /usr/bin/git)找到檔案,搜尋就會立刻停止。如果搜尋完所有目錄都找不到,Shell 就會顯示 zsh: command not found: git

階段三:作業系統建立 Process 與配置初始執行環境

Shell 找到 /usr/bin/git 後,會向作業系統發出系統呼叫(System Call),請求建立一個全新的 Child Process 來執行它。

作業系統在啟動 Process 前,會為這個 Process 配置好初始執行環境,主要包含 4 種核心資源:

  • 參數清單(argv):Shell 解析後的字串陣列 ["git", "commit", "-m", "fix bug"]
  • 工作目錄(cwd):使用者當前所在的目錄,作為程式處理相對路徑的基準點。
  • 環境變數(env):包含 PATHUSER 等由 Shell 繼承給 Child Process 的變數。
  • 標準 I/O 通道:連接到終端機的標準輸入(stdin)、標準輸出(stdout)與標準錯誤(stderr)。

配置好環境與資源後,作業系統將 Process 載入記憶體,並把控制權正式移交給 git 程式。

階段四:交還控制權與結束清理

git 程式被啟動後,它會讀取 argv 中的參數、執行業務邏輯,並透過 stdout/stderr 印出結果。

程式完成工作後,會向作業系統回傳一個整數狀態碼,稱為退出碼(Exit Code):

  • 0:代表程式順利執行成功。
  • 0(例如 1128:代表執行失敗。
$ git commit -m "fix bug"
[main 7a3f91b] fix bug
 1 file changed, 2 insertions(+)

$ echo $?
0

作業系統收到 Exit Code 後清理 Process 資源,並通知等待中的 Shell。Shell 取得 Exit Code 知道程式已執行完成,隨即重新印出提示符號 $,等待使用者輸入下一個命令。

這就是一行命令在進入 CLI 程式前,終端機、Shell 與作業系統所完成的準備與轉手流程。下一篇我們將站在 CLI 開發者的角度,看程式接手後內部如何拆解與設計 Command、Arg 與 Flag。


上一篇
為什麼要學習開發CLI
系列文
30 天學會做一個 CLI:打造人類與 AI 都友善的現代 CLI 應用2
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言