iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 9
1

前言

原本以為已經差不多有 Shell 的樣子了,結果剛剛試了一下竟然不能 cd,這 Shell 真是爛得徹底,竟然連 cd 都不行,這樣也能叫做 Shell 嗎???

分析原因

各位客倌先別激動,且聽筆者我來娓娓道來

之前在 Day2Day5 有說過,Shell 收到指令之後會到系統的 PATH 裡面尋找執行檔,接著再啟動一個 Process 來執行它,如下圖

也可以用 which 來看到某個指令的執行檔放在哪裡,像 lspsmv 都是放在 /bin 裡面

但神奇的事情發生了,用 which cd 去看 cd 執行檔時卻顯示 shell built-in command,也就是所謂的 Shell 內建指令,意思是他不是一個執行檔,而是 Shell 要自己實作的指令

為什麼要自己實作 cd ?

cd 指令的目的是要改變目前 Shell 的 Working Directory,但因為 每一個 Process 有自己的 Working Directory(包括 Shell),所以 Shell 沒辦法另外開一個 Process 來幫他自身進行 cd ,而是 Shell 本身收到 cd 指令後要變更自己的資料夾

總而言之,Shell 的 cd 指令沒辦法讓其他 Process 幫忙做,一定得自己做才行

懂了這個觀念之後就來看看怎麼做吧

實作

會用到的 function

  • os.Chdir(dir string)

    Chdir 也是一個 System Call,他可以切換目前 Process 的 Working Directory,所以要用它來實作 cd

executeInput

func executeInput(input string) error {
    args := strings.Split(input, " ")
    
    if args[0] == "cd" {
        // 如果指令是 cd dirname
        // 就跑 os.Chdir(dirname)
        err := os.Chdir(args[1])
        
        // 並回傳發生的錯誤(例如資料夾不存在)
        return err
    }

    cmd := exec.Command(args[0], args[1:]...)

    // ...
}

如果使用者輸入的指令是 cd dirname,那就使用 os.Chdir 來切換 Working Directory,而不是另外開一個 Process 來跑 cd,因為 cd 一定要是自己跑

Demo

總算是可以正常 cd 囉,ls 的結果也確實是那個資料夾的

小結

其實像 cd 這樣的內建指令還有很多,像是 exitalias,只要是改變 Shell 內部狀態的功能都必須是內建指令,因為另外啟動 Process 並不能改變目前 Shell 的狀態

今天的 commit 放在這裡,有什麼問題歡迎在下方提問,沒問題的話就明天見囉~

延伸閱讀


上一篇
Day08-Prompt 大改造(二)
下一篇
Day10-存取環境變數(一)
系列文
Gosh!原來用 Go 寫一個 Unix Shell 這麼簡單30

尚未有邦友留言

立即登入留言