it-swarm.com.de

Wie bestimme ich die aktuelle Shell, an der ich arbeite?

Wie kann ich die aktuelle Shell ermitteln, an der ich arbeite?

Wäre die Ausgabe des Befehls ps alleine ausreichend?

Wie kann dies in verschiedenen UNIX-Versionen geschehen?

571
josh
  • Es gibt drei Möglichkeiten, um das Name der aktuellen Shell-Programmdatei zu finden:

    Bitte beachten Sie, dass alle drei Vorgehensweisen getäuscht werden können, wenn die ausführbare Datei der Shell /bin/sh lautet, es sich jedoch beispielsweise wirklich um eine umbenannte bash handelt (was häufig vorkommt).

    Somit wird Ihre zweite Frage, ob die Ausgabe von ps funktioniert, mit "nicht immer" beantwortet.

    1. echo $0 - gibt den Programmnamen aus ... bei Shell handelt es sich um die eigentliche Shell

    2. ps -ef | grep $$ | grep -v grep - Hiermit wird die aktuelle Prozess-ID in der Liste der ausgeführten Prozesse gesucht. Da der aktuelle Prozess Shell ist, wird er eingeschlossen.

      Dies ist nicht 100% zuverlässig, da Sie möglicherweise ANDERE Prozesse haben, deren ps -Auflistung dieselbe Nummer wie die Prozess-ID von Shell enthält, insbesondere wenn diese ID eine kleine Nummer ist (z. B. wenn die PID von Shell "5" ist) Prozesse mit dem Namen "Java5" oder "Perl5" in derselben grep Ausgabe!). Dies ist das zweite Problem mit dem "ps" -Ansatz, obgleich es nicht möglich ist, sich auf den Shell-Namen zu verlassen.

    3. echo $Shell - Der Pfad zur aktuellen Shell wird als Shell -Variable für eine beliebige Shell gespeichert. Die Einschränkung für diese ist, dass, wenn Sie eine Shell explizit als Unterprozess starten (z. B. es ist nicht Ihre Anmeldeshell), Sie stattdessen den Wert Ihrer Anmeldeshell erhalten. Wenn dies möglich ist, verwenden Sie den Ansatz ps oder $0.


  • Wenn die ausführbare Datei jedoch nicht mit Ihrer tatsächlichen Shell übereinstimmt (z. B. ist /bin/sh tatsächlich bash oder ksh), benötigen Sie Heuristiken. Hier sind einige Umgebungsvariablen, die für verschiedene Shells spezifisch sind:

    • $version ist auf tcsh eingestellt

    • $BASH ist auf bash gesetzt

    • $Shell (Kleinbuchstaben) wird in csh oder tcsh auf den tatsächlichen Shell-Namen gesetzt

    • $ZSH_NAME ist auf zsh gesetzt

    • ksh hat $PS3 und $PS4 gesetzt, während normale Bourne Shell (sh) nur $PS1 und $PS2 gesetzt hat. Dies scheint im Allgemeinen am schwierigsten zu unterscheiden zu sein - der EINZIGE Unterschied zwischen sh und ksh, den wir auf Solaris Boxen installiert haben, ist $ERRNO, $FCEDIT, $LINENO, $PPID, $PS3, $PS4, $RANDOM, $SECONDS, $TMOUT.

726
DVK

ps -p $$

sollte überall funktionieren, wo die Lösungen mit ps -ef und grep funktionieren (auf jeder Unix-Variante, die POSIX-Optionen für ps ) und wird nicht unter den falschen Positiven leiden, die durch Greifen nach einer Folge von Ziffern eingeführt werden, die an anderer Stelle auftreten können.

89

Versuchen

ps -p $$ -oargs=

oder

ps -p $$ -ocomm=
37

Wenn Sie nur sicherstellen möchten, dass der Benutzer das Skript mit bash aufruft, gehen Sie wie folgt vor:

if [ ! -n "$BASH" ] ;then echo Please run this script $0 with bash; exit 1; fi
25
Peter Lamberg

Du kannst es versuchen:

ps | grep `echo $$` | awk '{ print $4 }'

Oder:

echo $Shell
19
karlphillip

$Shell muss nicht immer die aktuelle Shell anzeigen. Es gibt nur die aufzurufende Standard-Shell wieder.

Um dies zu testen, sagen Sie, dass bash die Standard-Shell ist, versuchen Sie echo $Shell, gehen Sie dann im selben Terminal in eine andere Shell (z. B. ksh) und versuchen Sie $Shell das Ergebnis als Bash in beiden Fällen.

Verwenden Sie cat /proc/$$/cmdline und den Pfad zur Shell, die von readlink /proc/$$/exe ausgeführt werden kann, um den Namen der aktuellen Shell abzurufen.

11
sr01853

ps ist die zuverlässigste Methode. Es kann nicht garantiert werden, dass die Shell envar eingestellt ist, und selbst wenn dies der Fall ist, kann sie leicht gefälscht werden

9
ennuikiller

Ich habe einen einfachen Trick, um die aktuelle Shell zu finden. Geben Sie einfach eine zufällige Zeichenfolge ein (dies ist kein Befehl). Es wird fehlschlagen und einen "nicht gefundenen" Fehler zurückgeben, aber am Anfang der Zeile wird angegeben, um welche Shell es sich handelt:

ksh: aaaaa: not found [No such file or directory]
bash: aaaaa: command not found
8
user5659949

Dies gibt immer die tatsächlich verwendete Shell an - erhält den Namen der tatsächlich ausführbaren Datei und nicht den Namen der Shell (dh ksh93 anstelle von ksh usw.) Für /bin/sh wird die tatsächlich verwendete Shell angezeigt: dh dash

ls -l /proc/$$/exe | sed 's%.*/%%'

Ich weiß, dass hier viele sagen, dass die Ausgabe von ls neu verarbeitet werden sollte, aber wie hoch ist die Wahrscheinlichkeit, dass eine von Ihnen verwendete Shell mit Sonderzeichen benannt oder in einem Verzeichnis mit Sonderzeichen platziert wird? Wenn dies immer noch der Fall ist, gibt es hier viele andere Beispiele, die es anders machen.

7
vadimbog

Ich habe viele verschiedene Ansätze ausprobiert und der beste ist für mich:

ps -p $$

Es funktioniert auch unter Cygwin und kann keine False Positives als PID Grepping erzeugen. Bei einigen Bereinigungen wird nur ein ausführbarer Name ausgegeben (unter Cygwin mit Pfad):

ps -p $$ | tail -1 | awk '{print $NF}'

Sie können eine Funktion erstellen, damit Sie sich diese nicht merken müssen:

# print currently active Shell
shell () {
  ps -p $$ | tail -1 | awk '{print $NF}'
}

... und dann einfach Shell ausführen.

Getestet unter Debian und Cygwin.

Meine Variante zum Drucken des übergeordneten Prozesses.

ps -p $$ | awk '$1 == PP {print $4}' PP=$$

Warum unnötige Anwendungen ausführen, wenn 'awk' dies für Sie erledigen kann?

4
Matthew Stier

Vorausgesetzt, Ihr /bin/sh unterstützt den POSIX-Standard und auf Ihrem System ist der lsof -Befehl installiert - eine mögliche Alternative zu lsof könnte in diesem Fall pid2path sein - Sie können auch ( oder passen Sie das folgende Skript an, das vollständige Pfade ausgibt:

#!/bin/sh
# cat /usr/local/bin/cursh
set -eu
pid="$$"

set -- sh bash zsh ksh ash dash csh tcsh pdksh mksh fish psh rc scsh bournesh wish Wish login

unset echo env sed ps lsof awk getconf

# getconf _POSIX_VERSION  # reliable test for availability of POSIX system?
PATH="`PATH=/usr/bin:/bin:/usr/sbin:/sbin getconf PATH`"
[ $? -ne 0 ] && { echo "'getconf PATH' failed"; exit 1; }
export PATH

cmd="lsof"
env -i PATH="${PATH}" type "$cmd" 1>/dev/null 2>&1 || { echo "$cmd not found"; exit 1; }

awkstr="`echo "[email protected]" | sed 's/\([^ ]\{1,\}\)/|\/\1/g; s/ /$/g' | sed 's/^|//; s/$/$/'`"

ppid="`env -i PATH="${PATH}" ps -p $pid -o ppid=`"
[ "${ppid}"X = ""X ] && { echo "no ppid found"; exit 1; }

lsofstr="`lsof -p $ppid`" || 
   { printf "%s\n" "lsof failed" "try: Sudo lsof -p \`ps -p \$\$ -o ppid=\`"; exit 1; }

printf "%s\n" "${lsofstr}" | 
   LC_ALL=C awk -v var="${awkstr}" '$NF ~ var {print $NF}'
3
carlo
echo $$ # Gives the Parent Process ID 
ps -ef | grep $$ | awk '{print $8}' #use the PID to see what the process is.

from http://www.unix.com/unix-dummies-questions-answers/10390-how-do-you-what-your-current-Shell.html

2
Moisei

Keine der Antworten funktionierte mit der fish-Shell (sie enthält keine Variablen $$ oder $0).

Dies funktioniert für mich (getestet mit sh, bash, fish, ksh, csh, true, tcsh und zsh; openSUSE 13.2):

ps | tail -n 4 | sed -E '2,$d;s/.* (.*)/\1/'

Dieser Befehl gibt einen String wie bash aus. Ich verwende hier nur ps, tail und sed (ohne GNU Erweiterungen; versuche, --posix hinzuzufügen, um dies zu überprüfen). Sie alle sind Standard-POSIX-Befehle. Ich bin sicher, dass tail entfernt werden kann, aber mein sed fu ist nicht stark genug, um dies zu tun.

Es scheint mir, dass diese Lösung nicht sehr portabel ist, da sie unter OS X nicht funktioniert. :(

2
rominf

Es gibt viele Möglichkeiten, die Shell und ihre entsprechende Version herauszufinden. Hier sind einige, die für mich gearbeitet haben.

Geradeaus

  1. $> echo $ (Gibt den Programmnamen an. In meinem Fall lautete die Ausgabe - bash )
  2. $> $ Shell (Dies bringt Sie in die Shell und in der Eingabeaufforderung erhalten Sie den Namen und die Version der Shell. In meinem Fall bash3.2 $ )
  3. $> echo $ Shell (Dies gibt den ausführbaren Pfad an. In meinem Fall /bin/bash )
  4. $> $ Shell --version (Dies gibt vollständige Informationen über die Shell-Software mit Lizenztyp)

Hackish Ansatz

$> ******* (Geben Sie einen Satz zufälliger Zeichen ein, und in der Ausgabe wird der Shell-Name angezeigt. In meinem Fall - bash: chapter2-a-sample-isomorphic- app: Befehl nicht gefunden )

2
Devang Paliwal

Dies ist keine sehr saubere Lösung, macht aber, was Sie wollen.

Mir ist klar, dass die Antwort in diesem guten alten Jahr 2015 etwas spät ist, aber ...

#MUST BE SOURCED..
getshell() {
    local Shell="`ps -p $$ | tail -1 | awk '{print $4}'`"

    shells_array=(
    # It is important that the shells are listed by the decrease of their length name.
        pdksh
        bash dash mksh
        zsh ksh
        sh
    )

    local suited=false
    for i in ${shells_array[*]}; do
        if ! [ -z `printf $Shell | grep $i` ] && ! $suited; then
            Shell=$i
            suited=true
        fi
    done

    echo $Shell
}
getshell

Jetzt können Sie $(getshell) --version. verwenden

Dies funktioniert jedoch nur bei ksh-ähnlichen Shells.

1
theoden

Unter Mac OS X (& FreeBSD):

ps -p $$ -axco command | sed -n '$p' 
1
zaga

Meine Lösung:

ps -o command | grep -v -e "\<ps\>" -e grep -e tail | tail -1

Dies sollte auf verschiedenen Plattformen und Shells portierbar sein. Es verwendet ps wie andere Lösungen, aber es ist nicht auf sed oder awk angewiesen und filtert Müll aus Piping und ps selbst heraus, sodass die Shell immer die sein sollte letzter Eintrag. Auf diese Weise müssen wir uns nicht auf nicht portable PID-Variablen verlassen oder die richtigen Zeilen und Spalten auswählen.

Ich habe Debian und MacOS mit bash, zsh und fish getestet (was mit den meisten dieser Lösungen nicht funktioniert, ohne den Ausdruck speziell für fish zu ändern, da eine andere PID-Variable verwendet wird).

1
wickles

Grepping PID von der Ausgabe von "ps" ist nicht erforderlich, da Sie die entsprechende Befehlszeile für jede PID aus der/proc-Verzeichnisstruktur lesen können:

echo $(cat /proc/$$/cmdline)

Das könnte jedoch nicht besser sein als einfach:

echo $0

Wenn Sie eine andere Shell ausführen möchten, als der Name angibt, können Sie die Version von Shell unter Verwendung des zuvor angegebenen Namens anfordern:

<some_Shell> --version

sh scheint mit Exit-Code 2 zu scheitern, während andere etwas Nützliches angeben (aber ich kann nicht alle verifizieren, da ich sie nicht habe):

$ sh --version
sh: 0: Illegal option --
echo $?
2
1
ajaaskel

Führen Sie die folgenden Schritte aus, um festzustellen, ob Ihre Shell DASH/BASH verwendet.

1) ls –la/bin/sh, wenn das Ergebnis / bin/sh ->/bin/bash ==> Dann verwendet Ihre Shell BASH.

wenn das Ergebnis / bin/sh ->/bin/dash ==> ist, verwendet Ihre Shell DASH.

Wenn Sie von BASH zu DASH oder umgekehrt wechseln möchten, verwenden Sie den folgenden Code ln -s/bin/bash/bin/sh (Shell zu BASH ändern)

HINWEIS: Wenn der obige Befehl zu einem Fehler führt, der besagt, dass/bin/sh bereits vorhanden ist, entfernen Sie/bin/sh und versuchen Sie es erneut.

1
Shiva

Wenn Sie nur überprüfen möchten, ob Sie Bash (eine bestimmte Version von Bash) ausführen, verwenden Sie am besten die Array-Variable $BASH_VERSINFO. Als (schreibgeschützte) Array-Variable kann sie nicht in der Umgebung festgelegt werden, sodass Sie sicher sein können, dass sie (wenn überhaupt) von der aktuellen Shell stammt. Da Bash jedoch ein anderes Verhalten aufweist, wenn es als sh aufgerufen wird, müssen Sie auch überprüfen, ob die Umgebungsvariable $BASH mit /bash endet.

In einem Skript, das ich geschrieben habe und das Funktionsnamen mit - (kein Unterstrich) verwendet und das von assoziativen Arrays abhängt (hinzugefügt in Bash 4), habe ich die folgende Überprüfung der Integrität (mit hilfreicher Benutzerfehlermeldung):

case `eval 'echo [email protected]${BASH_VERSINFO[0]}' 2>/dev/null` in
    */[email protected][456789])
        # Claims bash version 4+, check for func-names and associative arrays
        if ! eval "declare -A _ARRAY && func-name() { :; }" 2>/dev/null; then
            echo >&2 "bash $BASH_VERSION is not supported (not really bash?)"
            exit 1
        fi
        ;;
    */[email protected][123])
        echo >&2 "bash $BASH_VERSION is not supported (version 4+ required)"
        exit 1
        ;;
    *)
        echo >&2 "This script requires BASH (version 4+) - not regular sh"
        echo >&2 "Re-run as \"bash $CMD\" for proper operation"
        exit 1
        ;;
esac

Sie könnten die etwas paranoide Funktionsprüfung für Features im ersten Fall weglassen und einfach davon ausgehen, dass zukünftige Bash-Versionen kompatibel wären.

1
Alex Dupuy

Bitte verwenden sie unten befehl:

 # ps -p $$ | tail -1 | awk '{print $4}'
0
Ranjithkumar T