プロセスが孤立プロセスを残すかどうかをテストします。

プロセスが孤立プロセスを残すかどうかをテストします。

私はそれらを待つ必要はありません。ただ、はいまたはいいえが必要です。

私はスプリットシャットダウンを引き起こすことがわかっているプログラムに従います(子供もスプリットシャットダウンを受ける可能性があります)。正しく実行されたら、すべての子を処理し、完了したら終了する必要があります。これが真であることを確認するためにテストを作成する必要があります。分離されたプロセスはinitプロセスに割り当てられているため、pstreeには表示されなくなります。

SIGKILLを送信できるようにPIDリストを取得できればボーナスポイントになります。理想的には、POSIX-yエントリーは* BSDで機能します。

答え1

これを見つける1つの方法は、を使用してps -ef親IDが "1"の行を見つけることです。たとえば、次のようになります。

#!/bin/sh
orphans="$(ps -ef | awk '$3 == 1{ print $2; }')"
echo "Processes which might be orphans: $orphans"

しかし、たくさんプロセスの親プロセスは「1」です。興味のある項目を決定する最善の方法は、プログラムによって生成されたサブプロセスを覚えておくことです。

あなたが知っているならログイン名(そして/またはユーザーID)これらのプロセスを作成すると、いくつかの可能性が排除されます。最初の列がps表示されることがあります(システムの種類によって異なります)。ログイン名または該当ユーザーIDPOSIXこれにはいくつかの助けがありますが、さまざまなシステムを簡単に見つけることができ、文書には次のことが反映されています。

  • たとえば、FreeBSD 10は表示されません。ログイン名オプション-f。 just を使用すると、親ps -efプロセスのプロセス ID を表示せずに、最初の列にプロセス ID を表示します。-l(代わりに)表示するにはオプションが必要です。ユーザーID
  • OSXはどちらの場合もユーザーID(ps -efまたは)を提供しますps -efl
  • この-lオプションがある場合、Solaris 10 は最初の列と 2 番目の列にプロセスフラグを表示します。これはPOSIXで言及されていますが、コンテンツフラグ数は指定されません(内容が異なるため)。Unixプラットフォーム)。
  • Linux は POSIX に従ってログイン名とプロセスフラグを提供します。

ご覧のとおり、使用可能なシステムの一部のサブセットでは、最初の3つの列はps -efl「同じ」結果を提供します。より一般的なコンテンツの場合は、ヘッダー(最初の行)を見て、プロセス所有者に対応する情報を含む列を確認する必要があります(ログイン名またはユーザーID)とプロセスIDとそれ親プロセスのプロセスID。

特定のシステムについて(利用可能なオプションを知ってps一致することを確認)ログイン名またはユーザーIDawk)、一致するために使用することができますそれフィールドにも同じです。

#!/bin/sh
orphans="$(ps -ef | awk -v user=$LOGNAME '($1 == user && $3 == 1){ print $2; }')"
echo "Processes which might be orphans: $orphans"

$LOGNAMEここでは、POSIXのこの用語の使用を説明するためにを使用します。ログイン名これは誤解を招く可能性があります(原則として、プロセスはを通じて行うことができますが、sudoPOSIXで用語を使用することは「ログイン」を介して行われることを意味するためです)。

追加資料:

答え2

プロセスが終了すると、その子プロセスのPPIDは1(initによって採用)に設定されますが、PGID(プロセスグループ識別子)とSID(セッション識別子)は変更されません。

このプロセスの子は、デーモンになることを意図していない限り、プロセスグループを変更することはできません。そうでないと仮定すると、独自のプロセスグループでテストするプロセスを開始します。分岐後にsetpgid(getpid(), getpid())テスト中のプログラム実行を呼び出す前に、テストフレームワークで呼び出されます。 PGIDを使用して実行中のプロセスがあるかどうかをテストするために(負のパラメータと信号値0を使用して)execve呼び出されます。それらを殺すには、シグナル引数として渡します。kill(-test_program_pid, 0)killpidtest_program_pidSIGKILL

test_program_pid = fork();
if (test_program_pid) {
    waitpid(test_program_pid, &status, 0);
    if (kill(-test_program_pid, 0)) {
        record_failue("some child processes were not terminated properly");
    }
    kill(-test_program_pid, SIGKILL);
} else {
    setpgid(getpid(), getpid());
    execve("/program/to/test", …);
}

別のアプローチは、一時ファイルを作成して他の場所で開くのではなく、テスト中のプログラムで開くことです。プログラムがを呼び出す場合は、開いているファイル記述子にフラグ(または呼び出し)がexecveないことを確認してください。このメソッドは、プログラムが明示的に使用されていないファイル記述子を閉じないと仮定します。その後、実行してファイルが開いているプロセスを一覧表示して終了できます。このアプローチのバリエーションは、ファイル記述子を使用しないプログラムを閉じるためにも使用できますが、プログラムが現在のディレクトリを変更しないと仮定します。つまり、一時ディレクトリを作成し、そのディレクトリに変更してプログラムを実行します。O_CLOEXECfcntl(fd, FD_CLOEXEC, 0)fuser /temp/filefuser -k /temp/file

関連情報