php空间ssh,php非阻塞SSH客户端

之前工作中必须和国外服务器打交道,延迟和丢包问题有时候非常严重,已经到了不可忍受的地步,输入一条sql都是很费劲的事情。google搜了一遍没有找到非阻塞的ssh客户端,PHP有SSH2扩展,利用标准输入输出理论上可以实现一个基于命令行的SSH客户端,这样就解决了网络问题带来的不便,于是开发了一个PHP非阻塞SSH客户端。

价值:

基于命令,最大程度解决了网络延迟和丢包问题。

windows和Linux下测试通过。

不足:

没有自动补全功能

没有sftp和scp等其他功能

没有颜色和粗体显示

个别情况下显示上不是很完美

因为现在基本不用它了,所以暂时先不进行改进。

linux 运行效果

7416a26c7d5f2304231c94a90e8c3477.png

windows下运行效果

d24b04d362d4b6e425c8de1eb98fc074.png60992f379162928e213a056b9f14fed4.png0bc053d0e22e3e8f373c2a3d61f01945.png

因为是框架中的一个类,所以个别通用函数(比如debug_print())需要自己提供,我这里就不改写了。

class FSSH{

private $conn;

private $shell;

/**

* key=String 密码认证,key=array('pub'=>,'pri'=>,'type'=>,'phrase'=>)密钥认证

* 密钥认证type分为两种:ssh-rsa,ssh-dss

* $host[addr]=String 地址,$host['fp']=array() 服务器指纹

*/

function __construct($host,$user,$key){

if(empty($host['addr'])){

debug_print('Host cant't be empty',E_USER_ERROR);

}

if(empty($host['fp'])){

debug_print('finger print is not specified',E_USER_ERROR);

}

$this->stdin=fopen('php://stdin','r');

$this->stdout=fopen('php://stdout','w');

if(false!==strpos($host['addr'],':')){

$temp=explode(':',$host['addr']);

$host['addr']=$temp[0];

$port=$temp[1];

}else{

$port=22;

}

if(is_string($key) || empty($key['type'])){

$methods=null;

}else{

$methods=array('hostkey'=>$key['type']);

}

$conn=ssh2_connect($host['addr'],$port,$methods,array('disconnect'=>array($this,'disconnect')));

$fp=ssh2_fingerprint($conn,SSH2_FINGERPRINT_MD5);

$success=false;

$fpOK=false;

if(in_array($fp,$host['fp'])){

$fpOK=true;

}else{

fwrite($this->stdout,"$fpnIs fingerprint OK ?(y/n)");

$input=strtolower(stream_get_line($this->stdin,1));

if($input=='y'){

$fpOK=true;

}else{

$fpOK=false;

}

}

if($fpOK){

if(is_array($key)){

if (ssh2_auth_pubkey_file($conn,$user,$key['pub'],$key['pri'],$key['phrase'])){

$success=true;

}else{

debug_print('Public Key Authentication Failed',E_USER_ERROR);

}

}elseif(is_string($key)){

if(ssh2_auth_password($conn,$user,$key)){

$success=true;

}else{

debug_print('Password Authentication Failed',E_USER_ERROR);

}

}

}else{

debug_print('Fingerprint is invalid',E_USER_ERROR);

}

if($success){

$this->conn=$conn;

$this->shell=ssh2_shell($conn,null,null,1024);

}

return $success;

}

function shell(){

//最后一条命令

$last='';

//先结束shell,再结束while

$signalTerminate=false;

while(true){

$cmd=$this->fread($this->stdin);

$out=stream_get_contents($this->shell,1024);

if(!empty($out) and !empty($last)){

$l1=strlen($out);

$l2=strlen($last);

$l=$l1>$l2?$l2:$l1;

$last=substr($last,$l);

$out=substr($out,$l);

}

echo ltrim($out);

if($signalTerminate){

break;

}

if(in_array(trim($cmd),array('exit'))){

$signalTerminate=true;

}

if(!empty($cmd)){

$last=$cmd;

fwrite($this->shell,$cmd);

}

}

}

//解决windows命令行的读取问题,没有别的办法了。

private function fread($fd){

static $data='';

$read = array($fd);

$write = array();

$except = array();

$result = stream_select($read,$write,$except,0,1000);

if($result === false)

debug_print('stream_select failed',E_USER_ERROR);

if($result !== 0){

$c= stream_get_line($fd,1);

if($c!=chr(13))

$data.=$c;

if($c==chr(10)){

$t=$data;

$data='';

return $t;

}

}

}

function __destruct(){

fclose($this->stdin);

fclose($this->stdout);

$this->disconnect();

}

private function disconnect(){

if(is_resource($this->conn)){

unset($this->conn);

fclose($this->shell);

}

}

}

demo

//$ssh=new FSSH(array('addr'=>'x.x.x.x:22','fp'=>array('')),'tunnel',array('pub'=>'E:Identity.pub','pri'=>'E:Identity','type'=>'ssh-rsa'));

$ssh=new FSSH(array('addr'=>'192.168.2.205','fp'=>array('54ECC700B844DCF0D40554A56C57C01E')),'root','123456');

$ssh->shell();

较新版本,SSH2

linux 下ssh2扩展安装(需要epel和remi源)

yum install php-pecl-ssh2

源码安装:http://pecl.php.net/package/ssh2

windows pecl:http://downloads.php.net/pierre/

这里只有VC9版本,我之前保存了一个VC6版本,忘了从哪里找到的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值