我想在自己的进程组中启动一个进程(或者,一旦启动就更改其组)并且:
Ctrl
+ C
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
的代码本身。
答案 0 :(得分:3)
您是什么意思“在自己的流程组中启动流程”? 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
。
答案 1 :(得分:1)
编辑:如果你想要做的是使用setsid但是找到最终过程的会话ID和/或pid:
如果通过setsid命令启动进程,它将不会附加到您的终端,因此它当然不会响应ctrl-c。
你可以通过点击
的输出找到它ps x -O sid
或更像
的限制ps x -o %c,%p,sid
或者通过proc / [pid] / stat对所有条目进行简单的拖拽,并查看会话ID和其他感兴趣的内容(有关详细信息,请参阅man proc)
setsid的手册页没有给出任何标志来直接生成输出,但是您可以通过修改标准轻松地创建自己的版本来打印出所需的信息。
例如,从
的其中一个结果中获取setsid.c的副本http://www.google.com/codesearch?as_q=setsid&as_package=util-linux
注释掉nls include,locale stuff和_(“”)错误宏,它会导致问题,然后在execvp行之前添加它:
printf("process will be pid %d sid %d\n", getpid(), getsid(0));
答案 2 :(得分:0)
以下是关于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}
}
再次感谢!