HOWTO: Erkennen von Bash aus Shell-Skript

8

In diesem Szenario werden Benutzer aufgefordert, eine Skriptdatei zu erstellen:

%Vor%

Diese Skriptdatei verwendet möglicherweise nur die bash-Funktion, so dass wir festgestellt haben, dass die laufende Shell bash ist oder nicht.

Für andere Shells, die eine gemeinsame Syntax mit bash haben, zum Beispiel sh, zsh, ksh, möchte ich eine Warnung melden.

Was ist der zuverlässigste Weg, die aktuelle Shell unter Linux, Cygwin, OS X zu erkennen?

Was ich weiß, ist $ BASH, aber ich frage mich, ob es scheitern könnte.

    
Kan-Ru Chen 08.07.2010, 00:28
quelle

7 Antworten

13

Es gibt eine Reihe von Umgebungsvariablen, die Sie betrachten können, aber viele von ihnen werden nicht erkennen, ob eine andere Shell von bash stammt. Berücksichtigen Sie Folgendes:

%Vor%

Es gibt eine Anzahl von Variablen, die für die verschiedenen Shells spezifisch sind, außer dass sie die Angewohnheit haben, von Sub-Shells geerbt zu werden, wo die Umgebungs-Sache wirklich bricht. Das einzige, was fast funktioniert, ist ps -o command -p $$ . Dies gibt Ihnen technisch den Befehlsnamen, unter dem die Shell läuft. In den meisten Fällen wird dies funktionieren ... da Anwendungen mit einer Variante des exec Systemaufrufs gestartet werden und der Name des Befehls und der ausführbaren Datei sich unterscheiden können, ist es auch möglich, dass dies fehlschlägt. Überlegen Sie:

%Vor%

Ein weiterer Trick ist die Verwendung von lsof -p $$ | awk '(NR==2) {print }' . Dies ist wahrscheinlich so nah wie möglich, wenn Sie das Glück haben, lsof handy zu haben.

    
D.Shawley 08.07.2010, 01:38
quelle
10

Das funktioniert auch

%Vor%     
Fritz G. Mehner 08.07.2010 06:40
quelle
4

Hier ist ein schöner Weg:

%Vor%

und Sie können die "echo" -Anweisungen natürlich mit allem ersetzen, was Sie wollen.

==================

Diskussion:

  • Die Variable $SHELL gibt die bevorzugte Shell des Benutzers an ... die angibt Sie nichts über die Shell, die im Moment läuft.

  • Das Testen von $BASH_VERSION ist eine 99% -ige gute Idee, aber es könnte scheitern, wenn irgendein Klugscheißer eine Variable dieses Namens in die sh-Umgebung steckt. Darüber hinaus erfahren Sie nicht viel über welche Nicht-Bash-Shell läuft.

  • Die Methode $(type -p) ist superleicht und funktioniert sogar, wenn ein weiser Typ eine Datei namens "-p" in $PATH erstellt. Darüber hinaus kann es als Basis für eine 4-Wege-Diskriminierung oder 80% einer 5-Wege-Diskriminierung verwendet werden, wie unten diskutiert.

  • Wenn Sie einen Hash-bang, d. h. #! an der Spitze Ihres Skripts setzen, garantiert nicht , dass es an den Interpreter Ihrer Wahl weitergegeben wird. Zum Beispiel wird mein ~/.xinitrc von /bin/sh interpretiert, egal was Hash-Bang (wenn überhaupt) oben erscheint.

  • Es empfiehlt sich, einige Funktionen zu testen, die in beiden Sprachen zuverlässig existieren, sich jedoch anders verhalten. Im Gegensatz dazu wäre es nicht im Allgemeinen sicher, das gewünschte Feature zu testen und festzustellen, ob es fehlschlägt. Wenn Sie beispielsweise das integrierte Feature declare verwenden möchten und es nicht vorhanden ist, kann es ein Programm ausführen, und das hat ein unbegrenztes Potenzial für die Abwärtsentwicklung.

  • Manchmal ist es sinnvoll, kompatiblen Code zu schreiben, indem Sie den Feature-Set mit dem kleinsten gemeinsamen Nenner verwenden ... aber manchmal nicht. Die meisten dieser hinzugefügten Funktionen wurden aus einem bestimmten Grund hinzugefügt. Da diese Interpreten «fast» turing-complete sind, ist es «fast» garantiert möglich, mit dem anderen nachzueifern ... möglich, aber nicht sinnvoll.
  • Es gibt zwei Inkompatibilitätsstufen: Syntax und Semantik. Zum Beispiel ist die if-then-else-Syntax für csh so anders als bash, dass die einzige Möglichkeit, kompatiblen Code zu schreiben, darin bestehen würde, auf if-then-else-Anweisungen zu verzichten. Das ist möglich, aber es verursacht hohe Kosten. Wenn die Syntax falsch ist, wird das Skript überhaupt nicht ausgeführt. Sobald Sie diese Hürde hinter sich gebracht haben, gibt es Dutzende von Möglichkeiten, auf denen vernünftig aussehender Code zu unterschiedlichen Ergebnissen führt, je nachdem, welcher Dialekt des Interpreters gerade ausgeführt wird.
  • Für ein großes, kompliziertes Programm ist es nicht sinnvoll, zwei Versionen zu schreiben. Schreibe es einmal in der Sprache deiner Wahl. Wenn jemand es unter dem falschen Interpreter startet, kann man das erkennen und einfach exec den richtigen Interpreter.

  • Ein 5-Wege-Detektor kann hier gefunden werden:

    Ссылка

    Es kann unterscheiden:

    • bash
    • bsd-csh
    • Bindestrich
    • ksh93
    • zsh5

    Darüber hinaus deckt diese 5-Wege-Prüfung in meiner Ubuntu Xenial-Box auch Folgendes ab:

    • ash ist ein Symlink zum Bindestrich
    • csh ist ein Symlink zu / bin / bsd-csh
    • ksh ist ein Symlink zu / bin / ksh93
    • sh ist ein Symlink zum Gedankenstrich
Dumbled0re 11.12.2016 07:10
quelle
2

Die Umgebungsvariable SHELL sagt Ihnen, welche Login-Shell ausgeführt wird.

Sie können auch ps $$ verwenden, um die aktuelle Shell zu finden, die verwendet werden kann, wenn Sie wissen wollen, unter welcher Shell das Skript läuft (nicht unbedingt die Login-Shell). Reduzieren Sie die ps -Ausgabe auf den Shell-Namen: ps o command= $$ (nicht sicher, wie plattformübergreifend dies funktioniert, funktioniert aber unter Mac OS X).

    
Jeff 08.07.2010 00:36
quelle
2

Ich denke, das wäre die praktischste und Cross Shell-kompatible

%Vor%

Erläuterung:

/proc/self zeigt immer auf den aktuellen Ausführungsprozess. Wenn Sie beispielsweise Folgendes ausführen, wird die PID von readlink it self angezeigt (nicht die Shell, die den readlink ausführt)

%Vor%

Ergebnisse in:

%Vor%

Jetzt: /proc/self/exe ist eine symbolische Verknüpfung zur laufenden ausführbaren Datei

Beispiel:

%Vor%

ergibt:

%Vor%

Und hier sind die Ergebnisse, die in Dash und Zsh laufen und Bash durch einen Symlink und sogar durch eine Kopie laufen lassen.

%Vor%     
user2059857 22.01.2016 06:40
quelle
1

Was verhindert, dass Sie tragbares (dh Shell-unabhängiges) Skript schreiben?

    
Roman Cheplyaka 08.07.2010 07:09
quelle
0

Ich würde empfehlen, das Vorhandensein der benötigten Funktion zu ermitteln, anstatt bash vs zsh vs usw. Wenn das Feature vorhanden ist, verwenden Sie es, wenn Sie keine Alternative verwenden. Wenn es keine gute Möglichkeit gibt, die Funktion zu erkennen, außer sie zu verwenden und auf Fehler zu prüfen, dann ist das zwar etwas hässlich, aber ich habe keine bessere Lösung. Entscheidend ist, dass es zuverlässiger funktionieren sollte, als zu versuchen, bash zu erkennen. Und da andere Shells (die sich noch in der Entwicklung befinden) dieses Feature, das früher nur Bash war, irgendwann in der Zukunft haben werden, befasst es sich wirklich mit dem, was wichtig ist, und vermeidet, dass Sie eine Datenbank mit den Versionen jeder Shell führen müssen Unterstützung welche Funktion und welche nicht.

    
iconoclast 15.01.2013 15:39
quelle

Tags und Links