这是我想要实现的目标:打开一个 shell(korn 或 bash,没关系),从那个 shell,我想打开一个 ssh 连接(ssh user@host
)。在某些时候,可能会提示我输入密码,或者可能会询问我是否确定要连接(有问题的键)。
在有人问之前:是的,我知道有一个用于 ssh2 exec 调用的插件,但是我正在使用的服务器不支持它,而且不太可能这样做。
这是我到目前为止所尝试的:
$desc = array(array('pipe','r'),array('pipe','w'));//used in all example code
$p = proc_open('ssh user@host',$desc,$pipes);
if(!is_resource($p)){ die('@!#$%');}//will omit this line from now on
sleep(1);//omitting this,too but it's there every time I need it
stream_get_contents($pipes[1])
然后我尝试读取控制台输出'connection failed: '.stream_get_contents($pipes[1])
(
这给了我以下错误:
不会分配伪终端,因为 stdin 不是终端。
所以,我虽然在 io-stream 上下文中调用了 ssh,但php://
似乎是对上述错误的合理解释。
下一步:我想到了我的第一个 SO 问题,并决定先打开一个 bash/ksh shell 可能是个好主意:
$p = proc_open('bash',$desc,$pipes);
从那里拿走它,但我得到了完全相同的错误消息,只是这一次,脚本停止运行,但 ssh 确实运行了。所以我充满希望,然后感到愚蠢,最终绝望:
$p=proc_open('bash && ssh user@host',$desc,$pipes);
等待几秒钟后,我收到以下错误:
PHP致命错误:允许的内存大小为134217728字节已用尽(试图分配133693440字节)
即使在我最后一次绝望的尝试中,调用堆栈也会不断调出 stream_get_contents 行:
#!/path/to/bin/php -n
<?php
$p = proc_open('bash && ssh user@host',array(array('pipe','r'),array('pipe','w')),$ps);
if (!is_resource($p))
{
die('FFS');
}
usleep(10);
fwrite($ps[0],'yes'."\n");
fflush($ps[0]);
usleep(20);
fwrite($ps[0],'password'."\n");
fflush($ps[0]);
usleep(20);
fwrite($ps[0],'whoami'."\n");
fflush($ps[0]);
usleep(2);
$msg = stream_get_contents($ps[1]);
fwrite($ps[0],'exit'."\n");
fclose($ps[0]);
fclose($ps[1]);
proc_close($p);
?>
我知道,它一团糟,有很多fflush
冗余,但重点是:我知道这个连接会首先提示我输入违规密钥,然后询问密码。我的猜测是 $pipes[1] 中的流包含 ssh 连接,因此它的内容很大。那么我需要的是管道内的管道......这甚至可能吗?我一定遗漏了一些东西,如果这是不可能的,那么管道有什么好处......我的猜测是 proc_open 命令一开始是错误的,(错误:管道损坏)。但我真的看不到第一个错误的任何其他方式......有什么想法吗?或者如果上述咆哮根本不清楚(可能不是),请跟进问题。