Ich versuche, eine Funktion zu schreiben, die die Funktionalität des exit
eingebauten Moduls ersetzt, um zu verhindern, dass ich das Terminal verlasse.
Ich habe versucht, die SHLVL
Umgebungsvariable zu verwenden, aber sie scheint sich innerhalb von Subshells nicht zu ändern:
$ echo $SHLVL
1
$ ( echo $SHLVL )
1
$ bash -c 'echo $SHLVL'
2
Meine Funktion ist wie folgt:
exit () {
if [[ $SHLVL -eq 1 ]]; then
printf '%s\n' "Nice try!" >&2
else
command exit
fi
}
Dies erlaubt mir jedoch nicht, exit
innerhalb von Subshells zu arbeiten:
$ exit
Nice try!
$ (exit)
Nice try!
Was ist eine gute Methode, um festzustellen, ob ich in einer Unterschale bin oder nicht?
(...)
alle Eigenschaften des übergeordneten Prozesses. Die Antworten sind robustere Lösungen zur Bestimmung Ihres Shell-Levels.BASH_SUBSHELL
Antwort (auch wenn sie umstritten ist) nicht auf diese Frage zutreffen.Antworten:
In bash können Sie vergleichen
$BASHPID
zu$$
Wenn Sie nicht in der Bash-
$$
Phase sind, sollten Sie in einer Subshell gleich bleiben, sodass Sie eine andere Möglichkeit benötigen, um Ihre eigentliche Prozess-ID zu erhalten.Eine Möglichkeit, um Ihre tatsächliche PID zu erhalten, ist
sh -c 'echo $PPID'
. Wenn Sie das einfach in eine Ebene legen,( … )
scheint es nicht zu funktionieren, da Ihre Schale die Gabel wegoptimiert hat. Versuchen Sie es mit zusätzlichen No-Op-Befehlen( : ; sh -c 'echo $PPID'; : )
, um die Subshell für zu kompliziert zu halten, um sie zu optimieren. Die Gutschrift für diesen Ansatz geht an John1024 bei Stack Overflow .quelle
(sh -c 'echo $PPID'; : )
- siehe meinen Kommentar auf John1024 Antwort .Wie wäre es
BASH_SUBSHELL
?quelle
[dies hätte ein Kommentar sein sollen, aber meine Kommentare werden in der Regel von Moderatoren gelöscht, daher bleibt dies eine Antwort, die ich als Referenz verwenden könnte, auch wenn sie gelöscht werden.]
Die Verwendung
BASH_SUBSHELL
ist völlig unzuverlässig, da sie nur in einigen Subshells auf 1 gesetzt wird, nicht in allen Subshells.Bevor Sie behaupten, dass der Subprozess, in dem ein Pipeline-Befehl ausgeführt wird, keine wirklich echte Subshell ist, sollten Sie folgendes
man bash
Snippet betrachten:und die praktischen Implikationen - es ist wichtig, ob ein Skriptfragment in einem Unterprozess ausgeführt wird oder nicht, und keine terminologische Auseinandersetzung.
Die einzige Lösung, wie bereits in den Antworten auf diese Frage erläutert , besteht darin, zu prüfen, ob sie
$BASHPID
gleich$$
oder tragbar, aber viel weniger effizient sind:quelle
BASH_SUBSHELL
ist ziemlich zuverlässig eingestellt, aber es ist zweifelhaft, ob der Wert richtig eingestellt wird. Beachten Sie, was in den Dokumenten steht : "Inkrementiert um eins in jeder Subshell- oder Subshell-Umgebung, wenn die Shell in dieser Umgebung ausgeführt wird. " Ich glaube, dass im Pipe-Beispiel die Ausführung von Bash in dieser Subshell noch nicht begonnen hat, wenn die Variable erweitert wird. Sie können vergleichenecho $BASH_VERSION
mitdeclare -p BASH_VERSION
- letzteres sollte zuverlässig Ausgang 1 mit Rohren, Hintergrundjobs etc.eval 'echo $BASH_SUBSHELL $BASHPID' | cat
gibt 1 für ausBASH_SUBSHELL
, da die Variable nach dem Start der Ausführung erweitert wird.subshell_level
wirklich aufgeschoben , was wahrscheinlich einen Grund hat, den ich aber nicht ausmachen kann ;-)echo $$ $BASHPID $BASH_SUBSHELL | cat
.