7

ssh-addを使用して新しいキーを追加することにより、システムssh-agentを制御しようとしています。このために、私はSymfony Processコンポーネントを使用しています。

このコードを Web サイトから実行すると問題なく動作しますが、同じコードをシェル/コンソールで実行すると 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で を設定して、エージェントと通信できるようにし、入力でパスワードを送信します。前に言ったように、これを Web コンテキストで実行すると動作しますが、シェル/コンソール コンテキストではハングします。SSH_AUTH_SOCKssh-add

コンソールで実行するときにstraceof を実行しました。関連する部分は次のようになります

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プログラムは入力待ちのブロックを開始します。

4

1 に答える 1

8

ssh-add のソースを読み、PHP への PTY サポートの追加について語っているWez Furlong の非常に古い記事を読んだ後、最終的にこの問題の解決策を見つけました。

記事を引用するには:

これは、プロセスへのパイプを作成するのと似ていますが、代わりに、OS の /dev/ptmx インターフェイスを使用してマスター (スクリプト用) とスレーブ (実行中のプロセス用) の 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();
于 2014-11-25T18:38:42.907 に答える