複数のコマンドを実行し、bashで1つのコマンドで終了します。

複数のコマンドを実行し、bashで1つのコマンドで終了します。

1つのシェルで複数のコマンド(プロセス)を実行したいと思います。それらはすべて停止しない連続的な出力を持っています。バックグラウンドで実行すると中断されますCtrl。 - を使用してすべてのプロセスを停止Cできるように、単一のプロセス(おそらくサブシェル?)で実行したいと思います。CtrlC

特にmocha(監視モード)を使って単体テストを実行し、サーバを実行し、一部のファイル前処理を実行し(監視モード)、各テストの出力をターミナルウィンドウで確認したいと思います。デフォルトでは、一部のタスクランチャーを使用したくありません。

バックグラウンド(&)でプロセスを実行してこれを実行できますが、プロセスをフォアグラウンドにインポートして停止する必要があります。プロセスをラップしてプロセスを停止すると、「サブプロセス」が停止します。

答え1

コマンドを同時に実行するには、コマンド区切り文字を使用できます&

~$ command1 & command2 & command3

これが開始され、その後command1バックグラウンドで実行されます。と同じですcommand2。これで正常に起動できますcommand3

すべてのコマンドの出力が一緒に歪む可能性がありますが、これが問題にならない場合はこれが解決策です。

後で出力を個別に表示するには、各コマンドの出力にパイプすることで、tee出力をミラーリングするファイルを指定できます。

~$ command1 | tee 1.log & command2 | tee 2.log & command3 | tee 3.log

出力は非常に混乱する可能性があります。この問題を解決するには、各コマンドの出力にプレフィックスを指定できますsed

~$ echo 'Output of command 1' | sed -e 's/^/[Command1] /' 
[Command1] Output of command 1

したがって、これらすべてをまとめると、次のような結果が得られます。

~$ command1 | tee 1.log | sed -e 's/^/[Command1] /' & command2 | tee 2.log | sed -e 's/^/[Command2] /' & command3 | tee 3.log | sed -e 's/^/[Command3] /'
[Command1] Starting command1
[Command2] Starting command2
[Command1] Finished
[Command3] Starting command3

これはあなたが見ることができるものの非常に理想的なバージョンです。しかし、それが私が今考えることができる最善だ。

これらすべてを一度に停止するにはtrap

~$ trap 'kill %1; kill %2' SIGINT
~$ command1 & command2 & command3

これはバックグラウンドとcommand1フォアグラウンドで実行されるため、+を使用して殺すことができます。 command2command3CtrlC

Ctrl+を使用して最後のプロセスを終了すると、コマンドの実行は+を押して送信される割り込み信号の受信に関連付けられ、Cコマンドが実行されます。kill %1; kill %2CtrlC

最初と2番目のバックグラウンドプロセス(あなたcommand1command2)をそれぞれ終了します。コマンドを使用した後にトラップを削除することを忘れないでくださいtrap - SIGINT

モンスターの命令を完了してください。

~$ trap 'kill %1; kill %2' SIGINT
~$ command1 | tee 1.log | sed -e 's/^/[Command1] /' & command2 | tee 2.log | sed -e 's/^/[Command2] /' & command3 | tee 3.log | sed -e 's/^/[Command3] /'

もちろん見学することもできます画面。必要に応じて、コンソールを複数の個別のコンソールに分割できます。これにより、すべてのコマンドを同時に個別に監視できます。

答え2

同じプロセスで実行するようにスケジュールし、そのプロセスのみを実行するようにスケジュールすると、一度に複数のプロセスを簡単にシャットダウンできます。プロセスグループ

Linuxはユーティリティを提供しますsetsid新しいプロセスグループでプログラムを実行します(または新しいセッションでも実行されますが、私たちはそれを気にしません)。 (これはうまくいくがもっと複​​雑いいえsetsid

プロセスグループのプロセスグループID(PGID)は、グループ内の元の親プロセスのプロセスIDです。プロセスグループ内のすべてのプロセスを終了するには、負のPGIDをkillシステムコールまたはコマンドに渡します。そのPIDを持つ元のプロセスが終了しても、PGIDは有効なままです(やや混乱する可能性があります)。

setsid sh -c 'command1 & command2 & command3' &
pgid=$!
echo "Background tasks are running in process group $pgid, kill with kill -TERM -$pgid"

バックグラウンドでプロセスを実行している場合非対話型その後、それらはすべてシェルのプロセスグループに残ります。対話型シェルでのみ、バックグラウンドプロセスが独自のプロセスグループで実行されます。したがって、フォアグラウンドに残っている非対話型シェルからコマンドを分岐すると、+はCtrlすべてCのコマンドを終了します。waitすべてのコマンドが終了するまでシェルが待機するようにするには、組み込みコマンドを使用します。

sh -c 'command1 & command2 & command3 & wait'
# Press Ctrl+C to kill them all

答え3

まだ出ていないのは驚きですが、私の好きな方法はサブシェルバックグラウンドコマンドで。使用法:

(command1 & command2 & command3)

両方の出力が表示され、すべてのbashコマンドと便利な機能を引き続き使用でき、単一のコマンドで両方をCtrl-c終了できます。私は通常これを使用してライブデバッグクライアントファイルサーバーとバックエンドサーバーの両方を起動するので、必要に応じて簡単にシャットダウンできます。

仕組みは、command1新しいcommand2サブシェルインスタンスの背景とそのインスタンスの前景で実行され、サブシェルはキー押下から終了信号をcommand3最初に受信することです。Ctrl-cこれは、誰がどのプロセスを所有し、いつデーモンが終了するかという点でbashスクリプトを実行するのと非常に似ています。

答え4

を使用できますpipe。これにより、パイプの両端で同時にコマンドが開始されます。また、を使用してすべてのコマンドを停止できる必要がありますCTRL-C

1st command | 2nd command | 3rd command

コマンドを順番に実行するには、@serenesatのメソッドを使用できます。

関連情報