我正在尝试使用ssh-agent向系统添加新密钥来控制系统ssh-add。为此,我使用Symfony Process组件。
当我从网站运行此代码时,它运行得很好但是当我在shell /控制台中运行相同的代码时,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
可以与代理商交谈,然后在输入。正如我之前所说,当我在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)
...
正如您所看到的,写入似乎被忽略,ssh-add
程序开始阻止等待输入。
答案 0 :(得分:7)
在阅读了ssh-add的源代码之后,最后找到了解决这个问题的方法,并阅读了this very old article from Wez Furlong,他谈到了向PHP添加PTY支持。
引用文章:
这样做与创建进程的管道类似,而是使用操作系统的/ dev / ptmx接口创建master(对于您的脚本)和slave(对于您正在运行的进程)pty句柄。这允许您向显式打开/ dev / tty的应用程序发送和捕获数据 - 这通常在交互式提示输入密码时完成。
原来Symfony Process也支持PTY,因此原始代码只需要进行一些更改。首先,我需要通过调用setPty(true)
来指定我想使用PTY而不是管道。然后,我需要模拟用户在输入密码后输入 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();