在學習程式時,如果希望在自己的電腦上開發,絕大多數的語言的第一課一定就會是,環境設定,只要設定好,終端機就好像被施展魔法一樣,多了一個指令可以用,但到底是為什麼會做到,我從來都是一知半解,所以希望可以在這邊好好記錄下來
在這邊我們以ping這個指令作為範例,當我們在命令列中打上
❯ ping 127.0.0.1
PING 127.0.0.1 (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.052 ms
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.196 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.194 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.137 ms
這時候可以看到程式被順利運行了,但其實上,這個命令卻是執行為在/sbin/ping
的執行檔,所以上方的命令等義於
❯ /sbin/ping 127.0.0.1 ─╯
PING 127.0.0.1 (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.068 ms
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.132 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.207 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.120 ms
那為什麼他有辦法判斷說你的指令對應到這個檔案呢?這個就是環境路徑的用途了
原理如下
在你每一次的shell打開時,你的shell會先將一個名叫$PATH
的環境變數讀出來,接下來你的每個命令下下去時,他會根據你$PATH
提供的路徑,由前而後的來讀取這些資料夾中有沒有你下的指令的同名稱的執行檔,如果有,就直接執行,如果沒有,則回傳command not found
比如在我目前的電腦中
❯ echo $path
/opt/homebrew/opt/openjdk@17/bin /Users/kevin/.google-cloud-sdk/bin /Users/kevin/.krew/bin /opt/homebrew/opt/curl/bin /Users/kevin/.nvm/versions/node/v22.15.1/bin /Users/kevin/.gvm/pkgsets/go1.23/global/bin /Users/kevin/.gvm/pkgsets/go1.23/global/bin /Users/kevin/.gvm/gos/go1.23/bin /Users/kevin/.gvm/pkgsets/go1.23/global/overlay/bin /Users/kevin/.gvm/bin /Library/Frameworks/Python.framework/Versions/3.12/bin /opt/homebrew/bin /opt/homebrew/sbin /usr/local/bin /System/Cryptexes/App/usr/bin /usr/bin /bin /usr/sbin /sbin /var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin /var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin /var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin /Applications/VMware Fusion.app/Contents/Public /Users/kevin/.cargo/bin /Applications/iTerm.app/Contents/Resources/utilities /Users/kevin/.orbstack/bin
在裡面有看到/sbin
這個資料夾,所以我們的ping才能正常被執行
如果要查詢執行檔的實際位置,可以透過which
這個工具來幫忙
❯ which ping
/sbin/ping
如果有多個同名稱的執行檔,則shell會依據path的順序,誰在前面就使用誰,比如目前我的電腦有安裝好幾個python3,而可以看到我的path中,/Library/Frameworks
這個資料夾的順位比較前面,所以就會被優先使用
❯ which -a python3
/Library/Frameworks/Python.framework/Versions/3.12/bin/python3
/opt/homebrew/bin/python3
/usr/local/bin/python3
/usr/bin/python3
如果要使用其他的python3,只要使用完整的路徑就可以摟
❯ python3 --version
Python 3.12.3
❯ /usr/bin/python3 --version
Python 3.9.6