shell — Управление интерактивным процессом с помощью PHP с помощью Symfony Process

Я пытаюсь контролировать системы SSH-агент добавив новые ключи к нему с помощью SSH-добавить. Для этого я использую Процесс Symfony составная часть.

Когда я запускаю этот код с веб-сайта, он работает отлично, но когда я запускаю тот же код в оболочке / консоли, процесс ssh-add зависает Enter passphrase for <path to key>:

Упрощенная версия кода выглядит примерно так

use Symfony\Component\Process\Process;

$keyPath = '<path to key>';
$keyPassword = '<password for unlocking the key>';
$socketPath = '<path to ssh-agent socket>';

$sshAdd = new Process(
"ssh-add {$keyPath}",
null,
[
'SSH_AUTH_SOCK' => $socketPath
],
$keyPassword
);
$sshAdd->run();

Как вы можете видеть в коде выше, я звоню ssh-addустанавливает SSH_AUTH_SOCK в окружающей среде так ssh-add Можно поговорить с агентом, а затем отправить пароль на входе. Как я уже говорил ранее, когда я запускаю это в веб-контексте, оно работает, но зависает в контексте оболочки / консоли.

Я сделал strace когда работает в консоли и соответствующие части выглядит следующим образом

open("<path to key>", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
write(4, "<key password>", <length of password>)      = 20
close(4)                                              = 0
wait4(9650, 0x7fff00ab3554, WNOHANG|WSTOPPED, NULL)   = 0
select(8, [5 7], [], [], {0, 0})                      = 0 (Timeout)
wait4(9650, 0x7fff00ab3554, WNOHANG|WSTOPPED, NULL)   = 0
select(8, [5 7], [], [], {0, 0})                      = 0 (Timeout)
select(8, [5 7], [], [], {0, 200000}Enter passphrase for <path to key>:) = 0 (Timeout)
select(8, [5 7], [], [], {0, 200000})                 = 0 (Timeout)
select(8, [5 7], [], [], {0, 200000})                 = 0 (Timeout)
select(8, [5 7], [], [], {0, 200000})                 = 0 (Timeout)
select(8, [5 7], [], [], {0, 200000})                 = 0 (Timeout)
...

Как вы можете видеть, запись, кажется, игнорируется и ssh-add Программа начинает блокировать ожидание ввода.

6

Решение

Наконец-то нашел решение этой проблемы после прочтения исходного кода для ssh-add и чтения это очень старая статья от Wez Furlong где он говорит о добавлении поддержки PTY в PHP.

Цитировать статью:

Это похоже на создание канала для процесса, но вместо этого создает основные (для вашего сценария) и подчиненные (для процесса, который вы запускаете) pty с помощью интерфейса / dev / ptmx вашей ОС. Это позволяет отправлять и захватывать данные из приложений, которые явно открывают / dev / tty — и это обычно делается при интерактивном запросе пароля.

Оказывается, Symfony Process также поддерживает PTY, поэтому исходному коду потребовалось всего несколько изменений. Сначала мне нужно указать, что я хочу использовать PTY вместо каналов, вызвав setPty(true), Тогда мне нужно смоделировать, что пользователь нажал ВОЙТИ после ввода пароля просто добавив к входу перевод строки.

Конечный код будет выглядеть примерно так (с комментариями к измененным строкам)

use Symfony\Component\Process\Process;

$keyPath = '<path to key>';
$keyPassword = '<password for unlocking the key>';
$socketPath = '<path to ssh-agent socket>';

$sshAdd = new Process(
"ssh-add {$keyPath}",
null,
[
'SSH_AUTH_SOCK' => $socketPath
],
$keyPassword . "\n"   // Append a line feed to simulate pressing ENTER
);
$sshAdd->setPty(true);   // Use PTY instead of the default pipes
$sshAdd->run();
7

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]