Wie führe ich einen Befehl aus, nachdem ein bereits ausgeführter, bestehender Befehl beendet ist?

Wie führe ich einen Befehl aus, nachdem ein bereits ausgeführter, bestehender Befehl beendet ist?

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 ( stdoutund stderr) würde weiterhin an Ihr Terminal gehen, sofern Sie sie nicht irgendwohin umleiten) und dann waitdafür:

really_long_script.sh &
dosomethingelse
wait; echo Finished

Wenn Sie das Skript bereits ausgeführt haben, können Sie es mit anhalten Ctrl-Zund dann etwas wie Folgendes ausführen:

fg ; echo Finished

Bringt fgden angehaltenen Prozess in den Vordergrund ( bglä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_CMDKönnte so etwas sein notify-send ..., vorausgesetzt, es DISPLAYist 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.shauf 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 pgrepund 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 reptyrfür meine Zwecke ist dies die schönste und zuverlässigste.

verwandte Informationen