tmux Kill-window は子プロセスを終了しません。

tmux Kill-window は子プロセスを終了しません。

ウィンドウでプロセスを終了しctrlctmuxを終了すると、すべての子プロセスが終了します。ctrld

しかし、これを行うと:

ctrl+b次にshift+%

次に Y を選択してウィンドウを終了し、プロセスはアクティブのままです。ウィンドウが終了すると、プロセスも終了するかどうかを確認する方法を知っていますか?

ベストアンサー1

Ctrl+cとともにkill-window

通常、Ctrl+を使用するとcstty -a表示されるときintr = ^C)、SIGINTを次に送信します。フォアグラウンドプロセスグループのプロセス。 SIGINTを取得したすべてのプロセスが終了(終了)されると仮定しているように見えますが、通常はそうではありません。

Ctrl+に言及したので、dtmuxサーバーとシャットダウンしたいプロセスの間に対話型シェルがあるかもしれません。この場合、SIGINT はシェルではなくプロセスに転送されますが、シェルが SIGINT をインポートしても終了しません。 (必ずしもそうではありません。あなたの説明に適していると言っています。)

したがってCtrl、+プロセスが終了したら+を押してシェルを終了cできます。Ctrld

tmuxでウィンドウを終了すると、対応する疑似端末が閉じられ、制御端末がSIGHUPを受信したかのようにそれを使用して処理されます。これらのプロセスはSIGHUPをサブプロセスに送信できます(シェルの場合を参照)。この回答)。プロセスはこの信号を無視できます(参考資料を参照nohup)。シグナルを無視しても、もはや存在しない擬似端末を使用しようとすると、後で死ぬことも死ぬこともあります。

簡単に言うと:

  • SIGINT または SIGHUP を関連プロセスに送信します。
  • SIGINT または SIGHUP に対する反応の有無と方法は、プロセスによって異なります。

SIGINT 送信

プロセスは SIGINT を無視できます。Ctrl+が作業中のプロセスに対して目的の操作を実行している場合は、c各ウィンドウで+を押すのと同じように、ウィンドウを終了してSIGHUPを送信する前にSIGINTを送信するだけで十分ですCtrlc

次のコマンドは、現在のウィンドウペインにあるプロセス(tmuxサーバーの直系サブエントリ)を一覧表示し、対応するフォアグラウンドプロセスグループを取得し、各プロセスにSIGINTを送信します。

tmux list-panes -F "#{pane_pid}" | xargs ps -o tpgid= | xargs -I{} kill -s SIGINT -{}

問題は、このパイプもSIGINTを受信して​​早期に終了できることです。この問題を解決するには

  • 他の場所でコマンドを実行し、-t指定されたウィンドウを使用します。
  • あるいは、パイプの前景プロセスグループが除外されるようにいくつかのロジックを実装します。
  • または、バックグラウンドでパイプラインを実行します。

    tmux list-panes -F "#{pane_pid}" | xargs ps -o tpgid= | xargs -I{} kill -s SIGINT -{} &
    
  • または、コマンドがシグナルを無視するようにします。

    sh -c '
    trap "" SIGINT
    tmux list-panes -F "#{pane_pid}" | xargs ps -o tpgid= | xargs -I{} kill -s SIGINT -{}
    '
    

私はこのアプローチが競争条件に弱いと思いますpskillより良い(?)選択肢は、Ctrl+をc各ウィンドウに送信することです。

tmux list-panes -F "#{pane_id}" | xargs -I {} tmux send-keys -t {} C-c &

フック

このフックを使用すると、tmuxに編集したいウィンドウのすべてのウィンドウに+を送信させることができますCtrlckill-window

tmux set-hook before-kill-window 'run-shell "
   tmux list-panes -t \"#{window_id}\" -F \"##{pane_id}\" | xargs -I {} tmux send-keys -t {} C-c
"'

3つのレベルの参照があるため、これは悪いようですが、私のテストではまだ動作しているようです(まだ徹底的にテストしていませんが)。目的は##拡張を延期することです#{pane_id}。要点は、作業#{window_id}中に拡張が必要ですrun-shellが、生き残る必要があり、#{pane_id}出力を生成するときにのみ拡張する必要があることです。list-panes

フックはオーバーライドされますが、またははオーバーライドされkill-windowません。またkill-panekill-sessionkill-serverkill-windowいいえkill-pane何度も繰り返しただけなので、before-kill-pane ウィンドウを強制的に破壊するときにフックがすべてのケースをカバーするわけではありません。そしてrespawn-pane -kおよびrespawn-window -k命令。


十分でないとどうなりますか?

プロセスは SIGINT で終了しない場合があります。tmux list-panes -F "#{pane_pid}"開始点にSIGTERM(またはSIGKILL)を送信するPID(および/またはPGID)のリストを取得できます。この一般的なアプローチの主な問題は、プロセスを作成し、そのプロセスの祖先とttyとの接続を完全に切断できることです。

したがって、通常、特定のtmuxウィンドウで発生したすべてのプロセスを追跡することはできません。

おすすめ記事