Kann ich irgendwie ein "&& prog2" zu einem bereits laufenden prog1 hinzufügen?


87

Die meisten Shells bieten Funktionen wie &&und, ;um die Ausführung von Befehlen auf bestimmte Weise zu verketten. Aber was ist, wenn ein Befehl bereits ausgeführt wird? Kann ich trotzdem einen weiteren Befehl hinzufügen, der abhängig vom Ergebnis des ersten ausgeführt werden soll?

Angenommen, ich bin gerannt

$ /bin/myprog
some output...

aber ich wollte wirklich /bin/myprog && /usr/bin/mycleanup. Ich kann nicht myprogalles töten und neu starten, weil zu viel Zeit verloren gehen würde. Ich kann Ctrl+ Zes und fg/ bgfalls erforderlich. Kann ich damit einen anderen Befehl verketten?

Ich bin hauptsächlich an Bash interessiert, aber Antworten für alle gängigen Shells sind willkommen!

Antworten:


118

Sie sollten dies in der gleichen Shell tun können, in der Sie sich mit dem waitBefehl befinden:

$ sleep 30 &
[1] 17440

$ wait 17440 && echo hi

...30 seconds later...
[1]+  Done                    sleep 30
hi

Auszug aus der Bash-Manpage

wait [n ...]
     Wait for each specified process and return its termination status. Each n 
     may be a process ID or a job specification; if a job spec is given,  all 
     processes  in that job's pipeline are waited for.  If n is not given, all 
     currently active child processes are waited for, and the return status is 
     zero.  If n specifies a non-existent process or job, the return status is 
     127.  Otherwise, the return status is the exit status of the last process 
     or job waited for.

Das Warten auf den Befehl sollte den Job erledigen.
BillThor

Es gibt eine Reihe von Kurzformen für die PID des backgrounded Prozesses Eingabe wie %, %1und $!. Es ist wichtig, die PID anzugeben, da sonst der zweite Befehl immer ausgeführt wird.
BillThor

@ BillThor - qualifizieren Sie nur die Antwort oder sagen Sie mir dies?
slm

Ich qualifiziere die Antwort. Eine Ebene waitliefert nicht das gewünschte Ergebnis. Es ist üblich, die Kurzformulare zu verwenden, da sie weniger anfällig für Tippfehler sind.
BillThor

2
Lass mich der Erste sein, der dir zu deinem glänzenden neuen Abzeichen gratuliert :)
terdon

63

fgkehrt mit dem Exit-Code aus dem wiederaufgenommenen Programm zurück. Sie können daher Ihr Programm mit anhalten ^Zund anschließend fg && ...mit fortsetzen.

$ /bin/myprog
some output...
^Z
[1]+ Stopped              /bin/myprog
$ fg && /usr/bin/mycleanup

Wenn Sie den Vorgang vor dem Ende erneut unterbrechen und dasselbe mit einem anderen Befehl ausführen, wird die anfängliche Verkettung von mycleanup ersetzt?
Burhan Ali

3
@BurhanAli Beim myprogzweiten Anhalten wird der Vorgang fgmit dem Exit-Code 20 abgebrochen, der nicht Null ist, sodass der verkettete mycleanupBefehl nicht ausgeführt wird.
4.

1

Sie sind sich nicht sicher, ob das, wonach Sie fragen, möglich ist, aber wenn Sie immer noch die Shell haben, von der aus Sie das Programm gestartet haben, können Sie immer nach dem Beendigungsstatus $?des letzten Prozesses suchen:

$ /bin/myprog
some output...
$ if [ $? -ne 0 ];then echo "non-zero exit status";else echo "0 exit status";fi

1
Dies wird funktionieren, aber er muss dies anschließend manuell ausführen. Er möchte dies automatisch ausführen, wenn der Befehl beendet ist.
slm

@slm Einverstanden. Ich habe keine Lösung für genau dieses Problem.
Joseph R.

3
Check out waitBefehl in Bash.
slm

1

Befindet sich der Job im Vordergrund, verhält sich jeder dieser Befehle wie erwartet.

[ $? -eq 0 ] && prog2
(( $? )) || prog2

HINWEIS: $? wird den Rückgabestatus des laufenden Programms enthalten, wenn es beendet wird.

Hier wird explizit angegeben, was die Shell tun würde, wenn Sie den Befehl ursprünglich eingegeben hätten.

prog1 && prog2

Wenn der erste Befehl nicht ausliest stdinund im Vordergrund ausgeführt wird, kann der neue Befehl eingegeben werden, während der erste Befehl ausgeführt wird. Die Shell liest es und führt es aus, wenn der erste Befehl ausgeführt wird. Wenn der Befehl im Hintergrund ausgeführt wird, ist es unwahrscheinlich, dass er gelesen wird stdin.

BEARBEITEN: Sie können den Job auch in den Hintergrund stellen und den WAITBefehl verwenden. Dies muss mit Vorsicht erfolgen, wenn andere Jobs auch im Hintergrund ausgeführt wurden. Eine Auftragsspezifikation ist erforderlich, damit der WAITBefehl den Status des Auftrags zurückgibt, auf den gewartet wurde.


Dies wird funktionieren, aber er muss dies anschließend manuell ausführen. Er möchte dies automatisch ausführen, wenn der Befehl beendet ist.
slm

4
@slm Solange der Befehl nicht stdin liest, kann der neue Befehl eingegeben werden, während der erste Befehl ausgeführt wird. Die Shell liest es, sobald der erste Befehl ausgeführt wurde.
BillThor

Wenn er irgendetwas in der Shell macht, nachdem sie im Hintergrund ist, ist es wahrscheinlich abgespritzt. Zumindest nach dem Vorwort. Tests habe ich bisher gemacht!
slm

2
@ BillThor Ich denke, Sie sollten diesen Kommentar zu Ihrer Antwort hinzufügen.
Joseph R.

2
Ja, die Verwendung waitist auch nicht ideal. Der Vorteil, IMO, ist, dass wir eine klarere API haben, mit der wir es zu tun haben. Weitere Befehle in der Befehlszeile einzugeben, nachdem etwas ausgeführt wurde, schien mir ein wenig hacky zu sein. waitleidet immer noch daran, keine direkte Verbindung zu der laufenden PID zu erhalten, während der Rückgabestatus angezeigt wird. Dies scheint eher ein Problem zu sein, wenn Bash die Dinge implementiert: stackoverflow.com/questions/356100/… . Das könnte also so gut sein, wie es nur geht.
slm
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.