Ich suche nach einer einfachen und zuverlässigen Möglichkeit, den Namen der aktuellen Shell aus einem Skript oder einer Quelldatei ( nicht über die Befehlszeile) abzurufen . Ich hätte erwartet, nur zu tun, $(basename "$SHELL")
aber wenn meine Login-Shell ist zsh
und ich den folgenden Code in some_script.sh habe
this_shell=$( basename "$SHELL" )
echo "The Shell is $this_shell"
echo "The Shell is $0"
und ich führe es mit aus bash some_script.sh
, es listet immer noch zsh
statt bash
, obwohl der verwendete Interpreter ist /bin/bash
. Ich bin mir nicht sicher, warum Shell-Designer die Standard-Shell anstelle der aktuellen Shell angezeigt haben, aber das scheint das zu sein, woran wir festhalten.
Es gibt einige andere leicht ähnliche Fragen ( hier und hier ), aber ihre Antworten sind in vielerlei Hinsicht unzureichend.
- Sie gehen oft davon aus, dass der Benutzer versucht herauszufinden, welche interaktive Shell er derzeit verwendet, aber das ist verrückt. Ich weiß , was Shell Ich bin Typisierung Befehle in - I - Code benötigen , die überall ausgeführt werden könnte in der Lage sein zu bestimmen , welche Shell es verwendet wird .
- Sie geben oft verschiedene Dinge zum Ausprobieren - wieder, als ob Sie sich in der Befehlszeile befinden und nur herumspielen können, bis Sie erfahren, dass Sie Bash verwenden -, aber ich brauche eine einzige Sache, die in allen Kontexten zuverlässig ist.
- Sie geben oft Dinge, die aus Skripten völlig nutzlos sind, wie z
echo $0
. Das schlägt fehl, wie im obigen Skript gezeigt. (Ja, es funktioniert in einer interaktiven Shell-Befehlszeile, aber warum sollten Sie jemals nicht wissen, welche Shell Sie verwenden?) - Sie manchmal geben Befehle, die (in meinen begrenzten Tests) sind die richtigen Informationen, wie
ps -p $$
, aber nicht über Cross-Plattform, Cross-Shell kompatibel sed / awk - Befehle Rohr durchzukommen nur die Shell Namen und ignorieren die anderen Informationen , die kommen zusammen für die Fahrt. - Dazu gehören Dinge, die nur bei ein paar Muscheln funktionieren, wie
$BASH_VERSION
und$ZSH_VERSION
. Ich möchte so viele Muscheln wie möglich unterstützen, wie zum Beispielfish
,csh
,tcsh
.
Wie kann ich zuverlässig und genau erfassen jede aktuelle Shell? Ich suche nach etwas, das plattformübergreifend, in Skripten und für so viele Shells wie möglich und vernünftig funktioniert 1 .
UPDATE : Als ich diese Frage stellte, erwartete ich, dass in die Muscheln eine Einrichtung eingebaut war, um uns diese Informationen zu geben, was anscheinend nicht der Fall ist. Da es jetzt unvermeidlich erscheint, sich auf etwas außerhalb der Muscheln zu verlassen, sollte ich deutlicher machen, dass ich nach einer plattformübergreifenden Lösung frage (die, obwohl sie durch meine Einwände gegen andere Antworten oben impliziert wird, leicht zu übersehen sein könnte, wenn Sie sie nicht anziehen Lesen Sie die Frage nicht sorgfältig durch.
Update 2 Wenn noch jemand glaubt, dass dies ein Duplikat der Nur-Linux-Frage ist, weil Stéphanes Antwort nicht nur Linux ist, sind hier die Unterschiede zwischen dem, was ich verlange, und dem, was er bereitgestellt hat. (Beachten Sie, dass das, was er geschrieben hat, genial ist und ich nicht klopfe, aber es löst mein Problem nicht.)
- Ich bin auf der Suche nach etwas einfach und zuverlässig , dass
- kann zu jeder Skript- oder Funktionsdefinition (die von einem
.zshrc
oder.bash_profile
oder was auch immer bezogen wird) zum Verzweigen hinzugefügt werden . - Sie können sein Skript nicht als externes Dienstprogramm verwenden, das den Interpreternamen an das aufrufende Skript / die aufrufende Funktion übergibt, da es immer vom Standardinterpreter interpretiert wird und diesen zurückgibt. Dies macht es entweder schwierig oder unmöglich, es für meine Zwecke zu verwenden. Wenn es möglich ist, ist es immer noch sehr, sehr schwierig, und die Lösung dafür ist in der Antwort nicht angegeben. Deshalb hat er meine Frage nicht beantwortet, daher handelt es sich nicht um ein Duplikat.
Wenn Sie etwas sehen möchten, das funktioniert, schauen Sie sich ShellDetective auf GitHub an . Dies könnte es einfacher machen, die Unterschiede zwischen dem, was bereits in SE vorhanden ist, und dem, wonach diese Frage sucht, zu erkennen (und wurde tatsächlich geschrieben, um die Bedürfnisse dieser Frage zu befriedigen, die anderswo nicht erfüllt wurden).
(PS , wenn Sie kann nicht glauben , es ist ein Anwendungsfall für diese, stellen Funktionen , die in Quellen erhalten .zshrc
, .bash_profile
oder .profile
je nachdem , was Server verwendet wird und welche Schalen es zur Verfügung hat. Sie stammen sind , so dass sie keine Shebang - Zeile haben. Sie sind am nützlichsten, wenn sie in einer beliebigen Shell arbeiten können, aber manchmal müssen sie wissen, in welcher Shell sie sich befinden, um zu wissen, wie sie sich verhalten sollen.)
1 Es geht mir nicht um "Muscheln", die keine Muscheln im herkömmlichen Sinne des Wortes sind. Es geht mir nicht um eine Muschel, die ein Typ für sich selbst geschrieben hat. Ich beschäftige mich nur mit echten Shells , die tatsächlich in freier Wildbahn vorkommen und die möglicherweise jemand verwenden muss, wenn er sich bei einem Server anmeldet, auf dem er nicht einfach die gewünschten Shells installieren kann.
sh -c "…"
, und erledigen Sie dann den Großteil der Arbeit in der POSIX-Shell-Syntax.fish
und verwende sie zum Ausführen Ihres Skripts. Möchten Siefish
odercsh
?Antworten:
Ich habe mit dieser Kombination großartige Ergebnisse erzielt:
Unter Tru64 (OSF / 1) hat die Ausgabe Klammern um die Shell. Heften Sie an
tr -d '()'
, um sie zu entfernen.Scheint auf allen Shells unter Solaris 10 und RHEL 5.7 / 6.4 zu funktionieren. Ich habe keine anderen Distributionen wie Debian, Ubuntu oder Mint getestet, aber ich würde denken, dass sie alle gleich funktionieren sollten. Ich habe auch keine Ahnung, ob FreeBSD funktionieren würde.
quelle
Ich versuche immer noch, dies zu konkretisieren, aber ich denke, ich habe eine Idee, die funktionieren wird. Wie Sie bemerkt haben, ist das, was Sie versuchen, wenn nicht unmöglich, äußerst schwierig in allen Schalen zu tun (jede Variante, die Sie dem Polyglot hinzufügen, erhöht die Komplexität mit einer Geschwindigkeit, die über der linearen Rate liegt). Sie könnten es wahrscheinlich tun, wenn Sie sich in Bourne (sh, ash, dash, bash, ksh, pdksh, zsh usw.) und c-Muscheln (csh, tcsh, fish usw.) aufteilen, aber die Variation zwischen den
csh
Varianten bietet verschiedene interessante Möglichkeiten Herausforderungen.Lassen Sie uns also unsere Erkennungsroutine betrügen und in einer bekannten Sprache schreiben (Bash mit einer Shebang-Zeile, C, Perl, Python, was auch immer) und den Namen der ausführbaren Datei des Elternteils bestimmen. Wir können dann zwei Tricks verwenden, um die Informationen an das übergeordnete Element zurückzugeben, nämlich Rückgabewerte und ein einzelnes Wort, das auf Standard out geschrieben wurde. Bei sh absteigenden Shells würden wir 0 zurückgeben und den Namen der Shell schreiben, da alle eine gute Backtick-Handhabung haben. Bei der C-Shells-Familie können wir den Rückgabewert für jeden Satz von Inkompatibilitäten erhöhen, die wir umgehen müssen. Rückgabewerte über zweihundert würden Fehler anzeigen, die mit allem beginnen, was in Ordnung zu sein scheint, aber ich kann einfach nicht sagen, wer meine Eltern bei zweihundert sind.
Das innere Programm scheint unter Linux einfach zu sein (
/proc/ppid/exe
ist die halbe Miete). Ich bin mir ziemlich sicher, dass dies auf bsd mit ps-Optionen möglich ist, aber ich habe momentan kein laufendes bsd-System zum Testen und mein Mac benötigt eine neue Festplatte (und ist sowieso nur 10.4). Obwohl es die Probleme mit der Shell-Syntax erheblich reduziert, führt es zu einer Reihe anderer Kompatibilitätsprobleme. Ich denke immer noch, dass es Möglichkeiten gibt.quelle
sh -c "..."
, den er einer anderen Frage entnommen hat . (Entschuldigung: Ich habe Ihre Antwort zuerst übersprungen, weil ich keinen Code darin gesehen habe, und bin erst zurückgekommen und habe sie später gelesen.)case $shell in sh)...
(das ist nur Bourne-Syntax) oderswitch ($shell)
(nur csh) ausführen.test "$shell" = "sh" && do-something
arbeitet incsh
/sh
/rc
/es
, aber nichtfish
.../dev/null
. Aber ich habe eine Lösung, die ich veröffentlichen werde, sobald alles funktioniert.versuche so etwas
quelle
csh
und fehltcsh
.fish
, aber dannfish
leider nur in :ps h -p %self -o args='' | cut -f1 -d' '
. Dies schafft ein Henne-Ei-Problem ... Sie müssen wissen, dass Siefish
in sind, um diefish
Version des Codes auszuführen ...set shell_bin=`ps -p $$ -o args='' | cut -f1 -d' '`
- wird mit CSH arbeiten, aber nicht mit den anderencsh
/tcsh
war es dieser Teil:ps -p $$ -o args='' | cut -f1 -d' '
, die Renditen-sh
aufcsh
und-csh
auftcsh
.Ich glaube, Sie können nicht immer den Namen der aktuellen Shell erhalten , und ich denke, Sie sollten sich der Einschränkungen dessen bewusst sein, was möglich ist.
Bei Linux-Distributionen haben die meisten Benutzer
bash
ihre Login- und interaktive Shell (da diesbash
bei den meisten Distributionen die Standard-Shell ist). Einige Benutzer würden setzen ihre Schalezsh
,csh
(und Varianten) oderfish
.(Wie andere Kommentare und Antworten erklären, finden zuverlässig die Schale aus
bash
,zsh
,tcsh
,fish
ist schon eine Herausforderung)Aber einige seltsame Benutzer ihre Login - Shell zu etwas ganz anderes gesetzt werden - ein Lisp - Interpreter
scsh
,es
einige Skriptsprache à la Python oder Ocaml oder Perl, etc ...- und es ist ihre Freiheit , dies zu tun. Wahrscheinlich codieren einige Leute ihre eigene Shell und verwenden sie interaktiv. Selbst wenn Sie ihre seltsame Shell gefunden haben, können Sie nichts Nützliches daraus machen (daher sollten Sie meiner Meinung nach nicht versuchen, den Namen der Shell zu ermitteln).Ich vermute also, dass Sie eine beschaffbare Datei codieren (möglicherweise eine generieren), um eine Software zu konfigurieren. Erklären Sie einfach, was Sie tun, und codieren Sie den allgemeinen Fall von
bash
(und vielleichtzsh
&tcsh
) ....quelle
Verwendung unten auf eigenen Risiko Haftungsausschluss
quelle
-f
Option inreadlink
, einige Implementierungen haben diesen Schalter nicht-f
als verfügbare Option auf, wobei ich dasformat
als Argument nehme .readlink
Ich arbeite nicht an meinem Puredarwin VM, also habe ich keine Ahnung, was dort los ist.