SSH с Perl с использованием файловых дескрипторов, а не Net :: SSH - PullRequest
4 голосов
/ 28 декабря 2010

Прежде чем задать вопрос:

Я не могу использовать модуль cpan Net :: SSH, хочу, но не могу, никакое количество попрошайничества не изменит этот факт

Мне нужнобыть в состоянии открыть соединение SSH, держать его открытым, читать его стандартный вывод и записывать в стандартный вывод.До сих пор мой подход состоял в том, чтобы открыть его в трубе, но я не смог продвинуться дальше этого, он сразу же умирает.

Это то, что я имею в виду, я понимаю, что это вызывает развилку,Я написал соответствующий код для этого форка (или, я так думаю).

Ниже приведен скелет того, что я хочу, мне просто нужна система для работы.

#!/usr/bin/perl


use warnings;

$| = 1;

$pid = open (SSH,"| ssh user\@host");

if(defined($pid)){
    if(!$pid){
        #child
        while(<>){
            print;
        }
    }else{
        select SSH;
        $| = 1;

        select STDIN;

        #parent
        while(<>){
            print SSH $_;
            while(<SSH>){
                print;
            }
        }
    close(SSH);
    }
}

Я знаюИсходя из того, как это выглядит, я пытаюсь воссоздать «system ('ssh user @ host')», это не моя цель end , но знание того, как это сделать, приблизило бы меня кконечная цель.

По сути, мне нужен дескриптор файла для открытого ssh-соединения, где я могу читать из него выходные данные и записывать в них входные данные (не обязательно прямо из STDIN моей программы, все, что я хочу, переменные,yada yada)

Это включает в себя ввод пароля.

Я знаю о парах ключей, часть конечной цели заключается в создании пар ключей, но соединение должно происходить независимо от их существования, и если онине существует, это часть моего плана, чтобы заставить их существовать.

Ответы [ 4 ]

2 голосов
/ 28 декабря 2010

Это работает для меня:

use strict; use warnings;

my $pid = open my $SSH, '-|', 'ssh user@example.com' // die $!;

if ($pid) {
    while( <$SSH> ) {
        print $_;
    }
}
else {
    while( <> ) {
        print $SSH $_;
    }
}

close $SSH or die $!;
1 голос
/ 28 декабря 2010

Подумайте об использовании autossh и настройке переадресации портов с локального порта с помощью ключа ssh -L, а затем просто подключитесь к локальному порту.Это чрезвычайно упрощает задачу программирования за счет минимальной настройки.

Автоматическое создание пар ключей - действительно плохая идея;они должны быть установлены заранее.Каким-то образом автоматизация, которая просто требует проблем с безопасностью.

Если вам действительно нужно иметь дело с ssh и запросами пароля, Ожидайте - это способ старой школы.Я не уверен, что крутые дети используют в настоящее время.Обновление: я забыл, но есть чистый модуль perl Net :: SSH :: Expect , который управляет программой ssh;Вы, вероятно, хотите использовать его или обильно позаимствовать у него.

0 голосов
/ 07 сентября 2014

Здесь слишком сложно детализировать, но использование основного соединения ssh (через ControlMaster) является альтернативой использованию OpenSSH.После установки все последующие соединения SSH, независимо от метода (в том числе с помощью открытого $ SSH '| -' 'ssh user @ host "command"'), мультиплексируются через мастер без необходимости повторной авторизации и без дополнительных затрат на установку каждого нового SSH.время.До некоторой степени, именно так работает OpenSSH.

К сожалению, предлагаемый мною метод недоступен в родной среде Microsoft Windows.

0 голосов
/ 14 декабря 2011

Если можете, используйте Net :: OpenSSH или Net :: SSH2 . Например:

use Net::OpenSSH;
my $ssh = Net::OpenSSH->new($host, user => $user, password => $password);
my ($in, $out, $pid) = $ssh->open2($remote_cmd);

В противном случае используйте IPC :: Open2, чтобы открыть двунаправленную связь:

use IPC::Open2 qw(open2);
my $pid = open2(my $in, my $out, $ssh_cmd);

Или для более сложной и сложной реализации, которая также поддерживает аутентификацию по паролю (через Expect ), взгляните на исходный код Net :: SFTP :: Foreign :: Backend :: Unix :: _ open4

...