すでに実行中の既存のコマンドが終了した後に、別のコマンドを実行するにはどうすればよいでしょうか?

すでに実行中の既存のコマンドが終了した後に、別のコマンドを実行するにはどうすればよいでしょうか?

長時間かかるスクリプトを開始すると、スクリプトを開始した後に必ずそのことに気づき、終了したら何らかのアラートを出す方法があればいいのにと思うことになります。

たとえば、次のように実行します。

really_long_script.sh

Enter キーを押します...完了したら別のコマンドを実行するにはどうすればよいでしょうか?

答え1

複数のコマンドを で区切って;、順番に実行することができます。例:

really_long_script.sh ; echo Finished

スクリプトが戻りコード 0 で終了した場合にのみ次のプログラムを実行する場合 (通常は、スクリプトが正しく実行されたことを意味します)、次のようにします。

really_long_script.sh && echo OK

逆のこと(つまり、現在のコマンドが失敗した場合にのみ続行する)をしたい場合は、次のようにします。

really_long_script.sh || echo FAILED

スクリプトをバックグラウンドで実行することもできます (ただし、スクリプトの出力 (stdoutおよびstderr) は、どこかにリダイレクトしない限り、引き続きターミナルに送信されることに注意してください)。その後、wait次のようにします。

really_long_script.sh &
dosomethingelse
wait; echo Finished

すでにスクリプトを実行している場合は、 を使用してスクリプトを一時停止しCtrl-Z、次のようなコマンドを実行できます。

fg ; echo Finished

fg中断されたプロセスをフォアグラウンドに移動する場所(bg開始時とほぼ同じように、バックグラウンドで実行されるようになります&

答え2

プロセスが現在の tty で実行されない場合は、次を試してください。

watch -g ps -opid -p <pid>; mycommand

答え3

bashのジョブ制御も使用できます。

$ really_long_script.sh

次に、Ctrl + Z を押して一時停止します。

^Z
[1]+  Stopped                 really_long_script.sh
$ bg

ジョブをバックグラウンドで再開します( で開始した場合と同様really_long_script.sh &)。その後、このバックグラウンドジョブを待機するには、

$ wait N && echo "Successfully completed"

ここで、N はジョブ ID (他のバックグラウンド ジョブを実行していない場合はおそらく 1) であり、[1]上と同じように表示されます。

答え4

少し前に、別のプロセスの終了を待つスクリプトを作成しました。が正しく設定されていれば、NOISE_CMDのようなものになります。notify-send ...DISPLAY

#!/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

引数なしで、ただちにノイズを出します。この動作により、次のようなことが可能になります (以下のスクリプトを呼び出すとしますalarm.sh)。

apt-get upgrade ; ~/bin/alarm.sh

もちろん、このようなスクリプトでは、 のインスタンスを、他のコマンドalarm.shを待っている のインスタンスまで待たせるなど、さまざまな面白いことができますalarm.sh。または、ログインしている他のユーザーのタスクが終了した直後にコマンドを実行することもできます... >:D

pgrepプロセス ID への依存を回避し、プロセス ID を自分で検索することを受け入れたい場合は、上記のスクリプトの以前のバージョンが興味深いかもしれません。

#!/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 "$@"

少し話題から外れますが、似たような状況で役立つもの:reptyrは、ある(親)シェルからプロセスを「盗み」、現在のシェルからそれを実行するツールです。私は同様の実装を試しましたが、これがreptyr私の目的にとって最も美しく、最も信頼性が高いものでした。

関連情報