修正する

修正する

申込書を作成中です。さまざまな外部プロセスを生成する機能があります。アプリケーションが閉じられたときに生成されたすべてのプロセスを終了したいと思います。

簡単だと思いますか?私のPIDを見つけて、プロセスツリーを繰り返し探索してボトムアップに見えるものをすべて終了します。

しかし、これはそうではありません働く。 1つの特別なケースでは、をビルドしましたが、ちょうどfooビルドfoobarてすぐにシャットダウンしてbar実行状態のままにしました。ある何の記録もない実際、これはbarアプリケーションプロセスツリーの一部でした。したがって、アプリケーションは終了する必要があるかどうかを知る方法はありませんbar

私はこれを試した地球上の最初の人になることができないと確信しています。それでは、標準的なソリューションは何ですか?私は、プロセスが生成するすべてのプロセスが無条件に同じタグを継承するようにプロセスに「タグ」を割り当てる方法を探していると思います。

(これまで私が考えることができる最善は、他のユーザーとしてアプリケーションを実行することです。そうすることで、そのユーザーに属するすべてのプロセスを無差別にシャットダウンすることができますが、これによりあらゆる種類のアクセス権の問題が発生します。 ..)

ベストアンサー1

修正する

これは明らかに質問を注意深く読む必要がある質問の1つです(ただし、この質問に対するほとんどの答えはそうですが)。質問のポイントを明確に見逃したにもかかわらず、良い情報を提供するので、元の答えを維持しています。

SIDの使用

ここで(少なくともLinuxの場合)最も多様で信頼性の高いアプローチは、PPIDやPGIDの代わりにSID(セッションID)を使用することです。これは子プロセスによって変更される可能性がなく、シェルスクリプトの場合は、このsetsidコマンドを使用して新しいセッションを開始できます。setuidシステムコールはシェルの外部で使用できます。

セッションリーダーであるシェルの場合、次のようにしてセッション内の他のすべてのプロセスを終了できます(シェルはそれ自体で終了しません)。

kill $(ps -s $$ -o pid=)

注:パラメータの末尾の等号は列ヘッダーをpid=削除します。PID

それ以外の場合は、システムコールを使用してgetsid各プロセスを呼び出すことが唯一の方法のようです。

PID名前空間の使用

最も信頼性の高い方法ですが、Linuxでのみ機能し、root権限が必要であるという欠点があります。さらに、シェルツール(使用されている場合)は非常に新しく、まだ広く使用されていません。

PID名前空間の詳細については、次の質問を参照してください。「nsenter:」を使用してサブプロセスを刑務所に置く安定した方法。ここでの基本的なアプローチは、システムコールCLONE_NEWPIDと共に(またはコマンドを介して)フラグを使用して新しいPID名前空間を作成することです。cloneunshare

PIDネームスペースのプロセスが孤立した場合(つまり、親プロセスが完了したら)、代わりに最上位PIDネームスペースプロセスの親になりますinit。これは、プロセスをナビゲートして常に最上位プロセスを識別できることを意味します。 tree プロセスのすべての子項目です。シェルスクリプトの場合、以下のPPIDメソッドはすべての子を確実に終了します。

PID名前空間に関する追加情報:

元の答え

サブプロセスの終了

pkill(利用可能な場合)シェルスクリプトでこれを行う簡単な方法は次のとおりです。

pkill -P $$

これにより、現在指定されたプロセスのすべての子プロセスが終了します($$現在のシェルのPIDに展開されます)。

すべてのサブプロセスを終了

あるいは、現在のシェルプロセスのすべてのサブプロセスと直系のサブプロセスを終了することもできます。この場合、次の再帰シェル関数を使用してすべての子PIDを一覧表示し、それを引数として渡して終了できます。

list_descendants ()
{
  local children=$(ps -o pid= --ppid "$1")

  for pid in $children
  do
    list_descendants "$pid"
  done

  echo "$children"
}

kill $(list_descendants $$)

ダブルフォーク

注目すべき1つのことは、二重技術が上記の方法が期待どおりに機能しないことですfork()。これは通常、プロセスをデーモン化するときに使用されます。名前が示すように、開始されるプロセスは元のプロセスの第2四半期で実行されます。プロセスが開始されると、最初の分岐が終了します。これはプロセスが孤児になることを意味します。

initこの場合、そのプロセスを開始した元のプロセスではなく、プロセスの子プロセスになります。どのプロセスが元の親プロセスであるかを識別する信頼できる方法がないため、この場合、他の識別方法(PIDファイルなど)がないと、そのプロセスを終了できません。ただし、この手法を使用した場合は、正当な理由なくプロセスを終了しようとしないでください。

追加資料:

おすすめ記事