Взаимодействие proc_open

Вот что я пытаюсь достичь: открыть оболочку (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.

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

Псевдо-терминал не будет выделен, потому что stdin не является терминалом.

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

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

1 ответ

Решение

Прежде чем кто-либо спросит: да, я знаю, что есть плагин для вызовов 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');
?>
Другие вопросы по тегам