cod*_*ken 6 php shell process symfony symfony-process
我试图通过使用ssh-add向其添加新密钥来控制系统ssh-agent.为此我正在使用Symfony Process组件.
当我从一个网站运行这个代码时它工作得很好但是当我在shell/console中运行相同的代码时,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();
Run Code Online (Sandbox Code Playgroud)
正如您在上面的代码中看到的那样,我打电话给ssh-add,SSH_AUTH_SOCK在环境中设置,以便ssh-add与代理交谈,然后在输入中发送密码.正如我之前所说,当我在Web上下文中运行它时,它可以工作但它挂在shell /控制台上下文中.
我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)
...
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,写入似乎被忽略,ssh-add程序开始阻止等待输入.
在阅读了ssh-add的源代码之后,最后找到了解决这个问题的方法,并阅读了Wez Furlong的这篇非常古老的文章,其中他谈到了向PHP添加PTY支持.
引用文章:
这样做类似于为进程创建管道,而是使用操作系统的/ dev/ptmx接口创建master(对于您的脚本)和slave(对于您正在运行的进程)pty句柄.这允许您向显式打开/ dev/tty的应用程序发送和捕获数据 - 这通常在交互式提示输入密码时完成.
事实证明,Symfony Process也支持PTY,因此原始代码只需要进行一些更改.首先,我需要通过调用指定我想使用PTY而不是管道setPty(true).然后,我需要模拟用户按下ENTER键通过追加一个换行符输入简单地输入密码后.
最终的代码看起来像这样(在更改的行上有注释)
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();
Run Code Online (Sandbox Code Playgroud)