процесс открытого взаимодействия


Вот чего я пытаюсь достичь: откройте оболочку (korn или bash, не имеет значения), из этой оболочки я хочу открыть ssh-соединение (ssh user@host). В какой-то момент, скорее всего, произойдет, что мне будет предложено ввести пароль, или меня могут спросить, уверен ли я, что хочу подключиться (оскорбительные ключи).

Прежде чем кто-нибудь спросит: да, я знаю, что есть плагин для вызовов ssh2 exec, но серверы, над которыми я работаю, не поддерживают его и вряд ли будут это делать.

Вот что я пробовал до сих пор:

$desc = array(array('pipe','r'),array('pipe','w'));//used in all example code
$p = proc_open('ssh user@host',$desc,$pipes);
if(!is_resource($p)){ die('@!#$%');}//will omit this line from now on
sleep(1);//omitting this,too but it's there every time I need it

Затем я попытался прочитать вывод консоли (stream_get_contents($pipes[1])), чтобы увидеть, что мне нужно передать дальше (либо пароль, да, либо возврат 'connection failed: '.stream_get_contents($pipes[1]) и proc_close $p.

Это дало мне следующую ошибку:

Псевдотерминал не будет выделен, поскольку стандартный ввод не является терминалом.

Итак, я, хотя ssh был вызван в контексте php:// потока ввода-вывода, кажется правдоподобным объяснением вышеупомянутой ошибки.

Далее: Я подумал о моем первый вопрос SO и решил, что было бы неплохо сначала открыть оболочку bash/ksh:

$p = proc_open('bash',$desc,$pipes);

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

$p=proc_open('bash && ssh user@host',$desc,$pipes);

После нескольких секунд ожидания я получил следующую ошибку:

Неустранимая ошибка PHP: Разрешенный объем памяти 134217728 байт исчерпан (пытался выделить 133693440 байт)

Стек вызовов продолжает выводить строку stream_get_contents, даже в моей последней отчаянной попытке:

#!/path/to/bin/php -n
<?php
    $p = proc_open('bash && ssh user@host',array(array('pipe','r'),array('pipe','w')),$ps);
    if (!is_resource($p))
    {
        die('FFS');
    }
    usleep(10);
    fwrite($ps[0],'yes'."\n");
    fflush($ps[0]);
    usleep(20);
    fwrite($ps[0],'password'."\n");
    fflush($ps[0]);
    usleep(20);
    fwrite($ps[0],'whoami'."\n");
    fflush($ps[0]);
    usleep(2);
    $msg = stream_get_contents($ps[1]);
    fwrite($ps[0],'exit'."\n");
    fclose($ps[0]);
    fclose($ps[1]);
    proc_close($p);
?>

Я знаю, что это беспорядок, много fflush и избыточности, но суть в том, что я знаю, что это соединение сначала запросит у меня ключи, а затем попросит пароль. Я предполагаю, что поток в $pipes[1] содержит ssh-соединение, поэтому его содержимое огромно. что мне тогда нужно, так это труба внутри трубы... возможно ли это вообще? Должно быть, я что-то упускаю, что хороша труба, если это невозможно... Я предполагаю, что команда proc_open изначально неверна (ошибка: Сломанная труба). Но я действительно не вижу другого способа обойти первую ошибку... есть какие-нибудь мысли? Или задавайте дополнительные вопросы, если вышеприведенная тирада совсем не ясна (что, вероятно, не так).

Author: Community, 2012-04-11

1 answers

Прежде чем кто-нибудь спросит: да, я знаю, что есть плагин для вызовов ssh2 exec, но серверы, над которыми я работаю, не поддерживают его и вряд ли будут это делать.

На самом деле их два. Модуль PECL, который представляет собой PITA, который все равно не установлен на большинстве серверов, и phpseclib, чистая реализация PHP SSH2. Пример его использования:

<?php
include('Net/SSH2.php');

$ssh = new Net_SSH2('www.domain.tld');
if (!$ssh->login('username', 'password')) {
    exit('Login Failed');
}

echo $ssh->exec('pwd');
echo $ssh->exec('ls -la');
?>
 1
Author: neubert, 2012-04-11 17:15:51