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

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

这几乎有效。这 -t -t 选项应该迫使他们几乎做的伪码头。我可以输入SSH密码,然后按Enter。但是,按下进入终端后似乎只是悬挂了。没有输出,没有什么都没有 - 好像SSH会话失败了。我无法运行命令或任何东西,必须使用CTRL+C杀死整个事物。我知道登录成功,因为我可以执行像 ssh -t -t -p 22 user@server.com "ls -la" 并获取正确的输出。

我认为问题必须与我在proc_open呼叫中使用标准管的事实有关,因此我用PTY替换了它们。我收到以下错误:“该系统不支持PTY PSEUDO终端……”

Mac OS X根本不支持PTY或伪终端吗? (我非常擅长使用所有这些壳术语)。

这是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;  
    }  
} 

(抱歉 - 我一生都无法确定格式的说明...)

我究竟做错了什么?为什么我不能使用PTY?这是Mac OS X上不可能的吗?谢谢你的帮助!

有帮助吗?

解决方案

您应该使用公共密钥身份验证,而不是试图绕过交互式密码身份验证。

密码提示应该是从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.

其他提示

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

这是旧的,但是对于任何谷歌搜索者来说,这是使用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连接。这通常用于阻碍坚持从控制终端阅读的程序。

你尝试过吗 PHP SSH2扩展?

你有没有尝试过 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:~$');
?>

我在使用SSH2扩展名的PHP上写了一个SSH客户端,您可以在GitHub页面上查看源代码 https://github.com/roke22/php-ssh2-web-client

请发送一些反馈。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top