在SIGINT时优雅地关闭ssh并退出net :: ssh :: perl
发布时间:2020-12-15 23:32:40 所属栏目:大数据 来源:网络整理
导读:我正在连接到远程主机并执行一个不退出的命令(tail -f logfile) 我正在注册一个处理程序并将输出写入日志文件. 这工作正常 但我想在主程序上按Control C,它应该停止远程机器上的命令并正常关闭ssh连接 所以我正在为SIGINT注册一个信号处理程序 需要我需要放
我正在连接到远程主机并执行一个不退出的命令(tail -f logfile)
我正在注册一个处理程序并将输出写入日志文件. 所以我正在为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,但不是. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |