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
フォアグラウンドで実行されるため、+を使用して殺すことができます。 command2
command3
CtrlC
Ctrl+を使用して最後のプロセスを終了すると、コマンドの実行は+を押して送信される割り込み信号の受信に関連付けられ、Cコマンドが実行されます。kill %1; kill %2
CtrlC
最初と2番目のバックグラウンドプロセス(あなたcommand1
とcommand2
)をそれぞれ終了します。コマンドを使用した後にトラップを削除することを忘れないでください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のメソッドを使用できます。