Führen Sie einen Befehl nach dem anderen aus, auch wenn ich den ersten anhalte (Strg-z).

69

Ich weiß, dass ich in bash einen Befehl nach dem anderen ausführen kann, indem ich sie durch Semikolons trenne, wie z

$ command1; command2

Oder wenn ich nur command2ausführen möchte , wenn dies command1erfolgreich ist, verwenden Sie &&:

$ command1 && command2

Dies funktioniert, aber wenn ich die command1Verwendung unterbreche Ctrl-z, wird sie im ersten Fall command2sofort ausgeführt, und im zweiten Fall wird sie überhaupt nicht ausgeführt. Wie kann ich Befehle nacheinander ausführen, aber dennoch den ersten Befehl anhalten, aber den zweiten Befehl erst ausführen, nachdem ich ihn (mit fg) neu gestartet und beendet habe? Ich würde es vorziehen, etwas so einfach wie möglich zu tippen, da ich dies interaktiv tun möchte. Oder vielleicht muss ich einfach irgendwo eine Option einstellen.

Was ist übrigens der richtige Begriff für was Ctrl-z?

asmeurer
quelle
2
command1; command2sollte genau das tun, was Sie wollen. In Bezug auf die Terminologie setzt Strg-Z den Prozess aus.
NPE
Nun, das tut es nicht. Ich verwende die Bash-Version 4.2.8(2)-releaseunter Mac OS X 10.8 in iTerm2.
Asmeurer
Danke für die Terminologie. Ich werde die Frage aktualisieren, um sie zu verwenden.
Asmeurer
Ja, du hast recht, das tut es nicht. Ich denke du brauchst eine Unterschale. Siehe meine Antwort.
NPE

Antworten:

95

Folgendes sollte es tun:

(command1; command2)

Beachten Sie die hinzugefügten Klammern.

NPE
quelle
5
Genial! Nun verstehen Sie oder jemand Pflege einer Erklärung geben, warum es sich verhält, wie es funktioniert für diese drei Fälle ( command1; command2, command1 && command 2, und (command1; command2))?
Asmeurer
2
Eigentlich bin ich mir nicht sicher. Vielleicht könnte jemand uns beide aufklären.
NPE
44
Technisch gesehen setzen Sie Prozesse mit Control-z nicht aus, sondern setzen Jobs aus . Mit command1; command2ist der aktive Job nur der Vorgang, command1wenn Sie Strg-z drücken. Er wird also angehalten und der nächste Job ( command2) beginnt. Mit (command1; command2)besteht der aktive Job aus der Unterschale, in der die beiden Befehle ausgeführt werden, sodass die gesamte Unterschale von Control-z angehalten wird. Sie können dies bestätigen, indem Sie den jobsBefehl nach dem Anhalten ausführen.
Chepner
Danke @chepner, und was ist mit der command1 && command2Option? Das begegne ich häufig. Obwohl der Job aus beiden Befehlen zusammen besteht, habe ich auch festgestellt, dass der zweite Befehl nach dem Hintergrund nicht ausgeführt wird. (command1 && command2)funktioniert natürlich, aber ich weiß oft nicht, dass ich einen Prozess im Voraus hinterfragen möchte. Sonst hätte ich es von Anfang an als Hintergrundjob ausgeführt.
Mattatt
1
command1 && command2ist eigentlich zwei Jobs (ein Job besteht aus einer Pipeline, und die &&Liste besteht aus zwei (Einzelprozess-) Pipelines command1und command2). Der zweite Befehl wird erst ausgeführt command1, command1wenn er beendet wird (mit dem Status Null), und wird nicht beendet, wenn er gestoppt wird.
Chepner
11

Wenn Sie in Bash einen Job in den Hintergrund stellen (mit STRG + Z oder &), wartet er nicht auf den Abschluss des Jobs und gibt einen Beendigungscode von Null (Erfolg). So viel haben Sie beobachtet und es ist auf den manSeiten dokumentiert .

Das logische "UND" && wird von links nach rechts getestet. Jeder Teil muss erfolgreich sein. Wenn der erste Teil nicht erfolgreich ist, wird der zweite nicht ausgeführt. Mit && werden also Befehle von links nach rechts ausgeführt, bis einer von ihnen fehlschlägt. Die Definition von Erfolg ist ein Exitcode ($?) Von Null.

Vergleichen Sie dies mit dem logischen "ODER" ||, das Befehle von links nach rechts ausführt, bis einer von ihnen funktioniert .

Erläuterungen zur Subshell-Lösung von @NPE finden Sie auch auf den folgenden manSeiten:

Zusammengesetzte Befehle und Befehlssequenzen der Form 'a; b; c 'werden nicht ordnungsgemäß behandelt, wenn versucht wird, den Prozess auszusetzen. Wenn ein Prozess gestoppt wird, führt die Shell sofort den nächsten Befehl in der Sequenz aus. Es reicht aus, die Befehlsfolge in Klammern zu setzen, um sie in eine Unterschale zu zwingen, die als Einheit gestoppt werden kann.

Der richtige Begriff für STRG + Z ist das Suspend- Zeichen, wieder von den manSeiten:

Wenn Sie das Suspend-Zeichen (normalerweise ^ Z, Control-Z) eingeben, während ein Prozess ausgeführt wird, wird dieser Prozess gestoppt und die Steuerung an bash zurückgegeben.

(Tut mir leid, die manSeiten so oft zu zitieren , aber sie sind wirklich deine Freunde und lesenswert)

Wenn Sie sich das ansehen, werden stty -aSie so etwas sehen:

susp = ^Z; 

Sie können es also ändern, daher der Ausdruck "typisch". Tun Sie das aber nicht, es wird jeden verwirren. Der Terminaltreiber löst ein SIGTSTP-Signal aus, das von Bash abgefangen wird.

cdarke
quelle
Ich verstehe das Verhalten mit && immer noch nicht. Wird der Prozess durch Anhalten ungleich Null zurückgegeben?
Asmeurer
Von welchen Manpages stammen diese? Ich dachte, die Antwort könnte da sein, aber ich hatte keine Ahnung, wo ich überhaupt anfangen sollte.
Asmeurer
&&verbindet zwei Pipelines , und jede Pipeline ist ein separater Job. (Beachten Sie, dass es sich bei der Pipeline um einen oder mehrere Befehle handelt |, die durch a verbunden sind. Dies bedeutet, dass command1es sich technisch gesehen um eine einzelne Pipeline mit einem Befehl handelt.)
Chepner