Shell-Script

在腳本啟動後選擇解釋器,例如 hashbang 中的 if/else

  • March 22, 2020

有沒有辦法動態選擇執行腳本的解釋器?我有一個在兩個不同系統上執行的腳本,而我要使用的解釋器位於兩個系統上的不同位置。我最終不得不在每次切換時更改 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(無論是它bashpython還是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" "$@"

將包裝器保存在使用者的PATHas 中program,並將實際程序放在一邊或使用其他名稱。

#!/bin/bash由於flags數組,我在 hashbang 中使用過。如果您不需要儲存可變數量的標誌等並且可以不使用它,則腳本應該可移植地與#!/bin/sh.

引用自:https://unix.stackexchange.com/questions/365436