Befehle in die Warteschlange stellen, während ein Befehl ausgeführt wird

Befehle in die Warteschlange stellen, während ein Befehl ausgeführt wird

Angenommen, Sie führen einen Befehl aus, dessen Rückkehr einige Zeit in Anspruch nimmt, und möchten nach dessen Ausführung einen anderen Befehl ausführen, haben dies jedoch nicht im Voraus geplant.

Ich weiß, dass es die Möglichkeit gibt, auf Ctrl + Z„Senden“ zu klicken fg && otherCommand. Dies hat jedoch zwei große Mängel:

  1. Dies funktioniert nicht, wenn der erste Befehl aus einer Kombination verschiedener Befehle ( command1 && command2oder command1; command2) besteht, da dann die nachfolgenden Befehle der ersten übermittelten Zeile nicht ausgeführt werden.
  2. Die Ausführung des ersten Befehls wird angehalten, während Sie den nächsten Befehl eingeben. Bei diesen fiesen 30-Sekunden-Befehlen macht die Zeit, die Sie mit der Eingabe des nächsten Befehls verbringen, einen Großteil der verbleibenden Ausführungszeit aus, wenn nicht sogar die gesamte.

Ich weiß auch, dass man einfach den nächsten Befehl eingeben kann, während ein anderer Befehl ausgeführt wird, und Enterihn dann mit der Taste absenden kann. Dies hat jedoch auch zwei große Mängel:

  1. Es funktioniert nicht, wenn der von Ihnen ausgeführte Befehl zuerst von liest stdin.
  2. Wenn der zuerst ausgeführte Befehl eine Ausgabe erzeugt, können Sie nicht sehen, was Sie eingegeben haben.

Gibt es eine schnelle Möglichkeit, mehrere Befehle in die Warteschlange zu stellen, während ein Befehl ausgeführt wird, möglicherweise durch die Verwendung eines speziellen Terminalemulators oder mehrerer Terminals?

Antwort1

Drücken Sie Ctrl+ Zund führen Sie sofort aus bg. Dadurch wird der aktuelle Befehl im Hintergrund weiter ausgeführt. Anschließend können Sie verwenden, um nach dem aktuellen Befehl fg && otherCommandeinen Zeitplan einzugeben .otherCommand

Um dies zu vereinfachen, habe ich Ctrl+ Zin meiner Shell so konfiguriert, dass es ausgeführt wird bg, wenn ich es in einer leeren Befehlszeile drücke. SieheWie kann ich in zsh den Vordergrundprozess schneller verwerfen?UndWie senden Sie Befehlszeilen-Apps direkt in den Hintergrund?; Ich habe nicht überprüft, ob moderne Versionen von Bash dasselbe problemlos ermöglichen.

Antwort2

Sie können eine benannte Pipe erstellen (dies muss einmal durchgeführt werden):

mkfifo ~/myfifo

Dann können Sie von einem Terminal (nennen wir es Terminal A) aus sagen:

exec 10< ~/myfifo

Um das Lese-Ende der Pipe dem Datei-Deskriptor 10 zuzuweisen, können Sie jede andere Zahl über 2 verwenden (sodass die Standardeingabe, -ausgabe und -fehler verfügbar bleiben, wenn ein anderer Befehl sie benötigt).

Dann können Sie von einem anderen Terminal (nennen wir es Terminal B) sagen:

cat - > ~/myfifo

Um die Verbindung zu Terminal A herzustellen, das dann die Eingabeaufforderung zurückgibt. Dieser Befehl schreibt das, was Sie von der Standardeingabe eingeben, in die Pipe. Anschließend können Sie Folgendes in Terminal A eingeben:

while read -u10 -r LINE; do eval "$LINE"; done

Es führt also die Befehle aus, die Sie in Terminal B eingeben. Der readBefehl liest Zeilen aus dem Dateideskriptor 10 und führt sie mit aus eval. evalermöglicht Ihnen, Shell-Befehle auszuführen, wie z. B. das Exportieren von Variablen.

Solange Terminal A geöffnet ist, können Sie die Schleife mit Strg+C unterbrechen, um erneut Befehle einzugeben. Später können Sie die Schleife neu starten, um mit der Ausführung der verbleibenden in der Warteschlange befindlichen Befehle zu beginnen.

Die Befehle „exec“ und „while“ können in ein Shellskript eingefügt werden, sodass Sie mit Strg+Z fg && yourscriptden Pipe-Modus aktivieren können, falls Sie dies am Anfang vergessen haben.

Antwort3

Sie möchten höchstwahrscheinlich:

wait $pid

Wenn Sie nicht in derselben Shell arbeiten, können Sie kein integriertes Tool verwenden und benötigen eine Problemumgehung. Siehe DiskussionHier.

Antwort4

BEARBEITEN:Ich habe die Frage falsch interpretiert, aber die folgende Technik könnte für Benutzer dennoch nützlich sein, die Befehle in einem Bash-Skript ausführen (damit sie eine einzelne PID haben).

Das hier ist, was ich (unter Linux) verwende, wenn command1 eine nützliche Ausgabe druckt und ich einfach einen anderen Prozess in einer anderen Shell starten möchte, sobald dieser fertig ist (das heißt, ich möchte command1 nicht in den Hintergrund stellen):

tail --pid=$command1_pid -f /dev/null; command2

wo $command1_pidist die PID des Prozesses, auf dessen Abschluss Sie warten

(Ich glaube, ich habe es ursprünglich hier gefunden:https://stackoverflow.com/a/41613532/1676393. Weitere hilfreiche Details finden Sie dort. Beispielsweise eine Version, die unter Darwin (macOS) funktioniert.)


Schritt für Schritt:

  • stoppe command1 mit Ctrl+Z
  • Führen Sie den Befehl aus ps, suchen Sie nach dem Prozess, der dem Befehl „command1“ entspricht, und ermitteln Sie seine PID.
  • Starten Sie dann den Prozess von command1 neu, indem Sie eingeben fg, und führen Sie in einer neuen Shell den obigen Befehl aus

Auf diese Weise wird Befehl2 in der neuen Shell gestartet, wenn Befehl1 in der alten Shell ausgeführt wird.

verwandte Informationen