Home >Backend Development >PHP Tutorial >PHP non-blocking SSH client example_PHP tutorial

PHP non-blocking SSH client example_PHP tutorial

WBOY
WBOYOriginal
2016-07-13 10:47:401221browse

In my previous work, I had to deal with foreign servers. The delay and packet loss problems were sometimes so serious that they were intolerable. Entering a SQL statement was very laborious. I searched Google but couldn't find a non-blocking SSH client. PHP has SSH2 extension. In theory, a command-based SSH client can be implemented using standard input and output. This solves the inconvenience caused by network problems, so I developed a PHP Non-blocking SSH client

Value:

  • Based on commands, it solves the problem of network delay and packet loss to the greatest extent.
  • The test passed under windows and Linux.

Inadequacy:

  • No auto-complete function
  • No other functions such as sftp and scp
  • No color and bold
  • In some cases the display is not perfect
  • Because it is basically not used now, we will not improve it for the time being.

Linux running effect
PHP non-blocking SSH client example_PHP tutorial
Effect of running under windows
PHP non-blocking SSH client example_PHP tutorial
PHP non-blocking SSH client example_PHP tutorial
PHP non-blocking SSH client example_PHP tutorial

Because it is a class in the framework, some common functions (such as debug_print()) need to be provided by yourself, so I will not rewrite them here

The code is as follows Copy code

class FSSH{
private $conn;
private $shell;

 /**
* key=String password authentication, key=array('pub'=>,'pri'=>,'type'=>,'phrase'=>) key authentication
* There are two types of key authentication: ssh-rsa, ssh-dss
* $host[addr]=String address,$host['fp']=array() server fingerprint
​*/
 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();

复制代码
//$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();

http://www.bkjia.com/PHPjc/632846.htmlwww.bkjia.com
true
http://www.bkjia.com/PHPjc/632846.html
TechArticle之前工作中必须和国外服务器打交道,延迟和丢包问题有时候非常严重,已经到了不可忍受的地步,输入一条sql都是很费劲的事情。google搜...
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn