ric*_*ard 6 perl children kill
这是我的代码,为了清楚起见,删除了错误处理和其他内容:
sub launch_and_monitor {
my ($script, $timeout) = @_;
sub REAPER {
while ((my $child = waitpid(-1, &WNOHANG)) > 0) {}
$SIG{CHLD} = \&REAPER;
}
$SIG{CHLD} = \&REAPER;
my $pid = fork;
if (defined $pid) {
if ($pid == 0) {
# in child
monitor($timeout);
}
else {
launch($script);
}
}
}
Run Code Online (Sandbox Code Playgroud)
launch子程序执行一个shell脚本,然后启动其他进程,如下所示:
sub launch($) {
my ($script) = @_;
my $pid = open(PIPE, "$script|");
# write pid to pidfile
if ($pid != 0) {
while(<PIPE>) {
# do stuff with output
}
close(PIPE) or die $!;
}
}
Run Code Online (Sandbox Code Playgroud)
monitor sub基本上只等待一段指定的时间,然后尝试终止shell脚本.
sub monitor($) {
my ($timeout) = @_;
sleep $timeout;
# check if script is still running and if so get pid from pidfile
if (...) {
my $pid = getpid(...);
kill 9, $pid;
}
}
Run Code Online (Sandbox Code Playgroud)
这会杀死脚本,但是它不会杀死任何子进程.怎么修?
Ken*_*ter 12
如果操作系统支持,则可以使用进程组执行此操作.您需要使脚本流程成为流程组负责人.它运行的子进程将从其父进程继承进程组.然后,您可以使用kill同时向组中的每个进程发送信号.
在launch()
,你将需要open
用一个分叉替换该线.然后在孩子中,你会setpgrp()
在执行命令之前调用.像下面这样的东西应该工作:
my $pid = open(PIPE, "-|");
if (0 == $pid) {
setpgrp(0, 0);
exec $script;
die "exec failed: $!\n";
}
else {
while(<PIPE>) {
# do stuff with output
}
close(PIPE) or die $!;
}
Run Code Online (Sandbox Code Playgroud)
稍后,为了终止脚本进程及其子进程,否定您发出的进程ID:
kill 9, -$pid;
Run Code Online (Sandbox Code Playgroud)