一部のアプリケーションは完全に終了せず、プロセスはそのまま残ります。私が見つけた1つの例はFoxit Readerです。もちろん、バグを報告してアプリケーションを修正するのが最も理想的な状況ですが、これが不可能な場合もあります。たとえば、Foxit Readerの場合、開発者は完全な書き換え作業を進めているので、現在のバージョンを変更しないと述べました。
私はアプリケーションを終了したときに残りのプロセスが自動的に閉じるようにしたいと思います(もちろん、残りのプロセスをさらに作成せずに)。どうすればいいですか?
答え1
最も簡単な方法は、スクリプトを介してプログラムを起動し、プロセスグループtrap
全体kill
を設定することです。
#!/bin/bash
trap "kill -9 -- -$$" ERR EXIT
/path/to/gui-programm
どのように動作しますか?
Aはtrap
シェル組み込みコマンドです。スクリプトが 1 つ以上のシグナルを受信すると、特定のコマンドを実行します。この場合、EXITは正常なシャットダウン(つまり、GUIプログラムを閉じる)を示し、ERRはエラー(例えば、CTRL+Cまたは他の理由でFoxitが終了した)を示します。参照:man signal
とman bash
使用されるコマンドはSIGKILLが送信されるkill
場所です-9
。kill
PIDにマイナス記号を追加して単一のプロセスを終了できます。これはkill <pid>
プロセスグループ全体(つまり、プロセスとすべての子プロセスとフォーク)に影響します。--
これは、次のパラメータがフラグとして解釈されないようにするために必要です。つまり、kill -9 -- -$pid
プロセスグループは一定期間終了します。
$$
現在のシェルスクリプトのPID。 GUIプログラムはスクリプトの子プロセスであり、GUIプログラム自体の子プロセスもスクリプトにソースとして接続されているプロセスグループの一部です。
テストしたい場合は、複数の睡眠を使用することをお勧めします。
#!/bin/bash
#test script for kill via trap
trap "kill -9 -- -$$" ERR EXIT
for (( i=1 ; i<=100 ; i++ )) ; do
sleep 120
done
/path/to/gui-command
GUIコマンドを終了すると、すべてのスリープモードが消えます。トラップセクションをコメントアウトすると、そのまま残ります。
trap
子プロセスが失敗しても実行を保証するには継承が必要ですset -E
。
#!/bin/bash
set -E
trap "kill -9 -- -$$" ERR EXIT
/path/to/gui-programm
答え2
1つの方法は、アプリケーションを直接起動するのではなく、スクリプトからアプリケーションを起動することです。アプリケーションの実行中、その出力は一時ファイルにパイプされます。次に、fifoのパイプを介してファイルに対してtailを実行します。次のgrepはfifoに対して実行されます。一部のテキストが見つかると、tailプロセスが終了し、fifoが閉じられ、アプリケーションプロセスが強制終了され、一時ファイルが削除されます。
アプリケーションが終了したときに最後のテキスト出力になるようにテキストを選択する必要があります(コマンドラインからアプリケーションを起動すると、このテキストが表示されます)。たとえば、FoxitReaderを閉じると出力される最後のテキストは「CJS_Module :: ExitEnumJSPlugThread」です。
次のスクリプト例は、FoxitReaderと連携する方法を示しており、他のアプリケーションに簡単に適用できます。
#!/bin/bash
file=/tmp/foxit.txt
YOURPATH/foxitsoftware/foxitreader/FoxitReader "$@" &> $file &
foxitpid=$!
fifo=/tmp/tmpfifo.$$
mkfifo $fifo || exit 1
tail -f $file >$fifo &
tailpid=$!
grep -m 1 "CJS_Module::ExitEnumJSPlugThread" $fifo
kill $tailpid
rm $fifo
kill -9 $foxitpid
rm -f $file
exit 0
答え3
@mcaransの答えによれば、Foxit Readerのインストールディレクトリで起動スクリプトを微調整できます。
<INSTALLPATH>/foxitreader/FoxitReader.sh
このスクリプトを次のように変更します(<INSTALLPATH>確認を忘れないでください)。
#!/bin/bash
selfpath="<INSTALLPATH>/foxitreader"
file=/tmp/foxit.txt
"$selfpath/FoxitReader" "$@" &> $file &
foxitpid=$!
fifo=/tmp/tmpfifo.$$
mkfifo $fifo || exit 1
tail -f $file >$fifo &
tailpid=$!
grep -m 1 "~CJS_Module()" -m 1 "CJS_Module::ExitEnumJSPlugThread()" $fifo
kill $tailpid
rm $fifo
kill -9 $foxitpid
rm -f $file
exit 0
保存すると、すべての準備が完了します。 PDFファイルをダブルクリックして通常どおり閉じると、残りのプロセスはありません。