Mám skript, který chci spustit na dvou počítačích. Tyto dva stroje získávají kopie skriptu ze stejného úložiště git. Skript musí běžet se správným interpretem (např. zsh
).
Bohužel obě env
a zsh
žijí na různých místech v místních a vzdálených počítačích:
Vzdálený počítač
$ which env
/bin/env
$ which zsh
/some/long/path/to/the/right/zsh
Místní počítač
$ which env
/usr/bin/env
$which zsh
/usr/local/bin/zsh
Jak mohu nastavit shebang tak, aby byl skript spuštěn jako /path/to/script.sh
vždy používá Zsh
dostupné v PATH
?
Přijatá odpověď:
Nemůžete to vyřešit přímo pomocí shebang, protože shebang je čistě statický. Co byste mohli udělat, je mít nějaký »nejméně společný násobič« (z pohledu shellu) v shebang a znovu spustit skript se správným shellem, pokud tento LCM není zsh. Jinými slovy:Nechte svůj skript spustit pomocí shellu nalezeného na všech systémech, otestujte zsh
-pouze funkce a pokud test dopadne špatně, použijte skript exec
pomocí zsh
, kde test uspěje a vy jen pokračujete.
Jedna jedinečná funkce v zsh
, je například přítomnost $ZSH_VERSION
proměnná:
#!/bin/sh -
[ -z "$ZSH_VERSION" ] && exec zsh - "$0" ${1+"[email protected]"}
# zsh-specific stuff following here
echo "$ZSH_VERSION"
V tomto jednoduchém případě je skript nejprve spuštěn pomocí /bin/sh
(všechny systémy podobné Unixu po 80. letech rozumí #!
a mít /bin/sh
, buď Bourne nebo POSIX, ale naše syntaxe je kompatibilní s oběma). Pokud $ZSH_VERSION
není set, skript exec
's sám přes zsh
. Pokud $ZSH_VERSION
je nastaveno (resp. skript již běží přes zsh
), test je jednoduše přeskočen. Voilà.
Toto selže pouze v případě, že zsh
není v $PATH
vůbec.
Upravit: Abyste se ujistili, musíte pouze exec
zsh
na obvyklých místech můžete použít něco jako
for sh in /bin/zsh
/usr/bin/zsh
/usr/local/bin/zsh; do
[ -x "$sh" ] && exec "$sh" - "$0" ${1+"[email protected]"}
done
To by vás mohlo zachránit před nechtěným exec
něco ve vaší $PATH
což není zsh
očekáváte.