Ich möchte eine Bash-Subshell ausführen, (1) einige Befehle ausführen, (2) und dann in dieser Subshell bleiben, um zu tun, was ich möchte. Ich kann jedes von diesen einzeln tun:
Befehl mit
-c
Flag ausführen:$> bash -c "ls; pwd; <other commands...>"
Es kehrt jedoch sofort zur "super" Shell zurück, nachdem die Befehle ausgeführt wurden. Ich kann auch einfach eine interaktive Subshell ausführen:
Neuen
bash
Prozess starten :$> bash
und es wird die Subshell nicht verlassen, bis ich es explizit sage ... aber ich kann keine anfänglichen Befehle ausführen. Die nächste Lösung, die ich gefunden habe, ist:
$> bash -c "ls; pwd; <other commands>; exec bash"
Das funktioniert, aber nicht so, wie ich es wollte, da es die angegebenen Befehle in einer Subshell ausführt und dann eine separate für die Interaktion öffnet.
Ich möchte dies in einer einzigen Zeile tun. Sobald ich die Subshell verlasse, sollte ich ohne Zwischenfälle zur regulären "Super" -Shell zurückkehren. Es muss einen Weg geben ~~
NB: Was ich nicht frage ...
- Ich fragte nicht, wo ich die Bash-Manpage finden sollte
- Ich frage nicht, wie man Initialisierungsbefehle aus einer Datei liest ... Ich weiß, wie man das macht, es ist nicht die Lösung, nach der ich suche
- nicht daran interessiert, tmux oder gnu screen zu benutzen
- nicht daran interessiert, Kontext zu geben. Das heißt, die Frage soll allgemein und nicht für einen bestimmten Zweck sein
- Wenn möglich, möchte ich vermeiden, Problemumgehungen zu verwenden, die das erreichen, was ich will, aber auf "schmutzige" Weise. Ich möchte dies nur in einer einzigen Zeile tun. Insbesondere möchte ich so etwas nicht tun
xterm -e 'ls'
exec bash
Lösung für Sie ungeeignet?exec bash
Lösung umfasst auch zwei separate Unterschalen. Ich möchte eine durchgehende Unterschale.exec
ist , dass es ersetzt die erste Sub - Shell mit dem zweiten, so dass Sie nur links 1 Schale unter dem Elternteil. Wenn Ihre Initialisierungsbefehle Umgebungsvariablen festlegen, sind diese in der ausgeführten Shell vorhanden.exec
ist, dass Sie alles verlieren, was nicht über die Umgebung an Subshells weitergegeben wird, wie nicht exportierte Variablen, Funktionen, Aliase, ...Antworten:
Dies kann einfach mit temporären Named Pipes durchgeführt werden :
Dank für diese Antwort geht an den Kommentar von Lie Ryan . Ich fand das wirklich nützlich und es ist in den Kommentaren weniger auffällig, daher dachte ich, es sollte seine eigene Antwort sein.
quelle
$HOME/.bashrc
jedoch nicht ausgeführt wird. Es müsste aus der temporären Named Pipe aufgenommen werden.bash --init-file <(echo ". \"$HOME/.bashrc\"; ls; pwd")
.
ist ein Synonym für densource
Befehl: ss64.com/bash/source.html .sudo bash --init-file <(echo "ls; pwd")
odersudo -iu username bash --init-file <(echo "ls; pwd")
?Sie können dies auf Umwegen mit einer temporären Datei tun, obwohl es zwei Zeilen dauern wird:
quelle
rm $BASH_SOURCE
.mktemp
löst das Problem mit temporären Dateien, wie @cjc hervorhob. Bash könnte das Lesen der Init-Befehle von stdin unterstützen, aber soweit ich das beurteilen kann, nicht. Das Angeben-
als Init-Datei und das Weiterleiten zur Hälfte funktionieren, aber Bash wird dann beendet (wahrscheinlich, weil es die Pipeline erkannt hat). Die elegante Lösung, IMHO, ist die Verwendung von exec.Versuchen Sie dies stattdessen:
$SHELL
Es öffnet die Shell im interaktiven Modus und wartet auf ein Ende mitexit
.quelle
Die "Expect-Lösung", auf die ich mich bezog, programmiert eine Bash-Shell mit der Programmiersprache Expect :
Du würdest so laufen:
./subshell.exp "ls; pwd"
quelle
Warum nicht native Subshells verwenden?
Durch das Einschließen von Befehlen in Klammern wird Bash-Spawn zu einem Unterprozess, in dem diese Befehle ausgeführt werden. So können Sie beispielsweise die Umgebung ändern, ohne die übergeordnete Shell zu beeinflussen. Dies ist im Prinzip besser lesbar als das
bash -c "ls; pwd; exec $BASH"
.Wenn das immer noch ausführlich aussieht, gibt es zwei Möglichkeiten. Einer ist, dieses Snippet als Funktion zu haben:
Eine andere ist,
exec $BASH
kürzer zu machen :Ich persönlich mag die
R
Herangehensweise mehr, da es nicht nötig ist, mit Streichern zu spielen.quelle
Wenn
sudo -E bash
das nicht funktioniert, verwende ich das Folgende, was meine Erwartungen bisher erfüllt hat:Ich habe HOME = $ HOME festgelegt, weil ich möchte, dass in meiner neuen Sitzung HOME auf HOME des Benutzers und nicht auf HOME des Roots festgelegt wird, was bei einigen Systemen standardmäßig der Fall ist.
quelle
weniger elegant als
--init-file
, aber vielleicht besser instrumentierbar:quelle