web-dev-qa-db-ja.com

子孫を処理する

プロセスコンテナーを構築しようとしています。コンテナは他のプログラムをトリガーします。たとえば、「&」を使用して実行中のバックグラウンドタスクを起動するbashスクリプト。

私が求めている重要な機能はこれです。コンテナを強制終了すると、その下に生成されたすべてのものが強制終了されます。直接の子供だけでなく、その子孫も。

私がこのプロジェクトを始めたとき、あなたがプロセスを殺したとき、その子も自動的に殺されたと私は誤って信じていました。私は同じ間違った考えを持っていた人々からアドバイスを求めてきました。シグナルをキャッチして子供たちに殺しを渡すことは可能ですが、それは私がここで探しているものではありません。

Xtermを閉じると、その中で実行されていたものはすべて、Nohupでなかった場合に強制終了されるため、私は達成可能でありたいと思っています。これには、孤立したプロセスが含まれます。それを再現したいと思っています。

私が探しているのはUNIXセッションに関係しているという考えがあります。

プロセスのすべての子孫を特定するための信頼できる方法があった場合、任意のシグナルも送信できると便利です。例えばSIGUSR1。

23
Craig Turner

プロセスにシグナルを送信すると、そのプロセスは強制終了されます。プロセスを強制終了すると他のプロセスも強制終了するという噂はどのようにして始まったのでしょうか、特に直観に反しているようです。

ただし、複数のプロセスを強制終了する方法はいくつかあります。ただし、1つのプロセスにシグナルを送信することはありません。 プロセスグループ 全体を強制終了するには、信号を-1234に送信します。1234は、プロセスグループリーダーのPIDであるPGID(プロセスグループID)です。 pipeline を実行すると、パイプライン全体がプロセスグループとして開始されます(アプリケーションは setpgid または setpgrp )。

バックグラウンドでプロセスを開始するとき(foo &)、それらは独自のプロセスグループに属しています。プロセスグループは、ターミナルへのアクセスを管理するために使用されます。通常、フォアグラウンドプロセスグループのみがターミナルにアクセスできます。バックグラウンドジョブは同じ session のままですが、セッション全体を強制終了したり、セッション内のプロセスグループやプロセスを列挙したりする機能がないため、あまり役に立ちません。

端末を閉じると、カーネルは信号 SIGHUP制御端末 として持つすべてのプロセスに送信します。これらのプロセス セッションを形成する ですが、すべてのセッションに制御端末があるわけではありません。したがって、プロジェクトの場合、1つの可能性は scriptscreen などによって作成された独自のターミナルですべてのプロセスを開始することです。ターミナルエミュレータープロセスを強制終了して、含まれているプロセスを強制終了します(彼らが setsid で脱退していないと仮定します)。

他に何もしない独自のユーザーとしてプロセスを実行することで、さらに分離を提供できます。次に、すべてのプロセスを強制終了するのは簡単です。そのユーザーとしてkillシステムコール または tility )を実行し、PID引数として-1を使用してkill、「そのユーザーのすべてのプロセス」を意味します。

さらに分離を提供できますが、実際の container で含まれているプロセスを実行することにより、かなり多くの設定を使用できます。

親スクリプト内でkillシグナルをトラップし、すべての子を殺します。例えば、

#!/bin/bash
# kill the parent and children together
trap "kill 0" EXIT
# create all the children
for n in $(seq 1 100)
do
    ( echo "begin $n"; sleep 60; echo "end $n" ) &
done
# wait for the children to complete
wait
4

プロセスのすべての子孫を識別する信頼できる方法は、コマンド_pstree <pid>_を使用することです。ここで、pidは親プロセスIDです。

pstreehere のmanページを読んでください。

プロセスグループのすべてのメンバーに通知するには:killpg(<pgrp>, <sig>);
ここで、pgrpはプロセスグループ番号、sigはシグナルです。

指定したプロセスグループの子を待機するには:waitpid(-<pgrp>, &status, ...);

代わりに、新しいbashシェルでプロセスコンテナーを実行します。コマンドbashを使用して新しいbashシェルを作成し、プロセスを実行します。すべてのプロセスを終了する場合は、exitコマンドを使用してシェルを終了します。

4
Chris Ting

使用する

unshare -fp --kill-child -- yourprogram

unshareを強制終了すると、すべての子プロセス(yourprogramが生成された可能性がある)が強制終了されます。

これは現在、util-linux 2.32; このアップストリームを実装しました 。いずれかのユーザー名前空間が必要です(カーネル構成オプションCONFIG_USER_NS=y)またはroot権限。 here も参照してください。

1
nh2

rkill コマンド pslist パッケージは、指定されたプロセス(およびデフォルトでSIGTERM)を指定されたプロセスとそのすべての子孫に送信します。

rkill [-SIG] pid/name...
0
Onlyjob

シェルのすべての子孫を殺すための別のオプション:jobs -p | xargs -n 1 pkill -P

0
Doug Fawley