Ошибка удаленного выполнения Perl - PullRequest
1 голос
/ 21 марта 2012

В приведенном ниже коде я пытаюсь клонировать git-репозиторий на другую машину с помощью сценария Perl.

Если я печатаю $output, я получаю все сообщения для входа в систему, т. Е. Содержимое /etc/motd/, но не фактический вывод команды.

Как решить эту проблему? Я что-то не так делаю при выполнении команды ssh?

    sub myexec_remote    
    {
       my($cmd, $hostname, $filename) = @_;

       my $stdout = $stderr = $exit= "";
       my ($output) = `ssh $hostname $cmd 2>&1`;
       ## this is the command i.e, executed
       ##command is  ssh 111.22.11.32 "git clone --bare gt@l.com:/nfs/git/ /nfs/new123/"
       $exit = $?;
       if (defined $output)
       {
       open(MYOUTFILE, ">$filename");
       print MYOUTFILE "$output";
       close(MYOUTFILE);
       }

    }

Я использую обратные метки, потому что иногда ssh выполняется без пароля , и я видел, что модуль NET: SSH не поддерживает его ...

Ответы [ 2 ]

2 голосов
/ 21 марта 2012

Это потому, что вы используете оператор backticks в контексте списка :

my ($output) = `ssh $hostname $cmd 2>&1`;

При вызове в контексте списка backticks вернет список строк. Вы только захватываете первую строку и помещаете ее в $output. Другие строки игнорируются. От perldoc perlop:

В скалярном контексте он возвращается как один (потенциально многострочный) строка или undef, если команда не выполнена. В контексте списка возвращает список строк (однако вы определили строки с $ / или $ INPUT_RECORD_SEPARATOR) или пустой список, если команда не выполнена.

Решение:

1. my $output = `ssh $hostname $cmd 2>&1`;

Вызов обратных галочек в скалярном контексте приведет к тому, что $ output будет многострочным.

2. my @output = `ssh $hostname $cmd 2>&1`;

Вы можете нормально вызывать обратные пометки в контексте массива, но вам придется печатать весь массив в MYOUTPUTFILE позже

Другие комментарии:

Они не являются частью решения. Самого решения должно быть достаточно, чтобы исправить вашу ошибку. Однако они могут снизить риск ошибок и увеличить ваши знания Perl.

  1. Попробуйте использовать версию open с тремя аргументами вместо вашего двух аргумента с глобальным и отловить ошибку, когда файл не может быть открыт:

    open(my $handle, '>', $filename) or die "Unable to open file, $!";

  2. Многие люди решают использовать IPC :: System :: Simple вместо обратных галочек, потому что у вас есть больше информации, когда что-то идет не так, и вы можете избежать оболочки.

  3. Другой вариант - IPC :: Open3 , который даже позволяет легко захватывать STDOUT, STDERR и код выхода. Это немного сложнее в использовании.

0 голосов
/ 22 марта 2012

использование Net :: OpenSSH :

use Net::OpenSSH;
my $ssh = Net::OpenSSH->new($host, user => $user, password => $password);
my $output = $ssh->capture($cmd);
...