如何在自己的进程组中启动一个进程?

发布于 2024-11-03 16:47:27 字数 766 浏览 0 评论 0原文

我想在自己的进程组中启动一个进程(或者,启动后更改其组)并且:

  • 让组中的进程响应 Ctrl + C从终端
  • 获取进程组的 id,以便我可以通过 kill 命令终止组中的所有进程。

注意:我尝试了 setsid prog [args] 但进程不响应终端的 Ctrl+C,也无法获取新的进程组 ID。

我还尝试通过 Perl 的 setpgrp($pid, $pid)POSIX::setpgid($pid, $pid) 更改进程组,但无济于事。

编辑:更大的问题:

我有一个进程(单线程;让我们称之为“多产”进程P),它同步启动许多子进程(一个接一个;当前一个子进程终止时,它会启动一个新的子进程)。从终端,我希望能够杀死 P 及其下面的进程树。为此,我可以简单地安排终止 P 组中的进程。但是,默认行为是 P 位于其父进程的组中。这意味着如果我杀死 P 组中的所有进程,P 的父进程将被杀死,除非我有 P 及其树属于他们自己的群体。

我的目的是杀死 P 及其下面的树,但不是 P 的父树。另外,我无法修改 P 的代码本身。

I would like to start a process in its own process group (or, alternatively, change its group once started) and:

  • have the processes in the group respond to Ctrl + C from the terminal
  • get the id of the process group so that I can terminate all the processes in the group via the kill command.

Note: I tried setsid prog [args] but the processes do not respond to Ctrl+C from the terminal nor I could get the new process group id.

I also tried to change the process group via Perl's setpgrp($pid, $pid) and POSIX::setpgid($pid, $pid), to no avail.

Edit: The larger problem:

I have a process (single-threaded; let's call it the "prolific" process P) that starts many child processes synchronously (one after another; it starts a new one when the previous child process terminates). From the terminal, I want to be able to kill P and the tree of processes below it. To do that, I could simply arrange to kill the processes in P's group. However, the default behavior is that P is in the group of its parent process. That means that P's parent will be killed if I kill all the processes in P's group, unless I have P and its tree be in their own group.

My intention is to kill P and the tree below it, but not P's parent. Also, I cannot modify P's code itself.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梅窗月明清似水 2024-11-10 16:47:54

以下是按照上述 ninjalj 建议的 Perl 代码中的答案:

prolific_wrapper.pl

my $pid = fork();
if (not defined $pid) {

    die 'resources not available';

} elsif ($pid == 0) {

    # CHILD
    setpgrp;
    exit system(prolific => @ARGV);

} else {

    # PARENT
    my $was_killed = 0;
    local $SIG{INT} = sub {
        say 'kill prolific and its tree ...';
        kill KILL => -$pid;
        $was_killed = 1;
    };
    wait;
    my $child_status = $?;
    $SIG{INT} = 'DEFAULT';
    if ($was_killed) {kill INT => $}
    else {exit $child_status}

}

再次非常感谢!

Here is the answer in Perl code following ninjalj's suggestions above:

prolific_wrapper.pl

my $pid = fork();
if (not defined $pid) {

    die 'resources not available';

} elsif ($pid == 0) {

    # CHILD
    setpgrp;
    exit system(prolific => @ARGV);

} else {

    # PARENT
    my $was_killed = 0;
    local $SIG{INT} = sub {
        say 'kill prolific and its tree ...';
        kill KILL => -$pid;
        $was_killed = 1;
    };
    wait;
    my $child_status = $?;
    $SIG{INT} = 'DEFAULT';
    if ($was_killed) {kill INT => $}
    else {exit $child_status}

}

Many thanks again!

梦醒时光 2024-11-10 16:47:53

“在自己的进程组中启动进程”是什么意思? shell 在自己的进程组中启动进程,这就是它进行作业控制的方式(通过为前台进程提供一个进程组,并为在后台启动的每个管道提供多个进程组)。

要查看 shell 为每个管道启动一个新的进程组,您可以这样做:

ps fax -o pid,pgid,cmd | less

这将显示类似以下内容:

11816 11816  |   \_ /bin/bash
4759   4759  |       \_ ps fax -o pid,pgid,cmd
4760   4759  |       \_ less

请注意,shell 已为管道创建了一个新的进程组,并且管道中的每个进程共享该进程组。

编辑:

我想我知道你在说什么。您正在从 Perl 调用system。显然,sh -c 不会创建新的进程组,因为它是一个没有作业控制的 shell。

我要做的就是fork,然后在子进程上:

setpgrp;
system("ps fax -o pid,pgid,cmd");

然后在父进程上wait

What do you mean "start a process in its own process group"? The shell launches processes in their own process groups, that's how it does job control (by having a process group for processes in the foreground, and several process groups for every pipeline launched on the background).

To see that the shell launches a new process group for every pipeline, you can do this:

ps fax -o pid,pgid,cmd | less

which will show something like:

11816 11816  |   \_ /bin/bash
4759   4759  |       \_ ps fax -o pid,pgid,cmd
4760   4759  |       \_ less

Note that the shell has created a new process group for the pipeline, and every process in the pipeline shares the process group.

Edit:

I think I know what you are getting at. You are calling system from Perl. Apparently, sh -c doesn't create new process groups, since it's a shell without job control.

What I would do would be to fork, then on the child:

setpgrp;
system("ps fax -o pid,pgid,cmd");

and wait on the parent.

剑心龙吟 2024-11-10 16:47:53

编辑:如果您想做的是使用setsid,但找到结果进程的会话id和/或pid:

如果您通过setsid命令启动进程,它不会附加到您的终端,所以它当然不会' t 响应 ctrl-c。

你可以通过 grep 的输出

ps x -O sid 

或者更有限的东西

ps x -o %c,%p,sid

来找到它,或者简单地通过 proc/[pid]/stat 查找所有条目并查看会话 id 和其他感兴趣的内容(有关详细信息,请参阅 man proc

) setid 的页面没有给出任何直接生成输出的标志,但是您可以通过修改标准轻松制作自己的版本来打印所需的信息。

的结果之一获取 setsid.c 的副本

例如,从http ://www.google.com/codesearch?as_q=setsid&as_package=util-linux

注释掉会导致问题的 nls include、区域设置内容和 _("") 错误宏,然后添加就在 execvp 行之前:

    printf("process will be pid %d sid %d\n", getpid(), getsid(0));

EDIT: If what you wanted to do was use setsid but find the session id and/or pid of the resulting process:

If you launch a process through the setsid command it won't be attached to your terminal, so of course it won't respond to ctrl-c.

You could find it by grepping through the output of

ps x -O sid 

or something more limited like

ps x -o %c,%p,sid

Or simple trolling through proc/[pid]/stat for all entries and looking at the session id and whatever else is of interest (see man proc for details)

The man page for setsid is not giving any flags to directly generate output, but you could trivially make your own version that prints out the desired information, by modifying the standard.

For example, grab a copy of setsid.c from one of the results for

http://www.google.com/codesearch?as_q=setsid&as_package=util-linux

Comment out the nls include, the locale stuff and the _("") error macro which will cause problems and then add this right before the execvp line:

    printf("process will be pid %d sid %d\n", getpid(), getsid(0));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文