2016-02-24 2 views
2

Я хочу получить стандартную ошибку, отображаемую на главной машине после (ssh-> capture) переменной.не удалось захватить stderr во время выполнения openssh для переменной-perl

, например, когда я пытаюсь:

use Net::OpenSSH; 

my $ssh = Net::OpenSSH->new($host); 
my $out=$ssh->capture("cd /home/geek"); 
$ssh->error and 
die "remote cd command failed: " . $ssh->error; 

из пут:

child exited with code 1 at ./change_dir.pl line 32 

я не в состоянии видеть, что это ошибка. я не получаю такого файла или каталога на терминале. Я хочу захватить тот же «нет такого файла или директора» в $ out.

пример 2,

my ($stdout,$stderr)=$ssh->capture("cd /home/geek"); 
if($stderr) 
print"Error = $stderr"; 
else 
print "$stdout" 

я вижу "Error =" напечатаны, но не seee что $ STDERR на экране. Я вижу, что $ stdout напечатан с успехом, но print $ stderr не печатается, только печатается сообщение «Ошибка =».

+0

отредактировал вопрос. :) – geek

+1

вы можете использовать '$ ssh -> error'. в чем проблема? –

ответ

3

Когда возникает ошибка, скорее всего не будет в STDOUT, и если он находится в STDERR вы не поймать что. Вам нужно перейти к коду выхода приложения следующим образом. (Учитывая обновление на вопрос, который я только видим сейчас: Смотрите в конце для того, как получить STDERR.)

После capture метода вы хотите исследовать $? на наличие ошибок (см Net-OpenSSH). Распаковка, что, чтобы получить код завершения, возвращаемый что на самом деле управляет $ssh, а затем посмотреть в документации этого приложения, чтобы увидеть, что означает, что код

$exit_code = $?; 
if ($exit_code) { 
    $app_exit = $exit_code >> 8; 
    warn "Error, bit-shift \$? --> $app_exit"; 
} 

Код для исследования является $app_exit.

Пример. Я использую zip в проекте и иногда улавливаю ошибку 3072 (то есть $?). Когда это распакованно, как указано выше, я получаю 12, то есть фактический выход zip. Я просматриваю его документы, и он красиво перечисляет его коды выхода и 12 означает Ничего не обновлено. Это дизайнерское решение для zip, для выхода с 12, если у него не было файлов для обновления в архиве. Затем этот выход упаковывается в двухбайтовое число (в верхнем байте) и , что возвращается и, следовательно, я получаю в $?.

режимы отказов в общем, от system в документации Perl

if ($? == -1) { warn "Failed to execute -- " } 
elsif ($? & 127) { 
    $msg = sprintf("\tChild died with signal %d, %s coredump -- ", 
     ($? & 127), ($? & 128) ? 'with' : 'without'); 
    warn $msg; 
} else { 
    $msg = sprintf("\tChild exited with value %d -- ", $? >> 8); 
    warn $msg; 
} 

Фактический код выхода $? >> 8 подается независимо от RAN и поэтому его интерпретация до этого приложения. Вам нужно просмотреть его документы и, надеюсь, его коды выхода будут задокументированы.


Отметьте, что $ssh->error кажется предназначен для этой задачи. Из документов модуля

my $output = $ssh->capture({ timeout => 10 }, "echo hello; sleep 20; echo bye"); 
$ssh->error and warn "operation didn't complete successfully: ". $ssh->error; 

Печатная ошибка требует дальнейшего изучения.Документы не говорят, что это такое, но я бы ожидал, что распакованный код, описанный выше (, это обновление). Здесь $ssh выполняет только команду и не знает, что пошло не так. Он просто возвращает код выхода команды, чтобы посмотреть.

Или вы можете изменить команду, чтобы получить STDERR на STDOUT, см. Ниже.


capture метод является эквивалентом обратных кавычек в Perl (qx). Существует много на SO о том, как получить STDERR от backticks, а собственный FAQ для Perl имеет то, что красиво написано in perlfaq8. Усложнение состоит в том, что это не qx, а метод модуля и, что более важно, он работает на другой машине. Однако метод «перенаправления вывода» должен работать без изменений. Команда (выполняется $ssh) может быть записана так, чтобы ее STDERR перенаправлялся на ее STDOUT.

$cmd_all_output = 'your_whole_command 2>&1'; 
$ssh->capture($cmd_all_output); 

Теперь вы получите сообщение об ошибке, которое вы видите на терминале («нет такого файла или каталога»), напечатанной на STDOUT, таким образом, он будет ветер в вашем $stdout. Обратите внимание, что необходимо использовать синтаксис оболочки sh, как указано выше. Для этого есть немного больше, поэтому, пожалуйста, просмотрите его (но это должно работать так, как оно есть). В большинстве случаев это то же сообщение, что и в описании кода выхода.

Проверка, что у вас есть в вашем коде хорошо, первая линия обороны: один должен всегда проверка $? при выполнении внешних команд, и для этого команду для запуска не нужно трогать.

 Смежные вопросы

  • Нет связанных вопросов^_^