Взаимодействие 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');
?>