親プロセスが終了したら、すべての子プロセスを終了して初期化に切り替えるには?

親プロセスが終了したら、すべての子プロセスを終了して初期化に切り替えるには?

次の問題があります。多くの子プロセスを作成した後、大きな親プロセスが(誤って!)終了すると、すべての子プロセスがinit

どうすればこれらすべての子プロセスを安全に終了できますか?

私は方法があると思いました。このコマンドを使用して、親プロセスについて学びます。

ps -o ppid= <number of some child process>

完了すると使用できますこの回答すべての子プロセスを終了します。

ここでの問題は、すべてのサブプロセスが切り替えられ、initこのソリューションが機能していないことです。

htopを手動で終了する以外に他の方法はありますか?

よろしくお願いします!

答え1

  1. 短期ソリューション:  大規模な親プロセスが同時にすべての子プロセスを生成する場合は、psSTIME(プロセス開始時刻)に基づいて出力をソートします。これは、プロセス名とともにこの呼び出しで孤児を識別するのに役立ちます。
  2. 長期的な修正:  起動するすべてのプロセスのPIDログを保持するように親プロセスプログラムを変更します。その後、それをキルリストとして使用できます。

答え2

次の方法を使用して、合理的な最終候補リストを開発できます。

ps -ef | awk '$1 == "myUser" && $3 == 1'

おそらく、これはセッションの開始に使用されていないSTIME、?で使用されていないTTY、/usr/lib、/usr/bin、/libで始まらないCMDなどの他のフィールドをフィルタリングすることで改善される可能性があります。最終チェックのためにリストをファイルに入れてからawk | xargs | killを使用して列2を出力します。

答え3

移植可能ではありませんが、Linuxではinitプロセスの親エントリを再割り当てすることはできませんPR_SET_CHILD_SUBREAPERprctl(2)

PR_SET_CHILD_SUBREAPER(Linux 3.4以降)

      もしアルギニン20以外の場合は、呼び出しプロセスの「サブサブリッパー」プロパティを設定します。アルギニン20 の場合、プロパティは設定されません。プロセスが子収穫機としてマークされている場合、そのプロセスが生成するすべての子プロセスとその子プロセスは子収穫機を持つとマークされます。実際、サブハーベスターの機能は次のとおりです。初期化(1)子プロセスの場合。 …

しかし、サブリッパーも(偶然)死ぬことができます。別のオプション(Linuxでも)は、PID名前空間またはコンテナです。より一般的な解決策は、親プロセスが追い出されるか死ぬ可能性が低いように、できるだけ単純かつ強力に親プロセスを作成することです。

さらに複雑なのは、子プロセスを親プロセスにリンクすることです。ただし、子プロセスが別のタスクを実行した場合、または子プロセスが非同期I / Oを使用して問題を複雑にすることができない場合、子プロセスはパイプをチェックする必要があるため、接続できません。 EOFの場合は、親プロセスが終了するまで注意してください。

#include <err.h>
#include <errno.h>
#include <unistd.h>

int main(void)
{
    int fd[2];
    char ch;
    ssize_t ret;
    pipe(fd);

    switch (fork()) {
    case -1:
        err(1, "fork failed");
    case 0:
        close(fd[1]);
        warnx("child  %d start", getpid());
        /* this would really need to be done in an event loop so the
         * child can do other things meanwhile */
        ret = read(fd[0], &ch, 1);
        if (ret == 0)
            errx(1, "EOF from parent (child %d)", getpid());
        break;
    default:
        /* and another child process... */
        switch (fork()) {
        case -1:
            err(1, "fork failed");
        case 0:
            close(fd[1]);
            warnx("child  %d start", getpid());
            ret = read(fd[0], &ch, 1);
            if (ret == 0)
                errx(1, "EOF from parent (child %d)", getpid());
            break;
        default:
            sleep(9);
        }
    }
    return 0;
}

関連情報