Perl Net :: SSH2 scp_put помещает файл, а затем зависает - PullRequest
3 голосов
/ 13 мая 2011

Я использую метод scp_put в Net :: SSH2 для размещения одного файла в моем домашнем каталоге на сервере Unix из коробки Windows. Я использую Strawberry Perl 5.12 (портативная версия). Я установил двоичные файлы libssh2 1.2.5, а затем Net :: SSH2 из cpan.

Вот мой фрагмент кода:

sub uploadToHost{

my $file=@_[0];
my $host=@_[1];
my $user=@_[2];
my $pass=@_[3];
my $remotelocation=@_[4];

#makes a new SSH2 object
my $ssh=Net::SSH2->new() or die "couldn't make SSH object\n"; 

#prints proper error messages
$ssh->debug(1);

#nothing works unless I explicitly set blocking on
$ssh->blocking(1);
print "made SSH object\n";

#connect to host; this always works
$ssh->connect($host) or die "couldn't connect to host\n"; 
print "connected to host\n";

#authenticates with password
$ssh->auth_password($user, $pass) or die "couldn't authenticate $user\n";
print "authenticated $user\n";

#this is the tricky bit that hangs
$ssh->scp_put($file, $remotelocation") or die "couldn't put file in $remotelocation\n";
print "uploaded $file successfully\n";

$ssh->disconnect or die "couldn't disconnect\n";

} #ends sub

Вывод (отредактировано для анонимности):

созданный объект SSH \ n

подключено к хосту \ n

аутентифицирован \ n

libssh2_scp_send_ex (ss-> сессия, путь, режим, размер, mtime, atime) -> 0x377e61c \ n

Net :: SSH2 :: Channel :: read (size = 1, ext = 0) \ n

Затем он зависает навсегда (> 40 минут в одном тесте) и должен быть убит.

Что странно, так это то, что на самом деле копирует файл на удаленный сервер! Он зависает только после его завершения. Я не смог найти ссылки на эту любопытную проблему нигде в StackOverflow или где-либо еще.

Может ли кто-нибудь направить меня в правильном направлении: 1) остановить зависание или 2) внедрить (в качестве обходного пути) таймер, который убивает эту команду через несколько секунд, чего достаточно для поиска файла?

Спасибо всем!

Ответы [ 3 ]

0 голосов
/ 13 мая 2011

Использование Net :: SFTP :: Foreign с бэкэндом Net :: SSH2, Net :: SFTP :: Foreign :: Backend :: Net_SSH2 :

use Net::SFTP::Foreign;

my $sftp = Net::SFTP::Foreign->new($host, user => $user, password => $password, backend => Net_SSH2);
$sftp->die_on_error("Unable to connect to remote host");

$sftp->put($file, $remotelocation);
$sftp->die_on_error("Unable to copy file");

Если это тоже не сработает, вы можете попробовать использовать plink (из проекта PuTTY) вместо бэкэнда Net :: SSH2.

0 голосов
/ 18 июня 2013

Я не думаю, что это висит, это просто очень медленно.В 10 раз медленнее, чем должно быть.Причина, по которой файл может показаться, заключается в том, что он выделяет файл до того, как завершит передачу.Это не так уж неожиданно, Perl ежедневно находит новые способы разочаровывать и расстраивать программистов.Иногда мне кажется, что я трачу больше времени, работая над особенностями Perl и изучая 10 немного разных способов сделать то же самое, чем делать настоящую работу.

0 голосов
/ 13 мая 2011

Вы можете попробовать использовать alarm (), чтобы заставить ваш процесс вести себя, если вы сохраните этот пример как 'alarm.pl', вы увидите, как он работает:

use strict;
use warnings;
use 5.10.0;

# pretend to be a slow process if run as 'alarm.pl s'
if (@ARGV && $ARGV[0] eq 's') {
    sleep(30);
    exit();
}

# Otherwise set an alarm, then run myself with 's'
eval {
    local $SIG{ALRM} = sub {die "alarmed\n"};
    alarm(5);
    system("perl alarm.pl s");
};
if ($@) {
    die $@ unless $@ eq "alarmed\n";
    say "Timed out slow process";
}
else {
    say "Slow process finished";
}
...