Perl Net :: SSH2 scp_put помещает файл и зависает

Я использую метод 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 (размер = 1, ext = 0) \ n

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

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

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

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


person dave35    schedule 12.05.2011    source источник


Ответы (3)


Вы можете попробовать использовать 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";
}
person Alex    schedule 13.05.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.

person salva    schedule 13.05.2011

Я не думаю, что он висит, он просто ДЕЙСТВИТЕЛЬНО МЕДЛЕННО. В 10 раз медленнее, чем должно быть. Причина, по которой файл может оказаться там, заключается в том, что он выделяет файл до того, как он завершил передачу. На самом деле это не слишком неожиданно, Perl ежедневно находит новые способы разочаровывать и расстраивать программистов. Иногда мне кажется, что я трачу больше времени на изучение особенностей Perl и изучение 10 способов сделать то же самое, что и реальная работа, несколько иначе.

person MikeKulls    schedule 18.06.2013
comment
Чтобы добавить к этому, похоже, что он начинается медленно, около 150 КБ / с на ссылке, которая может работать со скоростью 5 МБ / с, но затем после передачи примерно 2 МБ данных она замедляется до примерно 5 КБ / с. Так что на самом деле он работает буквально в 1000 раз медленнее, чем должен. - person MikeKulls; 27.06.2014