ipc perl杀死后台工作需要杀死两个pid

时间:2013-10-22 08:47:20

标签: perl ipc kill-process

此问题与之前的问题有关: perl run background job and force job to finish?

我以为我有一个脚本可以通过kill 15, $logger_pid成功杀死我的后台工作,但事实证明该命令会创建两个工作。请参阅以下详细信息:

#!/usr/bin/perl
use strict;
# Do a background $USER top every minute
my $cmd = "top -b -d 1 -n 300 -u $ENV{USER} >> logfile";
$SIG{CHLD}="IGNORE"; my $logger_pid;
unless ($logger_pid=fork) { exec($cmd); }

# This actually creates two jobs with consecutive PIDs
# $USER  5609  0.0  0.0  63820  1072 pts/9    S    09:42   0:00 sh -c top -b -d 1 -n 300 -u $USER >> logfile
# $USER  5610  0.6  0.0  10860  1216 pts/9    S    09:42   0:00 top -b -d 1 -n 300 -u $USER

# Do something for a while
foreach my $count (1..5) { print "$count\n"; sleep 1; }
# I thought this first kill command was enough
kill 15, $logger_pid;
# This line is needed to kill the child job
kill 15, ($logger_pid+1);

1;

有人可以告诉我为什么我需要第二个kill 15, ($logger-pid+1)来实际杀死后台工作吗?有没有办法用一个kill语句来做到这一点?

1 个答案:

答案 0 :(得分:2)

使用sh -c ...执行带有外部元字符的外部命令的系统(在您的情况下,>>用于输出重定向,以及命令字符串中的任何空格)记录在{{ 1}}和exec。为避免使用system并创建单个流程,您可以使用sh -c形式的LIST

exec

输出重定向使这有点棘手,但您可以通过在my @cmd = ('top','-b','-d','1','-n','300','-u',$ENV{USER}); exec(@cmd); 之后和STDOUT之前关闭并重新打开fork来完成此操作:

exec

进行输出重定向时,重要的是正确设置文件描述符1,不一定是my @cmd = ... close STDOUT; open STDOUT, '>>', 'logfile'; exec @cmd; 。例如,这将无法像您希望的那样进行输出重定向。

STDOUT

使用流程组的替代解决方案: @Chris在评论中建议您向my @cmd = ...; close STDOUT; # close file descriptor 1 open FOO, '>/tmp/asdf'; # probably uses file descriptor 1 open STDOUT, '>>', 'logfile'; # probably uses file descriptor != 1 exec(@cmd); # probably writes output to FOO\/tmp/asdf 函数发送负值,以便终止整个流程组。通常,使用kill创建的流程与其父流程具有相同的流程组,但如果您将子流程设置为使用新流程组,则此工作将起作用:

fork