perl - 有时长时间运行的 ssh 命令会停止打印到标准输出

标签 perl ssh perlnetssh

我一直在使用 Perl::Net::SSH 在我的远程机器上自动运行一些脚本。然而,其中一些脚本需要很长时间才能完成(一两个小时),有时,我会停止从它们获取数据,而实际上并没有断开连接。

这是我使用的代码:

sub run_regression_tests {
    for(my $i = 0; $i < @servers; $i++){
        my $inner = $users[$i];
        foreach(@$inner){
            my $user = $_;
            my $server = $servers[$i];

            my $outFile;
            open($outFile, ">" . $outputDir . $user . "@" . $server . ".log.txt");
            print $outFile "Opening connection to $user at $server on " . localtime() . "\n\n";
            close($outFile);

            my $pid = $pm->start and next;

                print "Connecting to $user@" . "$server...\n";

                my $hasWentToDownloadYet = 0;
                my $ssh = Net::SSH::Perl->new($server, %sshParams);
                $ssh->login($user, $password);              

                $ssh->register_handler("stdout", sub {
                    my($channel, $buffer) = @_;             
                    my $outFile;
                    open($outFile, ">>", $outputDir . $user . "@" . $server . ".log.txt");                  
                    print $outFile $buffer->bytes;              
                    close($outFile);                

                    my @lines = split("\n", $buffer->bytes);
                    foreach(@lines){
                        if($_ =~ m/REGRESSION TEST IS COMPLETE/){
                            $ssh->_disconnect();

                            if(!$hasWentToDownloadYet){
                                $hasWentToDownloadYet = 1;
                                print "Caught exit signal.\n";
                                print("Regression tests for ${user}\@${server} finised.\n");
                                download_regression_results($user, $server);
                                $pm->finish;
                            }
                        }
                    }

                });
                $ssh->register_handler("stderr", sub {
                    my($channel, $buffer) = @_;             
                    my $outFile;
                    open($outFile, ">>", $outputDir . $user . "@" . $server . ".log.txt");

                    print $outFile $buffer->bytes;              

                    close($outFile);                
                });
                if($debug){
                    $ssh->cmd('tail -fn 40 /GDS/gds/gdstest/t-gds-master/bin/comp.reg');
                }else{
                    my ($stdout, $stderr, $exit) = $ssh->cmd('. ./.profile && cleanall && my.comp.reg');
                    if(!$exit){
                        print "SSH connection failed for ${user}\@${server} finised.\n";
                    }
                }
                #$ssh->cmd('. ./.profile');

                if(!$hasWentToDownloadYet){
                    $hasWentToDownloadYet = 1;
                    print("Regression tests for ${user}\@${server} finised.\n");
                    download_regression_results($user, $server);
                }

            $pm->finish;        
        }
    }
    sleep(1);
    print "\n\n\nAll tests started. Tests typically take 1 hour to complete.\n";
    print "If they take significantly less time, there could be an error.\n";
    print "\n\nNo output will be printed until all commands have executed and finished.\n";
    print "If you wish to watch the progress tail -f one of the logs this script produces.\n Example:\n\t" . 'tail -f ./gds1@tdgds10.log.txt' . "\n";
    $pm->wait_all_children;
    print "\n\nAll Tests are Finished. \n";
}

这是我的 %sshParams:

my %sshParams = (
    protocol => '2',
    port => '22',
    options => [
        "TCPKeepAlive yes",
        "ConenctTimeout 10",
        "BatchMode yes"
    ]
);

有时,长时间运行的命令之一会随机停止打印/触发 stdout 或 stderr 事件,并且永远不会退出。 ssh 连接不会中断(据我所知),因为 $ssh->cmd 仍在阻塞。

知道如何纠正这种行为吗?

最佳答案

在您的 %sshParams 哈希中,您可能需要将“TCPKeepAlive yes”添加到您的选项中:

$sshParams{'options'} = ["BatchMode yes", "TCPKeepAlive yes"];

这些选项可能适合也可能不适合您,但我建议为任何长时间运行的 SSH 连接设置 TCPKeepAlive。如果您的路径中有任何类型的状态防火墙,如果它长时间未通过连接传递流量,它可能会丢弃状态。

关于perl - 有时长时间运行的 ssh 命令会停止打印到标准输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7152203/

相关文章:

regex - Perl正则表达式-gc修饰符是什么意思?

perl - 需要解释在 Perl 中读取 "config"文件

heroku - 使用端口 443 连接到 Heroku

java - 创建用于 JSCH API 的输入流。 ( java )

linux - 如何在一个 linux 虚拟机上运行一个 shell 脚本,在另一个 linux 虚拟机上

perl - IO::Socket::SSL中的Listen参数控制什么

Perl 写宏的正确方法