Как я могу использовать PHP для настройки интерактивного сеанса SSH?


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

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

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

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

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;  
    }  
} 

(Извините - ни за что на свете не могу разобраться в инструкциях по форматированию SO...)

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

Author: BoltClock, 2010-11-05

6 answers

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

Предполагается, что запрос пароля должен использоваться из 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 (часть PuTTY для Linux) вместо OpenSSH, поскольку он может принимать пароль в командной строке plink -pw password example.com. Но это создает угрозу безопасности, поскольку любой, кто запускает ps aux на сервере, может видеть пароль в списке процессов.

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

 5
Author: Alexandre Jasmin, 2015-05-21 09:28:56

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

 3
Author: Cameron, 2010-11-06 23:10:25

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

Дескрипторы Pty доступны в PHP, но должны быть настроены во время компиляции (см. Этот 10-летний отчет об ошибке https://bugs.php.net/bug.php?id=33147)

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

import sys
import pty

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

О pty.spawn из документов python:

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

 2
Author: Magnus Jeffs Tovslid, 2015-08-06 07:23:34

Вы пробовали расширение PHP SSH2?

 1
Author: Anti Veeranna, 2010-11-05 09:26:05

Вы пробовали phpseclib, чистую реализацию PHP SSH?:

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

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

echo $ssh->read('username@username:~$');
$ssh->write("ls -la\n");
echo $ssh->read('username@username:~$');
?>
 1
Author: neubert, 2012-10-18 19:13:55

Я написал ssh-клиент на php с расширением ssh2, вы можете взглянуть на исходный код на странице github https://github.com/roke22/PHP-SSH2-Web-Client

Пожалуйста, отправьте несколько отзывов.

 0
Author: Roke, 2018-07-20 19:49:45