【发布时间】:2018-01-17 09:58:54
【问题描述】:
我从主控主机到从属主机进行 ZFS 远程复制,我有一个在主控主机上运行的 Perl 脚本。
对于每个文件系统,它 ssh 到远程主机并以侦听模式启动 mbuffer,然后脚本继续,然后发送数据。成功时,mbuffer 应自行退出。
问题
在远程主机上通过 ssh 启动 mbuffer 并在脚本中继续运行非常困难。我最终做了你在下面看到的。
问题在于,在脚本退出之前,它会为每个文件系统留下一个 <defunct> 进程。
问题
可以避免<defunct> 进程吗?
sub mbuffer {
my ($id, $zfsPath) = @_;
my $m = join(' ', $mbuffer, '-I', $::c{port});
my $z = join(' ', $zfs, 'receive', , $zfsPath);
my $c = shellQuote($ssh, $::c{slaves}{$id}, join('|', $m, $z));
my $pm = Parallel::ForkManager->new(1);
my $pid = $pm->start;
if (!$pid) {
no warnings; # fixes "exec" not working
exec($c);
$pm->finish;
}
sleep 3; # wait for mbuffer to listen
return $pid;
}
【问题讨论】:
-
父进程必须始终在其子进程上调用
wait(或其变体之一),以便让内核知道可以清理终止的子进程。 This question 有一些答案可能会为您指明正确的方向。 -
最快的解决方法是设置
$SIG{CHLD}='IGNORE'。见perldoc -f fork -
失效进程或僵尸进程是在没有父进程调用
wait的情况下终止的进程。因此,内核保留终止子进程的条目,因此当父进程调用wait时,它会返回所需的信息。为了避免僵尸,父进程需要等待它的子进程。
标签: linux perl ssh fork zombie-process