Bash - Ausführen von Befehlen in der aktuellen Shell

8

Ich habe das O'Reilly-Buch "Unix auf den Punkt gebracht" gelesen und dort gesehen, dass Befehle in der aktuellen Shell im folgenden Format gruppiert und ausgeführt werden können:

{ cmd1 ; cmd2 }

Ich habe nicht verstanden, wie dies möglich ist, da ich wusste, dass ein Aufruf von exec die Daten einer Shell ersetzt und die Shell daher nicht von einem Aufruf des exec-Systems zurückkehren kann. Also habe ich den Befehl getestet und kann nicht verstehen, was passiert ist. Ich habe eine Befehlszeile eingegeben und bin mir nicht sicher, wozu die Befehlszeile gehört.

Ist es nur die Befehlszeile des Terminalemulators, die von der Shell entfernt wurde?

Wie ist es in irgendeiner Weise nützlich, Befehle in der aktuellen Shell auszuführen?

Geben Sie hier die Bildbeschreibung ein

user3122885
quelle

Antworten:

6

Ausführen oder nicht ausführen

Ein Aufruf von exec ersetzt die Daten einer Shell, und daher kann die Shell nicht von einem Systemaufruf von exec zurückkehren.

Aber nicht jeder Befehl ist der Name eines auszuführenden Programms. So oft ist kein execAnruf beteiligt. Der Hauptunterschied besteht darin, dass Sie im Gegensatz ( cmd1; cmd2; )dazu keinen weiteren Shell-Prozess erhalten. Oder besser gesagt, die Shell gibt nur untergeordnete Programme aus, keine Shell-Prozesse.

Seltsame Eingabeaufforderung

Was gehört die Kommandozeile dazu?

Wie andere Antworten gezeigt haben, war Ihr Befehl unvollständig. Die Kommandozeile gehörte also zu Bash selbst, das auf das Ende Ihrer Gruppe wartete.

Verwendet

Wie ist es in irgendeiner Weise nützlich, Befehle in der aktuellen Shell auszuführen?

… Im Gegensatz zur Subshell-Gruppierung

Das bekannteste Beispiel ist das Festlegen von Variablen in diesem Unterbefehl. Dein das:

foo=1; { foo=2; echo $foo; }; ( foo=3; echo $foo; ); echo $foo

Dies wird gedruckt

2
3
2

Obwohl Sie foo=3innerhalb einer Gruppe festgelegt haben, wurde diese Gruppe in einer Subshell ausgeführt und ihre Einstellungen wurden nicht an die übergeordnete Gruppe weitergegeben.

Eine andere erwägenswerte Sache ist das aktuelle Arbeitsverzeichnis. { cd foo; make; }Sie werden im Verzeichnis foobelassen, während ( cd foo; make; )das aktuelle Arbeitsverzeichnis Ihrer Haupt-Shell nicht geändert wird.

… Im Gegensatz zu nicht gruppierten Befehlen

Die Gruppierung ist meistens nützlich, wenn Sie anderen Code außerhalb haben, z. B. Bedingungen

test -f foo && { echo "Foo exists."; rm foo; }

oder Weiterleitungen

{ echo "Content of $PWD:"; ls; } | gzip > dirlist.gz
MvG
quelle
10

Dies liegt daran, dass Sie die zweite Zeile nicht beenden: { cmd1; cmd2; }ist korrekt. Das Semikolon bedeutet "Befehlsende".

Jo-Erlend Schinstad
quelle
Sie haben Recht, danke (vielleicht verwendet das Buch ein altes Format). Aber wie ist es möglich, die Shell wieder aufzunehmen, wenn die Befehle darin ausgeführt werden? Ruft die Shell Gabel auf?
user3122885
Die Shell wird blockiert, bis der Befehl beendet ist. Dies ist eigentlich ein guter Grund, Gruppen zu verwenden. Wenn Sie beispielsweise eine PPA hinzufügen, möchten Sie zuerst die Repository-Informationen hinzufügen, dann Schlüssel importieren, dann Ihren Cache aktualisieren und dann installieren. Wenn Sie es als Gruppe einfügen, wird alles in der richtigen Reihenfolge ausgeführt. Wenn Sie dies nicht tun, müssen Sie erneut eingeben, da die Shell Ihre Eingabe nicht empfangen kann.
Jo-Erlend Schinstad
5

Das helpeingebaute kann sogar für das {Schlüsselwort nützlich sein . Von help -m {:

NAME
    { ... } - Group commands as a unit.

SYNOPSIS
    { COMMANDS ; }

Daher ist das Semikolon ( ;) nach jedem Befehl obligatorisch.

Radu Rădeanu
quelle