我正在尝试异步运行多个SSH命令到多个服务器,我想从命令中捕获输出并按顺序显示它们。 要投入额外的曲线球,我希望pid3只在pid2完成后运行,而pid4在前三个命令完成后运行。如何最好地完成这项工作?
示例:的
// $pid1 and $pid2 should run asynchronously
my $pid1 = open(my $SSH1, "|ssh -t -t runuser\@$server{'app'} 'sudo chef-client'");
my $pid2 = open(my $SSH2, "|ssh -t -t runuser\@$server{'auth'} 'sudo chef-client'");
// This command should wait for $pid2 to complete.
my $pid3 = open(my $SSH3, "|ssh -t -t runuser\@$server{'auth'} \"sudo -- sh -c '$update_commands'\"");
// This command should wait for $pid1-3 to complete before running.
my $pid4 = open(my $SSH4, "|ssh -t -t runuser\@$server{'varn'} \"sudo -- sh -c '$varn_commands'\"");
答案 0 :(得分:1)
# Silence all non-error output from the commands on first 2 servers:
my $pid1 = open(my $SSH1, "|ssh -t -t runuser\@$server{'app'} 'sudo chef-client > /dev/null'");
my $pid2 = open(my $SSH2, "|ssh -t -t runuser\@$server{'auth'} 'sudo chef-client > /dev/null'");
if ($pid1) {
print "Connecting to $server{'app'}: chef-client";
while ( <$SSH1> ) {
print $server{'app'};
print $_;
}
}
close $SSH1 or die $!;
if ($pid2) {
print "Connecting to $server{'auth'}: chef-client";
while ( <$SSH2> ) {
print $server{'auth'};
print $_;
}
}
close $SSH2 or die $!;
# Run pid3 once pid2 is closed
my $pid3 = open(my $SSH3, "|ssh -t -t runuser\@$server{'auth'} \"sudo -- sh -c '$update_command'\"");
if ($pid3) {
print "Connecting to $server{'auth'}: $update_command";
while ( <$SSH3> ) {
print $_;
}
}
close $SSH3 or die $!;
# Run pid4 after all previous commands have completed.
my $pid4 = open(my $SSH4, "|ssh -t -t runuser\@$server{'varn'} \"sudo -- sh -c '$varn_command'\"");
if ($pid4) {
print "Connecting to $server{'varn'}: $varn_command";
while ( <$SSH4> ) {
print $_;
}
}
close $SSH4 or die $!;
答案 1 :(得分:1)
Forks::Super
处理所有这些要求:
use Forks::Super;
# run $command1 and $command2 , make stderr available
my $job1 = fork { cmd => $command1, child_fh => 'err' };
my $job2 = fork { cmd => $command2, child_fh => 'err' };
# job 3 must wait for job 2. Collect stdout, stderr
my $job3 = fork { cmd => $command3, depend_on => $job2, child_fh => 'out,err' };
# and job 4 waits for the other 3 jobs
my $job4 = fork { cmd => $command4, depend_on => [ $job1, $job2, $job3 ],
child_fh => 'out,err' };
# wait for jobs to finish, then we'll collect output
$_->wait for $job1, $job2, $job3, $job4;
my @output1 = $job1->read_stderr;
my @output2 = $job2->read_stderr;
my @output3 = ($job3->read_stdout, $job3->read_stderr);
my @output4 = ($job4->read_stdout, $job4->read_stderr);
...
答案 2 :(得分:1)
# untested!
use Net::OpenSSH::Parallel;
my $pssh = Net::OpenSSH::Parallel->new;
$pssh->add_server(app => $server{app}, user => 'runuser');
$pssh->add_server(auth => $server{auth}, user => 'runuser');
$pssh->add_server(varn => $server{varn}, user => 'runuser');
$pssh->push('app', cmd => @cmd1);
$pssh->push('auth', cmd => @cmd2);
$pssh->push('auth', cmd => @cmd3);
$pssh->push('varn', join => '*');
$pssh->push('varn', cmd => @cmd4);
$pssh->run;
如果您需要传递密码,自动sudo
稍微复杂一些,但仍然可以完成。它在模块文档中进行了解释。