加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

在SIGINT时优雅地关闭ssh并退出net :: ssh :: perl

发布时间:2020-12-15 23:32:40 所属栏目:大数据 来源:网络整理
导读:我正在连接到远程主机并执行一个不退出的命令(tail -f logfile) 我正在注册一个处理程序并将输出写入日志文件. 这工作正常 但我想在主程序上按Control C,它应该停止远程机器上的命令并正常关闭ssh连接 所以我正在为SIGINT注册一个信号处理程序 需要我需要放
我正在连接到远程主机并执行一个不退出的命令(tail -f logfile)

我正在注册一个处理程序并将输出写入日志文件.
这工作正常
但我想在主程序上按Control C,它应该停止远程机器上的命令并正常关闭ssh连接

所以我正在为SIGINT注册一个信号处理程序

需要我需要放在子程序中的代码

下面的代码位于一个从forked child调用的函数中

#!/ats/bin/perl

use Net::SSH::Perl;
use File::Path;
use Text::CSV_XS;

chomp ($progName = `basename $0`);

if (@ARGV != 1 ) {
        print "usage: perl $progName <tc_id>n";
        exit;
}

$tc_id = shift;
$file = "config.prop";
$log_dir = "logs/";


#$SIG{INT}=&;close_write;

sub close_write
{
#-- write it to file
print "nInside END blockn";
#open FH,">$log_file";
#print $log_file;
#print FH @out;
#$thr->kill('INT');
#close $ssh->sock;
#undef $ssh;
exit 1;
}

# Read the configuration file and populate the Hash
$index = 0;
my $csv = Text::CSV_XS->new ({ binary => 1,eol => $/ });
 open my $io,"<",$file or die "$file: $!";
 while (my $row = $csv->getline ($io)) {
    next if (${$row}[0] =~ m/^#/);  #Ignore comments
    next if (${$row}[0] =~ m/^s*$/);   #Ignore blank lines
    ($logHashArray->[$index]->{host},$logHashArray->[$index]->{user},$logHashArray->[$index]->{pass},$logHashArray->[$index]->{cmd},$logHashArray->[$index]->{log_file}) = @$row;
    $index++;
 }


# Append "/" at the end of the directory if it does not exist
unless ($log_dir =~ m//$/) {
        $log_dir = $log_dir . "/";
        print "LogDir: $log_dirn";
        }
# Check if the log directory exists,if not,create it
if (-e $log_dir) {
        unless (-d $log_dir) {
                die "File exists but is not directory";
                }
        }
else {
        # don't forget to check mkdir's failure
        print "Directory $log_dir does not exist... Creating itn";
        mkpath($log_dir,0777) or die "Can't make directory: $!";
        }



foreach $logHash (@{$logHashArray}){
        #print "LogHash Index $logHashn";
        $logHash->{log_file} = $tc_id . "_" . $logHash->{host} . "_" .$logHash->{log_file};
        $logHash->{cmd} = $logHash->{cmd} . " | tee /tmp/" . $logHash->{log_file};
        $logHash->{log_dir} = $log_dir;

        #$logHash->{thr}=threads->new(&;connect_get_logs,$logHash);

        $logHash->{pid} = fork();

        if ($logHash->{pid}){
            # Parent
            push(@childs,$logHash->{pid});
        }
        elsif ($pid == 0){
            # Child
            connect_get_logs($logHash);
        }
        else {
            die "couldn’t fork: $!n";
            }

while (($key,$value) = each(%{$logHash})){
     print $key."=>".$value."n";
}

}

#$SIG{INT}=&;close_write;
#$thr=threads->new(&;connect_get_logs,$logHash);

foreach (@childs) {
    waitpid($_,0);
    }


#print "Waiting...";
#while(1) {sleep 1;}

#$thr->join;


sub connect_get_logs{

$SIG{INT}= sub {
        print "Inside INT blockn"; ### Need proper code here
        close $ssh->sock;
        undef $ssh;
        };

my $logHash = shift;

while (($key,$value) = each(%{$logHash})){
     print $key."=>".$value."n";
}
my $stdout;
my $stderr;
my $exit;

#-- setup a new connection
print "Logging in to $logHash->{host}...";
my $ssh = Net::SSH::Perl->new($logHash->{host},debug => 0,protocol => '2',options => ["PasswordAuthentication yes","BatchMode yes","PubkeyAuthenticaion no","RhostsAuthentication no","RhostsRSAAuthentication no","RSAAuthentication no","DSAAuthentication no"]);

#-- authenticate
$ssh->login($logHash->{user},$logHash->{pass});
print "Logged Inn";

#-- Create or Overwrite the log files
open LOG_FILE,">","$logHash->{log_dir}$logHash->{log_file}" or die $!;

#-- register a handler
$ssh->register_handler("stdout",sub {
        my($channel,$buffer) = @_;
        $str = $buffer->bytes;
        #push @out,$str;
        print LOG_FILE $str;
        #print $str;
});

#$SIG{INT}=&;close_write;

#-- execute the command
($stdout,$stderr,$exit) = $ssh->cmd($logHash->{cmd});

print "Error: $stderr";

}

以csv格式创建config.prop文件

host / ip,username,password,command(tail -F / full / path / to / logfile),要保存的文件名

解决方法

诀窍是使用-t(或可能是-tt)调用ssh.

默认情况下,ssh仅在远程计算机上为交互式登录shell分配pty(即,不在远程调用命令时). -t强制ssh分配pty,即使在执行远程命令时也是如此.你可以看到效果:

$ssh starquake tty
not a tty

VS

$ssh -t starquake tty
/dev/pts/1
Connection to starquake closed.

当连接到终端时ssh apparently will pass on signals to the remote process,但不是.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读