Welche Shell führt Skripte aus, wenn zu Beginn keine Shebang-Zeile (#! / Path / to / shell) vorhanden ist? Ich gehe von / bin / sh aus, kann es aber nicht bestätigen.
Der Kernel weigert sich solche Skripte und kehrt zur Ausführung ENOEXEC, so dass das genaue Verhalten auf dem Programm hängt führen Sie ein solches Skript aus .
- bash 4.2.39 - benutzt sich selbst
- busybox-ash 1.20.2 - nutzt sich selbst
- Strich 0.5.7 - läuft / bin / sh
- fish 1.23.1 - beschwert sich über ENOEXEC und gibt der falschen Datei die Schuld
- AT & T ksh 93u + 2012.08.01 - nutzt sich selbst
- mksh R40f - Läuft / bin / sh
- pdksh 5.2.14 - Läuft / bin / sh
- sh-heirloom 050706 - nutzt sich selbst
- tcsh 6.18.01 - Läuft / bin / sh
- zsh 5.0.0 - Läuft / bin / sh
- cmd.exe 5.1.2600 - schaut dich komisch an.
Funktioniert in glibcexecv()
oder gibt execve()
einfach ENOEXEC zurück. Aber execvp()
versteckt diesen Fehlercode und ruft automatisch / bin / sh auf. (Dies ist in exec (3p) dokumentiert .)
Was wird als "Best Practices" beim Schreiben von Shell-Skripten angesehen, die auf jeder Plattform ausgeführt werden können? (ok, das ist irgendwie offen)
Halten Sie sich entweder sh
nur an POSIX-definierte Funktionen, oder gehen Sie einfach zu Bash (was allgemein verfügbar ist) und erwähnen Sie es in Ihren Anforderungen, wenn Sie es verteilen.
(Jetzt, wo ich darüber nachdenke, wäre Perl - oder vielleicht Python - noch portabler, ganz zu schweigen von einer besseren Syntax.)
Füge immer die Shebang-Linie hinzu. Verwenden Sie bei Verwendung von bash oder zsh #!/usr/bin/env bash
den Pfad der Shell , anstatt ihn fest zu codieren. (Es ist jedoch garantiert, dass die POSIX-Shell aktiviert ist. /bin/sh
Überspringen Sie env
in diesem Fall.)
(Leider ist sogar /bin/sh
nicht immer dasselbe. Das GNU- Autoconf- Programm muss sich mit vielen verschiedenen Macken auseinandersetzen .)
Ist es möglich, ein Skript zu schreiben, das versucht, zsh zu verwenden und auf bash zurückgreift, wenn zsh nicht verfügbar ist? Ich habe versucht, zwei Shebang-Zeilen zu setzen, wie unten, aber es ist nur ein Fehler mit einem schlechten Interpreter: / bin / zsh: Keine solche Datei oder kein solches Verzeichnis , wenn ich es auf einer Maschine ohne zsh versuche.
Es kann nur eine Shebang-Linie geben. Alles, was nach dem Newline-Zeichen steht, wird nicht einmal vom Kernel gelesen und von Shells als Kommentar behandelt.
Es ist möglich , ein Skript zu schreiben, das als ausgeführt wird #!/bin/sh
, prüft, welche Shell verfügbar ist und ausgeführt wird, exec zsh "$0" "$@"
oder exec bash "$0" "$@"
abhängig vom Ergebnis. Die von bash und zsh verwendete Syntax ist jedoch an verschiedenen Stellen so unterschiedlich, dass ich dies aus Gründen der eigenen Vernunft nicht empfehlen würde .
strace -f -e fork,clone,execve
. Einige Muscheln wurden/bin/sh
nach dem Scheitern ausgeführt. andere interpretierten das Drehbuch selbst.readlink /proc/$$/exe
.csh
undtcsh
hängt das Verhalten davon ab, ob das Skript mit beginnt#
(in diesem Fall rufen sie sich selbst anstelle von sh auf, um das Skript zu interpretieren). Das geht auf die Zeit zurück, in der csh Kommentare unterstützte, jedoch nicht die Bourne-Shell. A#
war also ein Hinweis darauf, dass es sich um ein csh-Skript handelte.1) Die aktuelle Shell, in der Sie ausgeführt werden. (Welche Shell auch immer)
2) Bleibe beim selben Shell-Typ (bash / dash / ash / csh / was auch immer dein Geschmack ist) und stelle sicher, dass deine "unterstützten Plattformen" die Shell installieren, die du standardmäßig verwenden möchtest. Versuchen Sie außerdem, allgemein verfügbare Befehle auf Systemen zu verwenden. Vermeiden Sie maschinenspezifische Optionen.
3) Es gibt keine wirkliche "Wenn-Dann-Sonst" -Logik für die
interpreter directive
. Sie sollten eine Shell angeben, die auf allen Systemen vorhanden sein soll, die Sie unterstützen möchten ...#!/bin/bash
oder eine generische angeben,#!/bin/sh
solange Ihr Skript über alle Shells hinweg ziemlich generisch ist.quelle