系统相关
首页 > 系统相关> > linux-如何避免进程?

linux-如何避免进程?

作者:互联网

我将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;
}

解决方法:

当您创建一个进程时,它会一直停留到其父进程获得它为止. (如果其父级先退出,它将自动获得.)进程可以使用waitwaitpid对其子级进行收割.它还可以通过使用本地$SIG {CHLD} =’IGNORE’来自动使其子级收割.在创建孩子之前.

请注意,Parallel :: ForkManager不是启动单个孩子的正确工具.生成单个工人不是目的.

use String::ShellQuote qw( shell_quote );

sub mbuffer {
    my ($id, $zfsPath) = @_;

    my $mbuffer_cmd = shell_quote($mbuffer, '-I', $::c{port});
    my $zfs_cmd     = shell_quote($zfs, 'receive', $zfsPath);
    my $remote_cmd  = "$mbuffer_cmd | $zfs_cmd";
    my $local_cmd   = shell_quote($ssh, $::c{slaves}{$id}, $remote_cmd);

    # open3 will close this handle.
    # open3 doesn't deal well with lexical handles.
    open(local *CHILD_STDIN, '<', '/dev/null') or die $!;    

    return open3('<&CHILD_STDIN', '>&STDOUT', '>&STDERR', $local_cmd);
}

IPC :: Open3的级别很低,但是它与您现有的代码最接近.启动过程的更好方法包括IPC :: Run3和IPC :: Run.

标签:ssh,zombie-process,linux,perl,fork
来源: https://codeday.me/bug/20191025/1931292.html