3

我正在尝试通过 Mac OS X 10.6 上的命令行使用 PHP 建立与远程服务器的交互式 SSH 连接。我目前正在使用 PHP 的 proc_open 函数来执行以下命令:

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

这几乎可以工作。这些-t -t选项应该强制一个他们几乎做的伪终端。我可以输入 SSH 密码并按回车键。但是,按下回车后,终端似乎只是挂起。没有输出,什么都没有——就好像 SSH 会话失败了。我无法运行命令或任何东西,必须使用 Ctrl+C 杀死整个事情。我知道登录成功,因为我可以执行类似的命令ssh -t -t -p 22 user@server.com "ls -la"并获得正确的输出。

我认为问题一定与我在 proc_open 调用中使用标准管道这一事实有关,因此我将它们替换为 pty。我收到以下错误:“此系统不支持 pty 伪终端...”

Mac OS X 是否根本不支持 pty 或伪终端?(我对使用所有这些 shell 术语很陌生)。

这是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 上是不可能的吗?谢谢你的帮助!

4

6 回答 6

5

您应该使用公钥身份验证,而不是尝试以编程方式绕过交互式密码身份验证。

密码提示应该从 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(Linux 的 PuTTY 的一部分)而不是 OpenSSH,因为它可以在命令行上获取密码plink -pw password example.com但是这样做会带来安全风险,因为在服务器上运行的任何人都ps aux可以在进程列表中看到密码。

还有一个名为的程序sshpass从环境变量或命令参数中获取密码并将其传递给ssh.

于 2010-11-05T08:07:38.467 回答
4

看起来问题最好使用 PHP 的 passthru() 函数来解决。经过更多(相当痛苦)的研究后,我能够通过此功能发出命令,并可以通过终端与远程服务器进行交互,就像我手动运行 ssh 和 svn export 一样(它们都需要密码,因此是很好的测试) . 我要做的是构造一个(可能很长)命令字符串,由分隔&&并将它们附加到 ssh 命令的末尾:ssh -t -t -p 22 hostname command1 && command2 ... 即使命令正在远程服务器上执行,输出也会发送到我在 Mac OS X 中的终端。看起来这是我一直在寻找的解决方案 - 真的很简单!感谢所有帮助我的人。我给 Alexandre 打了“绿色复选标记”,因为他是唯一一个一直在回答的人,并且在推断问题的最终答案方面非常有帮助。谢谢亚历山大!

于 2010-11-06T23:10:25.777 回答
3

这是旧的,但对于任何谷歌用户来说,这里是一个使用 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])

关于来自 python 文档的 pty.spawn:

生成一个进程,并将其控制终端与当前进程的标准 io 连接。这通常用于阻碍坚持从控制终端读取的程序。

于 2015-08-06T07:23:34.153 回答
1

您是否尝试过PHP SSH2 扩展

于 2010-11-05T09:26:05.713 回答
1

你试过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:~$');
?>
于 2012-10-18T19:13:55.903 回答
0

我在 php 上写了一个带有 ssh2 扩展名的 ssh 客户端,你可以看一下 github 页面上的源代码https://github.com/roke22/PHP-SSH2-Web-Client

请发送一些反馈。

于 2018-07-20T19:49:45.280 回答