-
php无阻塞SSH客户端实例
之前工作中必须和国外服务器打交道,延迟和丢包问题有时候非常严重,已经到了不可忍受的地步,输入一条sql都是很费劲的事情,google搜了一遍没有找到非阻塞的ssh客户端,PHP有SSH2扩展,利用标准输入输出理论上可以实现一个基于命令的SSH客户端,这样就解决了网络问题带来的不便,于是开发了一个PHP非阻塞SSH客户端.
价值:基于命令,最大程度解决了网络延迟和丢包问题,windows和Linux下测试通过.
不足:没有自动补全功能,没有sftp和scp等其他功能,没有颜色和粗体显示,个别情况下显示上不是很完美,因为现在基本不用它了,所以暂时先不进行改进.
因为是框架中的一个类,所以个别通用函数(比如debug_print())需要自己提供,我这里就不改写了,代码如下:
- <?php
- 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(emptyempty($host['addr'])){
- debug_print('Host cant't be emptyempty',E_USER_ERROR);
- }
- if(emptyempty($host['fp'])){
- debug_print('finger print is not specified',E_USER_ERROR);
- }//开源代码phpfensi.com
- $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) || emptyempty($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(!emptyempty($out) and !emptyempty($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(!emptyempty($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();
出处:http://www.phpfensi.com/php/20140825/4780.html
栏目列表
最新更新
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
Python初学者友好丨详解参数传递类型
如何有效管理爬虫流量?
SQL SERVER中递归
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
这是目前我见过最好的跨域解决方案!
减少回流与重绘
减少回流与重绘
如何使用KrpanoToolJS在浏览器切图
performance.now() 与 Date.now() 对比
一款纯 JS 实现的轻量化图片编辑器
关于开发 VS Code 插件遇到的 workbench.scm.
前端设计模式——观察者模式
前端设计模式——中介者模式
创建型-原型模式