Problem : Finde heraus, wie viele Muscheln tief ich bin.
Details : Ich öffne die Shell sehr oft von vim. Bauen und ausführen und beenden. Manchmal vergesse ich und öffne ein anderes Vim und dann noch eine Muschel. :(
Ich möchte wissen, wie viele Muscheln tief ich bin, vielleicht habe ich sie sogar immer auf meinem Muschelschirm. (Ich kann diesen Teil verwalten).
Meine Lösung : Analysieren Sie den Prozessbaum, suchen Sie nach vim und bash / zsh und ermitteln Sie die Tiefe des aktuellen Prozesses.
Gibt es so etwas schon? Ich konnte nichts finden.
$SHLVL
Variable (die von mehreren Shells verwaltet wird) das, wonach Sie suchen?fg
zurückzukehren, was dieses Problem nicht hat.vim
möglicherweise verwirrender , mehrere parallel gestoppte Jobs zu haben, als einen Stapel verschachtelter Prozesse. Im Übrigen bevorzuge ich mehrere Fenster , damit ich schnell hin und her springen kann, aber ich würde dies nicht als XY-Problem bezeichnen, nur weil ich einen anderen Workflow bevorzuge.Antworten:
Als ich Ihre Frage las, war mein erster Gedanke
$SHLVL
. Dann sah ich, dass Sievim
Ebenen zusätzlich zu Shell-Ebenen zählen wollten . Eine einfache Möglichkeit, dies zu tun, besteht darin, eine Shell-Funktion zu definieren:Dies wird bei
SHLVL
jeder Eingabe einesvim
Befehls automatisch und unbeaufsichtigt inkrementiert . Sie müssen dies für jede Variante vonvi
/ tunvim
, die Sie jemals verwenden. z.B,Der äußere Satz von Klammern erstellt eine Subshell, sodass die manuelle Änderung des Werts von
SHLVL
die aktuelle (übergeordnete) Shell-Umgebung nicht verschmutzt. Dascommand
Schlüsselwort soll natürlich verhindern, dass sich die Funktionen selbst aufrufen (was zu einer unendlichen Rekursionsschleife führen würde). Und natürlich sollten Sie diese Definitionen in Ihre.bashrc
oder eine andere Shell-Initialisierungsdatei einfügen.Es gibt eine leichte Ineffizienz in der obigen. In einigen Muscheln (Bash ist eins), wenn Sie sagen
Wenn es sich um ein externes ausführbares Programm handelt (dh nicht um einen eingebauten Befehl), hält die Shell einen zusätzlichen Prozess herum, nur um auf das Beenden zu warten . Dies ist (wohl) nicht notwendig; Die Vor- und Nachteile sind umstritten. Wenn es Ihnen nichts ausmacht, ein wenig Speicher und einen Prozess-Slot zu belegen (und einen Shell-Prozess mehr zu sehen, als Sie benötigen, wenn Sie a ausführen ), gehen Sie wie oben beschrieben vor und fahren Sie mit dem nächsten Abschnitt fort. Das Gleiche gilt, wenn Sie eine Shell verwenden, bei der der zusätzliche Prozess nicht herumliegt. Wenn Sie jedoch den zusätzlichen Prozess vermeiden möchten, sollten Sie zunächst versuchen, dies zu tun
cmdn
cmdn
ps
Der
exec
Befehl soll verhindern, dass der zusätzliche Shell-Prozess nachlässt.Aber es gibt ein GOTCHA. Die Bedienung der Shell
SHLVL
ist etwas intuitiv: Beim Start der Shell wird geprüft, obSHLVL
gesetzt ist. Wenn es nicht gesetzt ist (oder auf etwas anderes als eine Zahl gesetzt ist), setzt die Shell es auf 1. Wenn es gesetzt ist (auf eine Zahl), fügt die Shell 1 hinzu.Aber von dieser Logik, wenn Sie sagen
exec sh
, IhrSHLVL
sollte steigen. Dies ist jedoch unerwünscht, da sich Ihr tatsächlicher Shell-Level nicht erhöht hat. Die Muschelgriffe dies durch eine Subtraktion vonSHLVL
, wenn Sie tun einexec
:Damit
ist eine Wäsche; es wird
SHLVL
nur inkrementiert , um es erneut zu dekrementieren. Sie können auch einfach sagenvim
, ohne eine Funktion zu nutzen.Um dies zu beheben, würden Sie tun
Dann habe ich gesehen, dass Sie
vim
Ebenen unabhängig von Shell-Ebenen zählen möchten. Nun, genau der gleiche Trick funktioniert (nun, mit einer kleinen Modifikation):(und so weiter für
vi
,view
usw.) Dasexport
ist notwendig, daVILVL
es standardmäßig nicht als Umgebungsvariable definiert ist. Es muss jedoch nicht Teil der Funktion sein. Sie können einfachexport VILVL
als separates Kommando (in Ihrem.bashrc
) sagen . Und, wie oben beschrieben, wenn der zusätzliche Shell - Prozess für Sie kein Problem ist, können Sie tun ,command vim
stattexec vim
, und lassen SieSHLVL
allein:Wenn Sie eine Shell verwenden, die nicht unterstützt wird
SHLVL
(z. B. Bindestrich), können Sie sie selbst implementieren, solange die Shell eine Startdatei implementiert. Mach einfach so etwas wiein Ihrer
.profile
oder einer entsprechenden Datei. (Sie sollten den Namen wahrscheinlich nicht verwendenSHLVL
, da dies zu Chaos führen kann, wenn Sie jemals eine unterstützte Shell verwendenSHLVL
.)Andere Antworten haben das Problem der Einbettung von Umgebungsvariablenwerten in Ihre Shell-Eingabeaufforderung angesprochen, daher werde ich das nicht wiederholen, besonders wenn Sie sagen, dass Sie bereits wissen, wie es geht.
quelle
ps
oderpstree
, wenn Sie dies mit Shell-Builtins tun können.dash
arithmetische Erweiterung hat.SHELL_LEVEL=$((SHELL_LEVEL + 1))
sollte auch dann ausreichen, wenn $ SHELL_LEVEL zuvor nicht gesetzt oder leer war. Es ist nur , wenn Sie an der Bourne - Shell tragbar sein musste , die Sie zurückgreifen müssen würdeexpr
, aber dann würden Sie auch ersetzen müssen$(...)
mit`..`
.SHELL_LEVEL=`expr "${SHELL_LEVEL:-0}" + 1`
bash
Skript dazu zwingen kann, ~ / .bashrc von zu lesen) Wenn Sie beispielsweise stdin zu einer Steckdose machen, kann dies zu einem Problem werden. Das ist eine Menge "Wenn", aber etwas, das man im Hinterkopf behalten sollte (nicht bereinigte Daten im arithmetischen Kontext sind gefährlich)Sie können so viele Zeit in Anspruch nehmen, bis Sie einen Sitzungsleiter gefunden haben. Wie bei
zsh
Linux:Oder POSIXly (aber weniger effizient):
Das würde 0 für die Shell ergeben, die von Ihrem Terminalemulator oder getty gestartet wurde, und eine weitere für jeden Nachkommen.
Sie müssen dies nur einmal beim Start tun. Zum Beispiel mit:
in Ihrem
~/.zshrc
oder einem gleichwertigen Format, um es in Ihrer Aufforderung zu haben.tcsh
und mehrere andere Muscheln (zsh
,ksh93
,fish
undbash
zumindest) halten eine$SHLVL
Variable , die sie beim Start erhöhen (und Abnahme vor einem anderen Befehl ausgeführt werden mitexec
(es sei denn , dassexec
in einer Subshell wenn sie nicht Buggy (aber viele sind))). Dass nur die Menge von Spuren Schale Verschachtelung nicht aber verarbeiten Verschachtelung. Es wird auch nicht garantiert, dass Stufe 0 der Sitzungsleiter ist.quelle
Verwenden Sie
echo $SHLVL
. Verwenden Sie das KISS-Prinzip . Abhängig von der Komplexität Ihres Programms kann dies ausreichen.quelle
bash
, aber nicht fürdash
.Eine mögliche Lösung besteht darin, den Output von zu betrachten
pstree
. Wenn Sie in einer Shell laufenvi
, die von innen erzeugt wurde , sollte der Teil des Baumbaums, der aufgelistet wirdpstree
, Ihnen zeigen, wie tief Sie sind. Zum Beispiel:quelle
Erste Variante - nur Schalentiefe.
Einfache Lösung für
bash
: Addiere zu den.bashrc
nächsten zwei Zeilen (oder ändere deinen aktuellenPS1
Wert):Ergebnis:
Die Zahl am Anfang der Eingabeaufforderungszeichenfolge gibt die Shell-Ebene an.
Zweite Variante mit verschachtelten Vim- und Shell-Ebenen.
füge diese Zeilen dem hinzu
.bashrc
Ergebnis:
v: 1 - Tiefenlevel vim
s: 3 - Tiefenlevel shell
quelle
In der Frage, die Sie erwähnt haben, analysieren von
pstree
. Hier ist ein relativ einfacher Weg:Die
pstree
Optionen:-A
- ASCII-Ausgabe zur einfacheren Filterung (in unserem Fall wird jedem Befehl ein vorangestellt`-
)-a
- zeige auch Befehlsargumente an, als Nebeneffekt wird jeder Befehl in einer eigenen Zeile angezeigt und wir können die Ausgabe einfach mit filterngrep
-l
- Schneiden Sie keine langen Zeilen ab-s
- Eltern des ausgewählten Prozessesanzeigen (wird in alten Versionen von leider nicht unterstützt
pstree
)$$
- der ausgewählte Prozess - die PID der aktuellen Shellquelle
Dies beantwortet die Frage nicht unbedingt , macht sie jedoch in vielen Fällen unnötig:
Wenn Sie Ihre Shell zum ersten Mal starten, führen Sie sie aus
set -o ignoreeof
. Steck es nicht in deine~/.bashrc
.Machen Sie es sich zur Gewohnheit, Strg-D einzugeben, wenn Sie glauben, dass Sie sich in der obersten Ebene der Shell befinden und sicher sein möchten.
Wenn Sie sich nicht in der Shell der obersten Ebene befinden, signalisiert Strg-D der aktuellen Shell das "Ende der Eingabe" und Sie werden eine Ebene zurückgesetzt.
Wenn Sie sich in der obersten Ebene der Shell befinden, erhalten Sie eine Nachricht:
Ich benutze dies die ganze Zeit für verkettete SSH-Sitzungen, um es einfach zu machen, auf eine bestimmte Ebene der SSH-Kette zurückzukehren. Es funktioniert genauso gut für verschachtelte Shells.
quelle