在駭客軍團的第 5 集約 39 分附近,因為失去「黑暗軍團」的幫忙,駭客想要馬上執行惡意程式來破壞「鋼山」公司的主機,如果有注意到的話,終端機的指令大致如下:
$ cd /opt/2/task/22/fdinfo/fsociety/hscripts $ ./fuxsocy
影片中直接使用 ./
來執行特定指令或 script,但並沒有特別指定要用 shell 或是要用 python?那這樣的話,電腦怎麼知道是執行檔可以直接載入記憶體中執行?或是否需要其他直譯器來執行?
Linux 和 Unix 在設計時有想到這個問題,目前大多數的解決方法,就是在檔案的第一行最前面加上 #! 符號作為標示,在標示後面跟著直譯器的絕對路徑,這樣就可以知道開發者需要使用哪個直譯器來跑這個 script。這個作法後來被稱為「shebang」。
shebang
在 Linux 或 Unix 上要處理簡單的事務時,通常會寫個小的 shell script 來做判斷,例如檢查硬碟是不是快要滿了 (範例是隨便寫的,真的需要請找更好的寫法 XD):
CAP=`df /dev/sda2 | tail -n 1 | awk '{print $5}' | cut -d'%' -f 1` if [[ $CAP > 90 ]]; then mail -s 'disk is almost full' admin@your.domain else echo yooo fi
上面這段 script 只需要使用常見的 sh
、bash
或 zsh
,只需要確認檔案具有執行權限 (chmod +x
) 即可直接呼叫執行,也就是在 shell 這樣寫:./script-name
即可。
那如果今天 script 不是用 shell script 的語法,而是使用 python 或是 perl 寫的,直接執行會發生什麼事?
$ ./hello ./hello: line 1: syntax error near unexpected token `"Hello World"' ./hello: line 1: `print("Hello World")'
系統預設會用使用者當下的 shell 來跑這個 script,所以會看到錯誤訊息。
若要指定使用特定的直譯器來跑 script,則在 script 的第一行使用 #!
開頭,並再後方寫下直譯器的路徑。修改後的檔案如下:
#!/bin/bash CAP=`df /dev/sda2 | tail -n 1 | awk '{print $5}' | cut -d'%' -f 1` if [[ $CAP > 90 ]]; then mail -s 'disk is almost full' admin@your.domain else echo yooo fi
同理,如果需要使用 python 來跑,開頭則改成 #!/usr/bin/python3.8
。
env
到這裡,大家或許會發現一個問題:bash 的路徑在 Linux 和 Unix 不一樣,把路徑寫死會不會炸?
答案是會!就拿 Ubuntu 和 FreeBSD 來比較吧,Ubuntu 中 bash 的路徑為 /bin/bash
;FreeBSD 中 bash 的路徑則為 /usr/local/bin/bash
。所以這個時候就要來介紹 env
這個工具。
單獨執行 env
這個指令 (不加參數),則 env
會列出使用者環境中所有的環境參數,常見的參數如:SHELL
、LANG
、HOME
、PATH
等。若在中加上執行檔名稱,則 env 會從 PATH 參數指定的路徑中,找到、並執行指令,也就是說只要 PATH
環境參數設定無誤,env
也可以找到透過 nvm
安裝的 node
位置。
另外使用 env
還有一個好處:在大多數的 Linux、Unix 系統上,env
的路徑幾乎都相同 /usr/bin/env
。因此在 shebang 中使用 env
不太需要擔心環境不同的問題。
因此,建議將 shebang
的開頭都改用 env
來自動偵測直譯器的路徑:
#!/usr/bin/env bash CAP=`df /dev/sda2 | tail -n 1 | awk '{print $5}' | cut -d'%' -f 1` if [[ $CAP > 90 ]]; then mail -s 'disk is almost full' admin@your.domain else echo yooo fi
相關文章: