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


32

長い時間がかかるスクリプトを開始する場合、スクリプトを開始した後に必然的にそれを認識し、終了後に何らかのアラートを行う方法があればいいのにと思います。

したがって、たとえば、私が実行した場合:

really_long_script.sh

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

回答:


45

複数のコマンドをで区切ることができる;ため、たとえば次のように順番に実行されます。

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を始めほとんどのように、それがバックグラウンドで実行するだろう&


@mlissnerは、このケースをカバーするために私の答えを拡大
オーランド

8
以来fg、それが再開ジョブの戻り値は、使用することができますfg && echo Finishedあなたは、コマンドが他のコマンドを実行する前に成功したことを確認したい場合。
-palswim

13

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]上記のように表示されます。


11

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

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

2
の創造的な使用が大好きですwatch。超簡単な答えで、時計を使用する新しい便利な方法を学びます
Piotr Czapla

2

これは難しくありません。既存のコマンドが実行されている間に次のコマンドをウィンドウに入力し、Enterキーを押すと、最初のコマンドが終了すると、2番目のコマンドが自動的に実行されます。

もっとエレガントな方法があると思いますが、これはうまくいくようです。

コマンドの終了後にアラートを実行する場合は、編集して.bashrcにこれらのエイリアスを作成し、実行alert中に実行できます。

 alias alert_helper='history|tail -n1|sed -e "s/^\s*[0-9]\+\s*//" -e "s/;\s*alert$//"'
 alias alert='notify-send -i gnome-terminal "Finished Terminal Job" "[$?] $(alert_helper)"'

7
実行中のスクリプトが、ある時点での入力を予期しない限り。
ダニエルベック

@ダニエル-はい...それは問題です。シュート。
mlissner

1

少し前に、別のプロセスの終了を待つスクリプトを書きました。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を自分でルックアップすることへの依存を避け、受け入れたい場合、興味深いかもしれません。

#!/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ましたが、私の目的にとって最もきれいで信頼性が高いです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.