web-dev-qa-db-ja.com

xtermではなく子xtermで子プロセスを強制終了します

Linuxは初めてです。 pythonスクリプトが異なるファイルにあり、それぞれが目的の機能を実行しています。

foo1.py 
foo2.py 
foo3.py

これらの各スクリプトは、終了する前にクリーンアップを実行する必要があります。さらに、端末でそれぞれを実行して、出力を個別に相互作用して読み取るようにします。

さまざまなkillシグナル(SIGTERM、SIGINTなど)をキャッチするためのクリーンアップ関数をすでに実装しました。

ターミナルで各スクリプトを実行するために、以下のように、それぞれに1つのxtermターミナルを開くstartup.shを使用しています。

startup.sh

xterm -e python foo1.py & pid1=$! 
xterm -e python foo2.py &  pid2=$!
xterm -e python foo3.py &  pid3=$!

次に、私のロジックでは、スクリプトfoo3.pyが最も重要なので、スクリプトが終了したら、他の2つも閉じる必要があります。

wait $pid3
kill -15 $pid1
kill -15 $pid2

問題は、$pid1$pid2がxtermのpidであり、スクリプト(foo.py)自体のpidではないことです。したがって、xterm(kill -15 $pid)を強制終了すると、pythonスクリプトはクリーンアップルーチンを実行する機会がありません。

Xtermから子プロセス( https://unix.stackexchange.com/a/54994/35751 )に送信されたシグナルをキャッチしようとしましたが、pythonスクリプトすぐに終了します。

それで、xterm内で実行されているスクリプトからpidsを取得する方法はありますか?または、そのようなクリーンアップルーチンが実行されることを確認する別の方法はありますか?

3

pythonスクリプトもSIGHUPをキャッチし、クリーンな終了を行う必要があります。xtermが実行中の疑似端末を破棄すると、SIGHUPを取得します。とにかくSIGHUPを処理する必要があります。これは、xtermが明示的に強制終了される以外の原因(X11サーバー自体が終了するなど)により、実行されている端末が消える可能性があるためです。

マスターのないスレーブ端末に対して読み取りまたは書き込みを行おうとすると、スクリプトはEIOエラーも正しく処理する必要があります。

とにかく、あなたはただあなたのpythonスクリプトを殺すことができます

_pkill -P $pid1
_

( "親による殺害"; pkill/pgrepの-​​ manpage を参照)

すべてのシェルがfork/exec/waitから単純なexecへのスクリプトの最後のコマンドを最適化するわけではないので(例dash、debianの_/bin/sh_など)、複雑なものを実行する必要がある場合シェルコマンドは、xterm -e 'script=$(...); exec python "$script"'のように、明示的にexecを呼び出す方がよいでしょう。

注:

この質問に正確に答えるわけではありませんが、ターミナルエミュレータから開始されたプロセスを見つけるための信頼性は低いが効果的な方法は、環境にWINDOWIDが設定されているプロセスを検索することです。

_pids_by_env(){ grep -aslP "\b($1)\0" /proc/[0-9]*/environ | grep -oP '\d+'; }

pids_by_window(){ pids_by_env "WINDOWID=$(printf '%d' "$(xwininfo "$@" | awk '/id:/{print$4}')")"; }

$ ps $(pids_by_window)
[click!]
  PID TTY      STAT   TIME COMMAND
11244 pts/8    Ss     0:00 bash
11297 pts/8    S+     0:00 vu [censored].pdf
_
2
mosvy