3つの端末エミュレータウィンドウを起動するスクリプトがあります。
#!/bin/sh
terminator --role='terminator-left' 2>/dev/null &
sleep 0.1
terminator --role='terminator-center' 2>/dev/null &
sleep 0.1
terminator --role='terminator-right' 2>/dev/null &
(私はopenbox設定ファイルで定義されている他のモニタにウィンドウを自動的に配置できるように--roleオプションを使用します)
私はこのスクリプトを別の仮想デスクトップで何度も起動しました。
ある種の「プロセスグループ」でこの3つの端末を起動し、そのうちの1つが終了したときに残りのすべてのプロセスを終了できるようにするにはどうすればよいですか。
重要:スクリプトの他のインスタンスから起動できるすべての端末を終了したくありません。パターンに一致するプロセスを終了するためにpkillまたはpgrepを使用することはできません。
つまり、仮想デスクトップ1と仮想デスクトップ2でスクリプトを実行しているとします。
これで、2つの異なる仮想デスクトップに3つのターミナルウィンドウがあります。
仮想デスクトップ1でターミナルをシャットダウンするときは、仮想デスクトップ2で実行されている他の3つの別々のウィンドウインスタンスに影響を与えず、残りの2つのウィンドウが自動的にシャットダウンされます。
私が説明することは可能ですか?
どうすればいいですか?
答え1
婦人声明:
私はopenboxで私の提案をテストする機会がありませんでした。 kde-plasmaでのみ確認しました。
私の解決策はwait
シェルの内部コマンドに依存しています。POSIX プログラママニュアルに記載されているように。特定の実装では、-nオプションを使用してスクリプトをより簡単にすることができます。
#!/bin/sh
ownkill()
{
trap - CHLD
pkill --signal 15 -P $$
}
terminator --role='terminator-left' 2>/dev/null &
sleep 0.1
terminator --role='terminator-center' 2>/dev/null &
sleep 0.1
terminator --role='terminator-right' 2>/dev/null &
trap ownkill CHLD
wait
このスクリプトは次のアイデアに基づいています。
- スタート3ターミネーター必要に応じて処理し、
- 完了するまでお待ちください。
- 残りのプロセスと同じ方法で、上記のプロセスの1つを終了するSIGCHLD信号を処理します。
注1(リセットハンドラ):aviroがコメントで正しく観察したように、シグナルハンドラはSIGCHLD処理をデフォルト値にリセットする必要があります。残りのプロセスを終了すると、他の(最大2つ)SIGCHLDがトリガーされるためです。
そうしないと、シェルはある種の再帰状況(ハンドラは自分で生成した信号を処理する必要がある)に陥り、シェルの実装に応じてある程度適切に管理されます。 (無害な警告から一部最大再帰深度を超えました。またはそれに相当するもの。間違い。 )
注2(待機するまでSIGCHLD基本処理を保持):Martin Vegterがコメントで正しく観察したように、このtrap ownkill CHLD
コマンドはスタンバイコマンドの直前に配置する必要があります。
これをスクリプトの最初のコマンドで作成すると(以前のバージョンでとんでもなく提案したように)、最初のプロセスが終了するとすぐに専用sleep
ハンドラが起動します。
答え2
wait -n
Bashを使用すると、すべてのプロセスIDを簡単に収集し、プロセスが終了した場合(bashの場合)、すべてのIDが適切な信号で終了するのを待つことができます。
#!/bin/bash
terminator --role='terminator-left' 2>/dev/null &
pid1=$!
sleep 0.1
terminator --role='terminator-center' 2>/dev/null &
pid2=$!
sleep 0.1
terminator --role='terminator-right' 2>/dev/null &
pid3=$!
wait -n
kill -hup $pid1 $pid2 $pid3 2>/dev/null
PIDの1つが期限切れになったため、kill
エラーメッセージを回避するためにstderrをnullにリダイレクトします。
答え3
起動、制御、停止が簡単なので、systemd一時デバイスを使用することができます。シェルスクリプトが次のように見なされ、すぐに完了しないようにコマンドを最後に追加したら、./myscript
次のように起動できます。wait -n
systemd-run --user --unit=mytest1 ./myscript
このコマンドはすぐにメッセージを返し、Running as unit: mytest1.service
通常のコマンドを使用して作成した一時セルでどのプロセスが実行されているかを確認できます。
systemctl status --user mytest1
1つのコマンドですべてのプロセスを停止できます。
systemctl stop --user mytest1
--unit=
同じスクリプトを複数回実行するには、毎回異なる名前を使用する必要があります。すべてで始まる場合は、すべてをtest
確認するか、を参照して停止できますtest*
。
バラより男性システムの実行--setenv=
、、、--working-directory=
など、便利なさまざまなオプションについて学びます
--collect
。--wait
コマンドの最後でスクリプトに引数を渡すこともできますsystemd-run
。