这是我想要实现的:打开一个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])
和proc_close $ p。
这给了我以下错误:
由于stdin不是终端,因此不会分配伪终端。
所以,我虽然在php://
io-stream上下文中调用了ssh,但似乎是对上述错误的合理解释。
下一篇:我虽然关于my first SO question并且认为首先打开一个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命令开头是错误的,(错误:断管)。但我真的看不到任何其他方式绕过第一个错误...任何想法?如果上述咆哮根本不清楚(可能不是),请跟进问题。
答案 0 :(得分:1)
实际上有两个。 PECL模块,它是大多数服务器尚未安装的PITA和phpseclib, a pure PHP SSH2 implementation。使用它的一个例子:在有人问之前:是的,我知道有一个ssh2 exec的插件 调用,但我正在处理的服务器不支持它,并且是 不太可能这样做。
<?php
include('Net/SSH2.php');
$ssh = new Net_SSH2('www.domain.tld');
if (!$ssh->login('username', 'password')) {
exit('Login Failed');
}
echo $ssh->exec('pwd');
echo $ssh->exec('ls -la');
?>