3

我的 perl 代码不允许超过 10 个分叉。对于下面的 perl 代码,每当我在读入脚本的机器列表中使用超过 10 台机器时,perl 脚本只会为 10 台机器分叉 10 个进程,其余的则因错误而死:

SSHProcessError ssh 进程已终止。在 serverLogin.pl 44 它死在它说 $ssh->waitfor('主机的真实性*',15); 的那一行。

PERL 脚本:

#!/usr/bin/perl -w

use Net::SSH::Expect;
use Term::ReadKey;


print "please enter filename:\n";
$filename = ReadLine;
chomp $filename;

print "please enter user ID:\n";
$userID = ReadLine;
chomp $userID;

print "please enter password:\n";
ReadMode 'noecho';
$passwordforuser = ReadLine 0;
chomp $passwordforuser;
ReadMode 'normal';

open READFILE,"<","$filename" or die "Could not open file listofmachines\n";

my @listofmachines = <READFILE>;

foreach $machine (@listofmachines)
{
    my $pid=fork();

    if ($pid){
        push(@childprocs,$pid);
    }
    elsif ( $pid == 0 ) {
        my $ssh = Net::SSH::Expect->new (
            host => "$machine",
            user => "$userID",
            password=> "$passwordforuser",
            timeout => 25,
            raw_pty => 1,
        );

        my $login_output = $ssh->run_ssh or die "Could not launch SSH\n";

        $ssh->waitfor('The authenticity of host*',15);

        #print "This output for machine $machine\n";

        $ssh->send("yes");
        $ssh->waitfor('password: ', 15);
        $ssh->send("$passwordforuser");
        $ssh->waitfor('$ ', 10);
        my @commresult=$ssh->exec("uptime");

        print $login_output;
        print @commresult;

        exit 0;
    }
    else {
        die "Could not Fork()\n";
    }
}

foreach(@childprocs){
    waitpid($_, 0)
}

请帮忙。谢谢,蓝蓝。

4

3 回答 3

3

您的脚本使用Net::OpenSSH::Parallel而不是 Net::SSH::Expect。

同时连接的数量限制为 10,以克服脚本中发生的任何资源耗尽问题(可能是 PTY):

#!/usr/bin/perl -w

use Net::OpenSSH::Parallel;
use Term::ReadKey;

print "please enter filename:\n";
$filename = ReadLine;
chomp $filename;

print "please enter user ID:\n";
$userID = ReadLine;
chomp $userID;

print "please enter password:\n";
ReadMode 'noecho';
$passwordforuser = ReadLine 0;
chomp $passwordforuser;
ReadMode 'normal';

open READFILE,"<","$filename" or die "Could not open file listofmachines\n";

my @listofmachines = <READFILE>;
chomp @listofmachines;

my $pssh = Net::OpenSSH::Parallel->new(connections => 10);
$pssh->add_host($_,
                user => $userID, password => $passwordforuser,
                master_opts => [-o => 'StrictHostKeyChecking=no'])
    for @listofmachines;

sub do_ssh_task {
    my ($host, $ssh) = @_;
    my $output = $ssh->capture('uptime');
    print "$host: $output";
}

$pssh->all(parsub => \&do_ssh_task);
$pssh->run;

for my $host (@listofmachines) {
    if (my $error = $pssh->get_error($host)) {
        print STDERR "remote task failed for host $host: $error\n";
    }
}
于 2012-10-23T08:38:55.843 回答
1

默认情况下,远程 ssh 守护进程将并发 ssh 连接数限制为每个用户标识 10 个。如果这对您来说是个问题,您将需要更改服务器配置...

于 2013-02-08T22:13:42.237 回答
0

也许您对可以创建的进程数量有限制?您可以在孩子们只是睡觉(60)的循环中创建30个或更多进程吗?

如果实际上您一次可以执行多少个限制,请尝试使用Parallel::ForkManager

如果这是由于达到了伪终端的限制,那么您如何设置取决于内核版本;uname -a 说什么?还取决于代码是使用 BSD 还是 SysV/UNIX98 ptys。如果你看到它打开像 /dev/ptyXY 这样的文件,其中 X 是 ae 或 pz 之一,它是前者,你将在系统范围内有 256 个硬限制。

usermod您可以在没有伪终端的情况下使用而不是更改密码passwd,但这会暂时暴露进程列表中的加密密码;在您的情况下这可能是可以接受的。

于 2012-10-22T20:45:46.730 回答