PHP+Swoole实现web版的shell客户端详解

本来是想通过PHP的proc_open和进程进行交互,可是中间的坑太多了,不得不转换一下思路,然后想起来宝塔有网页版shell客户端,然后研究了一下,嘿嘿,发现能成 。

一、前期准备

PHP连接ssh是基于第三方拓展库,PECL/ssh2( libssh2的php扩展,允许php程序调用libssh2中的函数)

然后有一个现成的、封装好大部分常用操作的库phpseclib

通过swoole的协程实现SSH的读和写并发进行以及websocket和浏览器进行通信。

1、安装ssh2拓展库

1.1、Linux安装

首先要安装libssh2(libssh2是一个C 函数库,用来实现SSH2协议。)

yum install libssh2 libssh2-devel 

然后通过pcel安装ssh2拓展 ,找准版本

pecl install ssh2-1.1.2

当然也可以通过phpize进行手动安装。

1.2、window安装

libssh2好像一般都有,没有就下载丢到系统里,主要是安装ssh2。根据自己PHP的版本去下载,可以看下自己的php版本,以及是32位的还是64位的,32位的下载x86, 64位的下载x64

下载地址

php.ini中加入 extension=php_ssh2.dll ,完事。

2、swoole安装

参考官网:https://wiki.swoole.com/#/environment

3、phpseclib

官网:https://phpseclib.com,composer安装即可:

composer require phpseclib/phpseclib:~3.0

二、编写代码

测试Demo:http://cname.teiao.com:5707/

通过swoole创建一个websocket,连接成功时创建一个协程专门读取ssh返回的内容发送到websocket,客户端发送消息时转发给shell。

以下是简单的功能实现,不可应用于生产,经测试,实际使用过程中某些命令的输出需要进行特殊处理。

1、swoole.php

-1, //tcp超时
    'hook_flags' => SWOOLE_HOOK_ALL  //HOOK函数范围
]);


/*
 * 创建协程容器
 * */
run(function () {

    /*
     * 第三个参数 代表是否开启ssl
     * */
    $server = new Server('0.0.0.0', 5707, false);

    $server->handle('/ws', function (Request $request, Response $ws) {

        /*websocket协议*/
        $ws->upgrade();

        /*连接ssh*/
        $ssh = new SSH2('localhost',22);

        /*如果登录失败*/
        if (!$ssh->login('root', 'Qq461625091@')) {
            $ws->close();
            return;
        }

        /*命令输出内容的读取时间*/
        $ssh->setTimeout(0.1);



        /*
         * 创建协程,专门输出命令行内容
         * */
        $subscribe=function () use($ws,$ssh){


            /*
             * 保存id,用于取消协程
             * */
            $ws->Gid = go(function () use ($ws,$ssh){

                /*
                 * 协程退出时清理
                 * */
                defer(function () use ($ssh,$ws) {
                    /*
                     * 退出
                     * */
                    logs($ws->qq.',已断开链接!');
                    $ssh->disconnect();
                });


                try {

                    while (true){
                        $msg=$ssh->read('username@username:~$');
                        if(!empty($msg)){
                            $ws->push($msg);
                        }
                    }

                } catch (\Throwable $e) {
                    logs('读取异常');
                }

            });
        };


        /*
         * 清理
         * */
        $quit=function ($log) use ($ws){

            logs($log);//记录退出原因

            /*
             * 如果协程已经运行
             * */
            if(isset($ws->Gid)){
                Coroutine::cancel($ws->Gid); //关闭协程
            }

            $ws->close(); //断开ws

        };


        /*
         * 正常处理逻辑
         * */

        $subscribe(); //开始订阅

        $cmd=[
            'ps -ef',
            'ping 127.0.0.1',
            'ifconfig',
            "\x03"
        ];


        while (true) {

            $frame = $ws->recv(); //阻塞接收消息

            if ($frame === '') {

                $quit("断开连接,收到空数据!");
                break;

            } else if ($frame === false) {

                $quit(swoole_last_error());
                break;

            } else {

                if ($frame->data == 'close' || get_class($frame) === CloseFrame::class) {
                    $quit("用户主动关闭\n");
                    break;
                }

                /*
                  * 如果不在测试命令,则终止
                  * */
                if(!in_array($frame->data,$cmd)){
                    continue;
                }

                $ssh->write($frame->data."\n"); // note the "\n"

            }
        }
    });


    /*
     * 输出默认测试模板
     * */
    $server->handle('/', function (Request $request, Response $response) {
        $response->end(getTest());
    });

    $server->start();
});

2、function.php


        
        
            
            
            
            Web SSH客户端
            
            
            
            
        
        
        

Web SSH测试

须知:测试环境只支持:ps -ef、ping 127.0.0.1、ifconfig,三个命令。
提示:回车提交、ctrl+c中断(终端现在连接的是网站的主机)

HTML; return $test; } /* * 记录日志 * */ function logs(string $log, bool $flag = true): void { $time = date("Y-m-d H:i:s", time()); if ($flag) { echo $time . ',' . $log . "\n"; } else { file_put_contents('log.txt', $time . ',' . $log . "\n", FILE_APPEND); } }

3、运行

php swoole.php

以上就是PHP+Swoole实现web版的shell客户端详解的详细内容,更多关于PHP Swoole shell客户端的资料请关注脚本之家其它相关文章!

你可能感兴趣的:(PHP+Swoole实现web版的shell客户端详解)