Как я могу использовать PHP для настройки интерактивного сеанса SSH? - PullRequest
3 голосов
/ 05 ноября 2010

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

ssh -t -t -p 22 user@server.com

Это почти работает. Опции -t -t должны вызывать псевдо-терминал, что они почти делают. Я могу ввести пароль SSH и нажать Enter. Однако после нажатия кнопки ввода терминал, кажется, просто зависает. Нет вывода, нет ничего - все равно, что сеанс SSH не удался. Я не могу запускать команды или что-то еще, и мне приходится убивать все это с помощью Ctrl + C. Я знаю, что вход в систему успешен, потому что я могу выполнить команду типа ssh -t -t -p 22 user@server.com "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 user@server.com', $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? Спасибо за вашу помощь!

Ответы [ 6 ]

5 голосов
/ 05 ноября 2010

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

Предполагается, что запрос на ввод пароля используется из 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.

3 голосов
/ 07 ноября 2010

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

2 голосов
/ 06 августа 2015

Это старый, но для любого гуглера, вот актуальное решение с использованием 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:

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

1 голос
/ 18 октября 2012

Вы пробовали 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 голос
/ 05 ноября 2010

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

0 голосов
/ 20 июля 2018

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

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

...