Ich habe ein Skript, das ich auf zwei Computern ausführen möchte. Diese beiden Maschinen erhalten Kopien des Skripts aus demselben Git-Repository. Das Skript muss mit dem richtigen Interpreter ausgeführt werden (z. B. zsh
).
Leider beides env
und zsh
leben an verschiedenen Orten auf den lokalen und entfernten Rechnern:
Remote-Computer
$ which env
/bin/env
$ which zsh
/some/long/path/to/the/right/zsh
Lokaler Computer
$ which env
/usr/bin/env
$which zsh
/usr/local/bin/zsh
Wie kann ich den Shebang so einrichten, dass das Skript als /path/to/script.sh
ausgeführt wird verwendet immer den Zsh
verfügbar in PATH
?
Akzeptierte Antwort:
Sie können dies nicht direkt durch Shebang lösen, da Shebang rein statisch ist. Was Sie tun könnten, ist, einen »geringsten Multiplikator« (aus Shell-Perspektive) im Shebang zu haben und Ihr Skript mit der richtigen Shell erneut auszuführen, wenn dieses LCM nicht zsh ist. Mit anderen Worten:Lassen Sie Ihr Skript von einer Shell ausführen, die auf allen Systemen zu finden ist, testen Sie auf ein zsh
-only-Funktion und wenn der Test falsch ist, führen Sie das Skript exec
aus mit zsh
, wo der Test erfolgreich ist und Sie einfach fortfahren.
Eine einzigartige Funktion in zsh
, ist beispielsweise das Vorhandensein von $ZSH_VERSION
Variable:
#!/bin/sh -
[ -z "$ZSH_VERSION" ] && exec zsh - "$0" ${1+"[email protected]"}
# zsh-specific stuff following here
echo "$ZSH_VERSION"
In diesem einfachen Fall wird das Skript zunächst von /bin/sh
ausgeführt (Alle Unix-ähnlichen Systeme nach den 80ern verstehen #!
und haben einen /bin/sh
, entweder Bourne oder POSIX, aber unsere Syntax ist mit beiden kompatibel). Wenn $ZSH_VERSION
ist nicht set, das Skript exec
’s selbst durch zsh
. Wenn $ZSH_VERSION
gesetzt ist (bzw. das Skript bereits durch zsh
gelaufen ist ), wird der Test einfach übersprungen. Voilà.
Dies schlägt nur fehl, wenn zsh
ist nicht im $PATH
überhaupt.
Bearbeiten: Um sicherzugehen, führen Sie nur exec
aus ein zsh
An den üblichen Stellen könnten Sie so etwas wie
for sh in /bin/zsh
/usr/bin/zsh
/usr/local/bin/zsh; do
[ -x "$sh" ] && exec "$sh" - "$0" ${1+"[email protected]"}
done
Dies könnte Sie vor versehentlichem exec
bewahren etwas in Ihren $PATH
einfügen was nicht der zsh
ist du erwartest.