![Wie führe ich einen Befehl aus, nachdem ein bereits ausgeführter, bestehender Befehl beendet ist?](https://rvso.com/image/1289035/Wie%20f%C3%BChre%20ich%20einen%20Befehl%20aus%2C%20nachdem%20ein%20bereits%20ausgef%C3%BChrter%2C%20bestehender%20Befehl%20beendet%20ist%3F.png)
Wenn ich ein Skript starte, das lange dauern wird, merke ich das zwangsläufig erst, nachdem ich das Skript gestartet habe, und wünschte, ich hätte die Möglichkeit, eine Art Warnmeldung auszulösen, wenn es fertig ist.
Wenn ich beispielsweise Folgendes ausführe:
really_long_script.sh
und drücken Sie die Eingabetaste. Wie kann ich einen weiteren Befehl ausführen, wenn er abgeschlossen ist?
Antwort1
Sie können mehrere Befehle durch trennen ;
, sodass sie nacheinander ausgeführt werden, zum Beispiel:
really_long_script.sh ; echo Finished
Wenn Sie das nächste Programm nur ausführen möchten, wenn das Skript mit dem Rückgabecode 0 beendet wurde (was normalerweise bedeutet, dass es korrekt ausgeführt wurde), dann:
really_long_script.sh && echo OK
Wenn Sie das Gegenteil möchten (d. h. nur fortfahren, wenn der aktuelle Befehl fehlgeschlagen ist), dann:
really_long_script.sh || echo FAILED
Sie könnten Ihr Skript im Hintergrund ausführen (aber Vorsicht, die Skriptausgabe ( stdout
und stderr
) würde weiterhin an Ihr Terminal gehen, sofern Sie sie nicht irgendwohin umleiten) und dann wait
dafür:
really_long_script.sh &
dosomethingelse
wait; echo Finished
Wenn Sie das Skript bereits ausgeführt haben, können Sie es mit anhalten Ctrl-Z
und dann etwas wie Folgendes ausführen:
fg ; echo Finished
Bringt fg
den angehaltenen Prozess in den Vordergrund ( bg
lässt ihn im Hintergrund laufen, so wie er gestartet wurde &
)
Antwort2
Wenn der Prozess auf dem aktuellen TTY nicht läuft, versuchen Sie Folgendes:
watch -g ps -opid -p <pid>; mycommand
Antwort3
Sie können auch die Jobsteuerung von bash verwenden. Wenn Sie
$ really_long_script.sh
Drücken Sie dann Strg+Z, um es anzuhalten:
^Z
[1]+ Stopped really_long_script.sh
$ bg
um den Job im Hintergrund neu zu starten (so als ob Sie ihn mit gestartet hätten really_long_script.sh &
). Anschließend können Sie mit auf diesen Hintergrundjob warten.
$ wait N && echo "Successfully completed"
wobei N die Job-ID ist (wahrscheinlich 1, wenn Sie keine anderen Hintergrundjobs ausgeführt haben), die auch wie [1]
oben angezeigt wird.
Antwort4
Vor einiger Zeit habe ich ein Skript geschrieben, um auf das Ende eines anderen Prozesses zu warten. NOISE_CMD
Könnte so etwas sein notify-send ...
, vorausgesetzt, es DISPLAY
ist richtig eingestellt.
#!/bin/bash
NOISE_CMD="/usr/bin/mplayer -really-quiet $HOME/sfx/alarm-clock.mp3"
function usage() {
echo "Usage: $(basename "$0") [ PROCESS_NAME [ PGREP_ARGS... ] ]"
echo "Helpful arguments to pgrep are: -f -n -o -x"
}
if [ "$#" -gt 0 ] ; then
PATTERN="$1"
shift
PIDS="$(pgrep "$PATTERN" "$@")"
if [ -z "$PIDS" ] ; then
echo "No process matching pattern \"$PATTERN\" found."
exit
fi
echo "Waiting for:"
pgrep -l "$PATTERN" "$@"
for PID in $PIDS ; do
while [ -d "/proc/$PID" ] ; do
sleep 1
done
done
fi
exec $NOISE_CMD
Ohne Argumente machen Sie einfach sofort etwas Lärm. Dieses Verhalten ermöglicht der Einfachheit halber so etwas wie das Folgende (sagen wir, Sie rufen das folgende Skript auf alarm.sh
):
apt-get upgrade ; ~/bin/alarm.sh
Natürlich kann man mit einem solchen Skript viele lustige Dinge anstellen, wie zum Beispiel eine Instanz von alarm.sh
auf eine Instanz von warten lassen alarm.sh
, die wiederum auf einen anderen Befehl wartet. Oder einen Befehl direkt ausführen, nachdem eine Aufgabe eines anderen angemeldeten Benutzers beendet wurde... >:D
Eine frühere Version des obigen Skripts könnte interessant sein, wenn Sie eine Abhängigkeit vermeiden pgrep
und die Suche nach Prozess-IDs selbst in Kauf nehmen möchten:
#!/bin/bash
if [ "$#" -lt 2 -o ! -d "/proc/$1" ] ; then
echo "Usage: $(basename "$0") PID COMMAND [ ARGUMENTS... ]"
exit
fi
while [ -d "/proc/$1" ] ; do
sleep 1
done
shift
exec "$@"
Etwas abseits vom Thema, aber nützlich in ähnlichen Situationen: Man könnte interessiert sein anreptyr
, ein Tool, das einen Prozess aus einer (übergeordneten) Shell „stiehlt“ und ihn in der aktuellen Shell ausführt. Ich habe ähnliche Implementierungen ausprobiert und reptyr
für meine Zwecke ist dies die schönste und zuverlässigste.