在腳本啟動後選擇解釋器,例如 hashbang 中的 if/else
有沒有辦法動態選擇執行腳本的解釋器?我有一個在兩個不同系統上執行的腳本,而我要使用的解釋器位於兩個系統上的不同位置。我最終不得不在每次切換時更改 hashbang 行。我想做一些與此邏輯等效的事情(我意識到這個確切的構造是不可能的):
if running on system A: #!/path/to/python/on/systemA elif running on system B: #!/path/on/systemB #Rest of script goes here
或者更好的是這樣,以便它嘗試使用第一個解釋器,如果找不到它使用第二個:
try: #!/path/to/python/on/systemA except: #!path/on/systemB #Rest of script goes here
顯然,我可以改為執行它,
/path/to/python/on/systemA myscript.py
或者/path/on/systemB myscript.py
取決於我所在的位置,但我實際上有一個啟動的包裝腳本myscript.py
,所以我想以程式方式而不是手動指定 python 解釋器的路徑。
不,那行不通。這兩個字元
#!
絕對需要是文件中的前兩個字元(無論如何,您將如何指定解釋 if 語句的內容?)。這構成了exec()
函式族在確定它們將要執行的文件是腳本(需要解釋器)還是二進製文件(不需要解釋器)時檢測到的“幻數”。shebang 行的格式非常嚴格。它需要有一個解釋器的絕對路徑,並且最多有一個參數。
你可以做的是使用
env
:#!/usr/bin/env interpreter
現在,通常的路徑
env
是,但從技術上講,這並不能保證。/usr/bin/env
這允許您調整
PATH
每個系統上的環境變數,以便找到interpreter
(無論是它bash
,python
還是perl
您擁有的任何東西)。這種方法的一個缺點是不可能將參數可移植地傳遞給解釋器。
這意味著
#!/usr/bin/env awk -f
和
#!/usr/bin/env sed -f
不太可能在某些系統上工作。
另一個明顯的方法是使用 GNU 自動工具(或一些更簡單的模板系統)來查找解釋器,並在一個
./configure
步驟中將正確的路徑放入文件中,這將在每個系統上安裝腳本時執行。也可以求助於使用顯式解釋器執行腳本,但這顯然是您要避免的:
$ sed -f script.sed
您總是可以製作一個包裝腳本來為實際程序找到正確的解釋器:
#!/bin/bash if something ; then interpreter=this script=/some/path/to/program.real flags=() else interpreter=that script=/other/path/to/program.real flags=(-x -y) fi exec "$interpreter" "${flags[@]}" "$script" "$@"
將包裝器保存在使用者的
PATH
as 中program
,並將實際程序放在一邊或使用其他名稱。
#!/bin/bash
由於flags
數組,我在 hashbang 中使用過。如果您不需要儲存可變數量的標誌等並且可以不使用它,則腳本應該可移植地與#!/bin/sh
.