2010-11-05 2 views
3

Я пытаюсь установить интерактивное соединение SSH с удаленным сервером с помощью PHP через командную строку в Mac OS X 10.6. В настоящее время я использую функцию proc_open PHP, чтобы выполнить следующую команду:Как я могу использовать PHP для установки интерактивной сессии SSH?

ssh -t -t -p 22 [email protected] 

Это почти работает. Предполагается, что параметры -t -t вынуждают псевдотерминал, который они почти делают. Я могу ввести пароль SSH и нажать enter. Однако после нажатия введите терминал, который просто зависает. Нет вывода, ничего нет - это похоже на неудачный сеанс SSH. Я не могу запускать команды или что-то еще и должен убить все это, используя Ctrl + C. Я знаю, что логин успешный, потому что я могу выполнить команду, как ssh -t -t -p 22 [email protected] "ls -la" и получить правильный вывод.

Я думал, что проблема должна быть связана с тем, что я использовал стандартные трубки в моем вызове proc_open, поэтому я заменил их на pty. Я получаю следующую ошибку: «pty pseudo terminal не поддерживается в этой системе ...»

Mac OS X просто не поддерживает pty или псевдо терминалы? (Я довольно новичок в использовании всей этой терминологии оболочки).

Вот код PHP:

$descriptorspec = array(0 => array("pty"), 1 => array("pty"), 2 => array("pty")); 
$cwd = getcwd(); 
$process = proc_open('ssh -t -t -p 22 [email protected]', $descriptorspec, $pipes, $cwd); 
if (is_resource($process)) 
{ 
    while (true) 
    { 
     echo(stream_get_contents($pipes[1])); 
     $status = proc_get_status($process); 
     if (! $status["running"]) 
      break; 
    } 
} 

(К сожалению - не могу за жизнь мне понять, ТАК это форматирование инструкции ...)

Что я делаю неправильно? Почему я не могу использовать pty? Это просто невозможно в Mac OS X? Спасибо за вашу помощь!

+0

Я установил форматирование для вас. Чтобы форматировать блоки кода, просто добавьте четыре пробела в начало каждой строки кода. Для форматирования встроенных образцов кода используются обратные элементы '\' '. – BoltClock

+0

Если вы укажете причину открытия SSH с PHP, возможно, мы сможем найти другие способы достижения того, что вы пытаетесь сделать. –

+0

Я пытаюсь открыть SSH-соединение в PHP, потому что я работаю над инфраструктурой развертывания, которая будет автоматизировать развертывание кода на удаленном сервере, вроде как Capistrano. Основная задача состоит в том, чтобы иметь возможность проверять код из хранилища Subversion/Git/Bazaar и автоматизировать другие задачи. – Cameron

ответ

5

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

Предполагается, что приглашение пароля будет использоваться с tty, и я считаю, что это было намеренно трудно использовать иначе. Также аргумент -t -t вступает в силу только после подключения к удаленному хосту. И я не верю, что функция PHP proc_open() может запускать команду внутри виртуального терминала.

Для настройки аутентификации с открытым ключом:

# Generate keypair 
ssh-keygen -t rsa 

# Copy public key to server 
scp ~/.ssh/id_rsa.pub example.com:.ssh/authorized_keys 

# Now you shouldn't be prompted for a password when connecting to example.com 
# from this host and user account. 
ssh example.com 

# Since the web server (and thus PHP) probably has its own user account... 
# Copy the ~/.ssh/id_rsa file somewhere else 
cp ~/.ssh/id_rsa /some_path/id_rsa 

# Change ownership of the file to the web server account 
chown www-data:www-data /some_path/id_rsa 

# Fix the file permissions (ssh ignore the keyfile if it is world readable) 
chown 600 /some_path/id_rsa 

# Try connecting to the server through the web server account 
su -c "ssh -i /some_path/id_rsa -o UserKnownHostsFile=/some_path/known_hosts example.com" www-data 

# Add the host to the known hosts file when prompted 


В качестве альтернативы, вы можете использовать plink (часть замазки для Linux), а не OpenSSH, как это может занять пароль в командной строке plink -pw password example.com. Но при этом возникает угроза безопасности, поскольку любой, кто запускает ps aux на сервере, может видеть пароль в списке процессов.

Существует также программа под названием sshpass, которая берет пароль из переменной окружения или аргумента команды и передает ее в ssh.

+0

Я бы не рекомендовал последний вариант, имея пароль, видимый в команде. Любой, кто запускает 'ps aux' на сервере, может видеть ваш пароль. – Lekensteyn

+0

@ Lekensteyn Спасибо, я отредактировал мое сообщение. –

+0

Спасибо Alexandre, но это выходит за рамки простого пароля для входа. Я также хотел бы иметь возможность предлагать интерактивную сессию пользователям моей инфраструктуры, чтобы они могли отвечать на любые запросы, которые они могли бы получать с сервера. Доступ к открытым ключам велик, просто не для этой цели. Я просто использую логин SSH в качестве примера. – Cameron

1

Вы пробовали PHP SSH2 extension?

+0

Я пробовал расширение SSH2 безрезультатно. Это не даст мне интерактивную сессию через каналы или pty. Я могу выполнять команды и получать выходные данные, но ничего с входом не будет работать (как и все, что требует пароль). – Cameron

3

Похоже, проблема лучше всего решить с помощью функции passthru() PHP. После еще большего (довольно болезненного) исследования я смог выпустить команду через эту функцию и мог взаимодействовать с удаленным сервером через терминал, как если бы я выполнял экспорт ssh и svn вручную (они оба требуют пароли, поэтому были хорошими тестами) ,Мне нужно будет построить (потенциально очень длинную) строку команд, разделенных && и присоединить их к концу команды ssh: ssh -t -t -p 22 hostname command1 && command2 ... Выход будет отправлен на мой терминал в Mac OS X, команды выполняются на удаленном сервере. Похоже, это решение, которое я искал все время - довольно просто! Спасибо всем, кто помог мне с этим. Я дал Александру «зеленую галочку», потому что он был единственным, кто продолжал отвечать, и был весьма полезен в выводе окончательного ответа на проблему. Спасибо Александру!

+0

Я думаю, что это должен быть принятый ответ. –

1

Это старая, но и для любых Googlers там, вот фактическое решение с использованием proc_open:

Pty дескрипторы доступны в PHP, но должны (см. этот отчет об ошибке 10yr old https://bugs.php.net/bug.php?id=33147)

Но в python, однако, у нас нет этой проблемы. Таким образом, вместо того, чтобы выполнить команду SSH непосредственно, запустить этот питон скрипт:

import sys 
import pty 

args = " ".join(sys.argv[1:]) 
pty.spawn(['/usr/bin/ssh', args]) 

О pty.spawn из питона документы:

Spawn a process, and connect its controlling terminal with the current process’s standard io. This is often used to baffle programs which insist on reading from the controlling terminal.

Смежные вопросы