web-dev-qa-db-ja.com

bashで2つのコマンドを同時に使用するCtrl-C

Linuxマシンのbashで2つのコマンドを同時に実行したい。したがって、私の./execute.sh私が置いたbashスクリプト:

command 1 & command 2
echo "done"

ただし、bashスクリプトを停止してヒットしたい場合 Ctrl+C、2番目のコマンドのみが停止します。最初のコマンドは実行を続けます。完全なbashスクリプトが停止していることを確認するにはどうすればよいですか?またはいずれにしても、両方のコマンドを停止するにはどうすればよいですか?この場合、私がどれだけ頻繁に押しても Ctrl+C コマンドは実行を続け、ターミナルを閉じることを余儀なくされます。

15
maero21

入力した場合

command 1 & command 2

これは

command 1 &
command 2

つまり、これは最初のコマンドをバックグラウンドで実行し、次に2番目のコマンドをフォアグラウンドで実行します。特にこれは、echo "done"がまだ実行されている場合でも、command 2が終了した後にcommand 1が出力されることを意味します。

あなたはおそらく欲しい

command 1 &
command 2 &
wait
echo "done"

これにより、両方のコマンドがバックグラウンドで実行され、両方が完了するまで待機します。


CTRL-Cを押すと、SIGINTシグナルがフォアグラウンドプロセスにのみ送信されます。つまり、バージョンではcommand 2、バージョンではwaitになります。

次のようにトラップを設定することをお勧めします。

#!/bin/bash

trap killgroup SIGINT

killgroup(){
  echo killing...
  kill 0
}

loop(){
  echo $1
  sleep $1
  loop $1
}

loop 1 &
loop 2 &
wait

トラップを使用すると、CTRL-Cによって生成されたSIGINTシグナルがトラップされ、killgroup関数によって置き換えられます。これにより、これらすべてのプロセスが強制終了されます。

17
michas

スクリプトからコマンドをバックグラウンドに配置すると、PIDが画面に表示されません。最後のプロセスのPIDを格納する組み込み変数$!を使用して、command1のPIDを取得できます。

command1 &
echo $!

command1のPIDをエコーし​​ます。

Bashには、特定の信号を受信したときに実行する一連のコマンドを登録するために使用できる組み込みトラップも用意されています。これを使用して、メインスクリプトを終了する前にSIGINTおよびkill command1をキャッチできます。

#!/bin/bash

onINT() {
echo "Killing command1 $command1PID too"
kill -INT "$command1PID"
exit
}

trap "onINT" SIGINT
command1 &
command1PID="$!"
comamnd2
echo Done

さて、コマンド2の実行中に、 CtrlC command1とcommand2の両方がSIGINTに送信されます。

6
user591

GNU Parallelの新しいバージョンは、あなたが望むことをします:

parallel ::: "command 1" "command 2"
echo "done"

または、commandが同じ場合:

parallel command ::: 1 2
echo done

簡単な概要については、紹介ビデオをご覧ください: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

チュートリアル(man parallel_tutorial)をウォークスルーします。あなたはそれを愛しています。

5
Ole Tange

CtrlC SIGINTシグナルをcommand2であるフロントプロセスに送信します。 command1はバックグラウンドで実行されるため、入力ストリームは関係ありません。

command1 &と入力すると、bashは[1234]のようなプロセスのPIDを提供します。このプロセスを強制終了するには、kill 1234を使用できます。これで、command1command2の両方のPIDがある場合(ps -efを確認してください)、killを使用してそれらすべてを終了できます。

kill pid1 pid2 pid3 ...

少しトリックは、両方のコマンドをバックグラウンドで実行することです:

command1 & command2 &

Bashは両方のPIDを提供し、殺される準備ができています。もう1つのトリックは、command1を終了したら、command2をフォアグラウンドに戻すことです。

command1 & command2
# Hit Ctrl+C : command2 terminates.

fg # Bring back command1 to foreground.
# Hit Ctrl+C again, command1 terminates.

詳細についてはこちらをご覧ください: http://linuxg.net/how-to-manage-background-and-foreground-processes/

1
John WH Smith