xterm.js 组件实现WebSSH功能

JavaScript/前端
493
0
0
2023-02-13
标签   SSH

本次实验将使用Django 3.0 配合 dwebsocket websocket组件,实现一个网页版的SSH命令行工具,其支持 vim , 支持 ping等交互命令,唯一的一个小缺点是略卡,不知道是我电脑问题还是这个socket框架不稳定呢。

解决方案了 https://github.com/huashengdun/webssh

基本用法

<html>
<head>
  <link rel="stylesheet" href="https://www.blib.cn/cdn/xterm.css" />
  <script src="https://www.blib.cn/cdn/xterm.js"></script>
    <script src="https://www.blib.cn/cdn/jquery.js"></script>
</head>
<body>
  <div id="terminal"></div>
  <script type="text/javascript">
      var window_width = $(window).width();
      var window_height = $(window).height();
      var term = new Terminal(
            {
                cols: Math.floor(window_width/9),
                rows: Math.floor(window_height/20),
                useStyle:true,
                cursorBlink:true
            }
    );
    term.open(document.getElementById('terminal'));
    term.write('Hello lyshark \x1B[1;3;31mxterm.js\x1B[0m $ ')
  </script>
</body>
</html>

命令执行

<html>
<head>
  <link rel="stylesheet" href="https://www.blib.cn/cdn/xterm.css" />
  <script src="https://www.blib.cn/cdn/xterm.js"></script>
    <script src="https://www.blib.cn/cdn/jquery.js"></script>
</head>
<body>
<input type="button" value="执行命令" onclick="show()">
  <div id="terminal"></div>
  <script type="text/javascript">
      var window_width = $(window).width();
      var window_height = $(window).height();
      var term = new Terminal(
            {
                cols: Math.floor(window_width/9),
                rows: Math.floor(window_height/20),
                useStyle:false,
                cursorBlink:false
            }
    );
    term.open(document.getElementById('terminal'));
      function show(){
          $.ajax({
              url:"/term/",
              type:"POST",
              contentType:"application/json;",
              data: "ok",
              success:function (res) {
                  var data = JSON.parse(res);
                  console.log(data["cmd"]);
                  term.writeln(data["cmd"]);
              }
          });
      }
  </script>
</body>
</html>
from django.shortcuts import render,HttpResponse
import subprocess,json

def term(request):
    if request.method == "POST":
        data = request.body.decode("utf-8")
        if data == "ok":
            proc = subprocess.Popen("ipconfig",stdout=subprocess.PIPE,shell=True)
            cc = str(proc.stdout.readlines())
            return HttpResponse(json.dumps({"cmd":cc}))
    return render(request, "index.html")

img

光标问题已经解决了,找了很久的,操蛋啊。

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <link rel="stylesheet" href="https://www.blib.cn/cdn/xterm.css" />
  <script src="https://www.blib.cn/cdn/xterm.js"></script>
    <script src="https://www.blib.cn/cdn/jquery.js"></script>
</head>
<body>
<input type="button" value="执行命令" onclick="show()">
  <div id="terminal"></div>
  <script type="text/javascript">
      var window_width = $(window).width();
      var window_height = $(window).height();
      var term = new Terminal(
            {
                cols: Math.floor(window_width/9),
                rows: Math.floor(window_height/20),
                useStyle:false,
                convertEol: true,
                cursorBlink:false,
                rendererType: "canvas",
                theme:{
                    foreground: 'yellow',
                    background: 'rgba(6,1,1,0.55)',
                }
            }
    );
    term.open(document.getElementById('terminal'));
      function show(){
          $.ajax({
              url:"/term/",
              type:"POST",
              contentType:"application/json;",
              data: "ok",
              success:function (res) {
                      term.writeln(res);
              }
          });
      }
  </script>
</body>
</html>
from django.shortcuts import render,HttpResponse
import paramiko

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

def ssh_cmd(user,passwd,port,cmd):
    ssh.connect("192.168.1.20",port=port,username=user,password=passwd)
    cmd=cmd
    stdin, stdout, stderr = ssh.exec_command(cmd)
    result = stdout.read()
    if not result:
        result=stderr.read()
    ssh.close()
    return result.decode()

def term(request):
    if request.method == "POST":
        data = request.body.decode("utf-8")
        if data == "ok":
            a = ssh_cmd("root","123","22","ifconfig")
            return HttpResponse(a)
    return render(request, "index.html")

img

来我们继续,加上边框,进行定制。

{% extends "admin/base_site.html" %}
{% load i18n static %}

{% block content %}
    <link rel="stylesheet" href="https://www.blib.cn/cdn/xterm.css" />
    <link rel="stylesheet" href="https://www.blib.cn/cdn/bootstrap3.css" />
    <script src="https://www.blib.cn/cdn/xterm.js"></script>
    <script src="https://www.blib.cn/cdn/jquery.js"></script>

    <div class="panel panel-primary">
        <div class="panel-heading">
            <h3 class="panel-title">批量命令执行CMD工具</h3>
        </div>
        <div class="panel-body">
              <div id="terminal"></div>
        </div>
        <div class="panel-footer">
            <input type="button" value="执行命令" onclick="show()">
        </div>
    </div>

    <script type="text/javascript">
      var window_width = $(window).width()-200;
      var window_height = $(window).height()-200;
      var term = new Terminal(
            {
                cols: Math.floor(window_width/9),
                rows: Math.floor(window_height/20),
                useStyle:false,
                convertEol: true,
                cursorBlink:false,
                rendererType: "canvas",
            }
    );
    term.open(document.getElementById('terminal'));
      function show(){
          $.ajax({
              url:"/term/",
              type:"POST",
              contentType:"application/json;",
              data: "ok",
              success:function (res) {
                  //term.clear();
                  term.writeln(res);
              }
          });
      }
    </script>
{% endblock %}
from django.shortcuts import render,HttpResponse
import paramiko

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

def ssh_shell(address,username,password,port,command):
    ssh.connect(address,port=port,username=username,password=password)
    stdin, stdout, stderr = ssh.exec_command(command)
    result = stdout.read()
    if not result:
        result=stderr.read()
    ssh.close()
    return result.decode()


def term(request):
    if request.method == "POST":
        data = request.body.decode("utf-8")
        if data == "ok":
            a = ssh_shell("192.168.1.20","root","123","22","yum")
            print(a)
            return HttpResponse(a)
    return render(request, "index.html")

img

继续改造啊,先玩着,后期上websocket.

views.py
from django.shortcuts import render,HttpResponse
import paramiko,json,time

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

def ssh_shell(address,username,password,port,command):
    try:
        ssh.connect(address,port=port,username=username,password=password)
        stdin, stdout, stderr = ssh.exec_command(command)
        result = stdout.read()
        if not result:
            result=stderr.read()
        ssh.close()
        return result.decode()
    except Exception:
        ssh.close()
def term(request):
    if request.method == "POST":
        data = request.body.decode("utf-8")
        json_data = json.loads(data)
        address = json_data.get("address")
        command = json_data.get("command")
        if len(address) >=2 and len(command) >=2:
            ret = ssh_shell(address,"root","123","22",command)
            if ret !=None:
                times = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
                times = "---> \x1B[1;3;32m 执行时间: [ {} ] \x1B[0m".format(times)
                address = "\x1B[1;3;33m 主机地址: [ {} ] \x1B[0m".format(address)
                command = "\x1B[1;3;35m 执行命令: [ {} ] \x1B[0m".format(command)
                retn = times + address + command + "\x1B[1;3;25m 回执: [ok] \x1B[0m"
                return HttpResponse(retn)
            else:
                times = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
                times = "---> \x1B[1;3;32m 执行时间: [ {} ] \x1B[0m".format(times)
                address = "\x1B[1;3;33m 主机地址: [ {} ] \x1B[0m".format(address)
                command = "\x1B[1;3;35m 执行命令: [ {} ] \x1B[0m".format(command)
                retn = times + address + command + "\x1B[1;3;20m 回执: [Error] \x1B[0m"
                return HttpResponse(retn)
        else:
            return HttpResponse("主机地址或命令行不能为空...")
    return render(request, "index.html")
{% extends "admin/base_site.html" %}
{% load i18n static %}
{% block content %}
    <link rel="stylesheet" href="https://www.blib.cn/cdn/xterm.css" />
    <link rel="stylesheet" href="https://www.blib.cn/cdn/bootstrap3.css" />
    <script src="https://www.blib.cn/cdn/xterm.js"></script>
    <script src="https://www.blib.cn/cdn/jquery.js"></script>

    <div class="panel panel-primary">
        <div class="panel-heading">
            <h3 class="panel-title">批量命令执行CMD工具</h3>
        </div>
        <div class="panel-body">
              <div id="terminal"></div>
        </div>
        <div class="panel-footer">
            <input type="text" id="address" placeholder="主机范围" style="width:200px;height:40px"/>
            <input type="text" id="command" placeholder="执行命令" style="width:400px;height:40px"/>
            <input type="button" value="执行命令" onclick="show()">
        </div>
    </div>
    <script type="text/javascript">
      var window_width = $(window).width()-200;
      var window_height = $(window).height()-300;
      var term = new Terminal(
            {
                cols: Math.floor(window_width/9),
                rows: Math.floor(window_height/20),
                useStyle:false,
                convertEol: true,
                cursorBlink:true,
                cursorStyle:null,
                rendererType: "canvas",
            }
    );
    term.open(document.getElementById('terminal'));
      function show(){
          var address = $("#address").val();
          var command = $("#command").val();
          console.log(command);
          $.ajax({
              url:"/term/",
              type:"POST",
              contentType:"application/json;",
              data: JSON.stringify({"address":address,"command":command}),
              success:function (res) {
                  term.writeln(res);
              }
          });
      }
    </script>
{% endblock %}
from MyWeb import views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('term/',views.term)
]

img

Dwebsocket

网上找到一个老版本的,改造了一下 可以支持 django 3.0 。

index.html

<html>
<head>
    <title>django-websocket</title>
    <script src="https://www.blib.cn/cdn/jquery.js"></script>
    <script type="text/javascript">
        $(function () {
            $('#connect_websocket').click(function () {
                if(window.s){
                    // 如果已经连接了,就关闭,重新连接
                    window.s.close()
                }
                var s = new WebSocket("ws://" + window.location.host + "/echo/");
                s.onopen = function () {
                    console.log('WebSocket open');
                };
                s.onmessage = function (e) {
                    console.log('message: ' + e.data);
                };
                s.onclose = function (e) {
                    console.log('WebSocket close');
                };
                // 把s挂到全局
                window.s = s;
            });

            $('#send_message').click(function () {
                if(!window.s){
                    alert("Please connect server.");
                }else{
                    window.s.send($('#message').val());
                }
            });

            $('#close_websocket').click(function () {
                if(window.s){
                    window.s.close();

                }
            });

        });
    </script>
</head>

<body>
<input type="text" id="message" value="Hello, World!" />
<button type="button" id="connect_websocket">Connect websocket</button>
<button type="button" id="send_message">Send message</button>
<button type="button" id="close_websocket">Close websocket</button>
<h1>Received Messages</h1>
<div id="messagecontainer"></div>
</body>
</html>

views.py

from django.shortcuts import render,HttpResponse
from dwebsocket.decorators import accept_websocket,require_websocket

def index(request):
    return render(request,"index.html")

@accept_websocket
def echo(request):
    if not request.is_websocket():#判断是不是websocket连接
        try:#如果是普通的http方法
            message = request.GET['message']
            return HttpResponse(message)
        except:
            return render(request,'index.html')
    else:
        for message in request.websocket:
            request.websocket.send(message)#发送消息到客户端
from MyWeb import views

urlpatterns = [
    path('', views.index),
    path('echo/', views.echo),
]

页面加载后自动连接

<html>
<head>
    <script src="https://www.blib.cn/cdn/jquery.js"></script>
    <script type="text/javascript">
        $(function () {
            if(window.s){
                window.s.close()
            }else{
                var s = new WebSocket("ws://" + window.location.host + "/echo/");
            }
            s.onmessage = function (e) {
                console.log('message: ' + e.data);
            };
            // 把s挂到全局
            window.s = s;

            $('#send_message').click(function () {
                    window.s.send("hello lyshark");
            });
        });
    </script>
</head>
<body>
<button type="button" id="send_message">Send message</button>
</body>
</html>

img

<html>
<head>
    <link rel="stylesheet" href="https://www.blib.cn/cdn/xterm.css" />
    <link rel="stylesheet" href="https://www.blib.cn/cdn/bootstrap3.css" />
    <script src="https://www.blib.cn/cdn/xterm.js"></script>
    <script src="https://www.blib.cn/cdn/jquery.js"></script>
    <div id="terminal"></div>
    <script>
      var window_width = $(window).width();
      var window_height = $(window).height();
      var term = new Terminal(
            {
                cols: Math.floor(window_width/9),
                rows: Math.floor(window_height/20),
                useStyle:false,
                convertEol: true,
                cursorBlink:false,
                cursorStyle:null,
                rendererType: "canvas",
            }
    );
    </script>
    <script type="text/javascript">
       $(function () {
           var sock = new WebSocket("ws://" + window.location.host + "/echo/");
           // 打开 websocket 打开 web 终端
            sock.addEventListener("open",function () {
                term.open(document.getElementById('terminal'));
                term.writeln("socket init ok...");
            });
            // 读取服务器发来的数据
            sock.addEventListener("message",function (recv) {
                term.write(recv.data);
            });

            var message = {"status":null,"data":null};
            term.on("data",function(data){
                message['status'] = 0;
                message['data'] = data;
                var send_data = JSON.stringify(message);
                window.sock.send(send_data);
                console.log(send_data);
                
            });
            window.sock = sock;
        });
</script>
</head>
<body>
<button type="button" id="send_message">Send message</button>
</body>
</html>
from django.shortcuts import render,HttpResponse
from dwebsocket.decorators import accept_websocket
import paramiko

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

def ssh_cmd(user,passwd,port,cmd):
    ssh.connect("192.168.1.20",port=port,username=user,password=passwd)
    cmd=cmd
    stdin, stdout, stderr = ssh.exec_command(cmd)
    result = stdout.read()
    if not result:
        result=stderr.read()
    ssh.close()
    return result.decode()


def index(request):
    return render(request,"index.html")

@accept_websocket
def echo(request):
    if not request.is_websocket():#判断是不是websocket连接
        try:
            message = request.GET['message']
            a = ssh_cmd("root","123","22","ls -lh")
            print(a)
            return HttpResponse(a)
        except:
            return render(request,'index.html')
    else:
        for message in request.websocket:
            request.websocket.send(message)#发送消息到客户端

img

继续尝试,ssh隧道怎末开?

<html>
<head>
    <link rel="stylesheet" href="https://www.blib.cn/cdn/xterm.css" />
    <link rel="stylesheet" href="https://www.blib.cn/cdn/bootstrap3.css" />
    <script src="https://www.blib.cn/cdn/xterm.js"></script>
    <script src="https://www.blib.cn/cdn/jquery.js"></script>
    <div id="terminal"></div>
    <script>
      var window_width = $(window).width();
      var window_height = $(window).height();
      var term = new Terminal(
            {
                cols: Math.floor(window_width/9),
                rows: Math.floor(window_height/20),
                useStyle:false,
                convertEol: true,
                cursorBlink:false,
                cursorStyle:null,
                rendererType: "canvas",
            }
    );
    </script>
    <script type="text/javascript">
       $(function () {
           var sock = new WebSocket("ws://" + window.location.host + "/echo/");
           // 打开 websocket 打开 web 终端
            sock.addEventListener("open",function () {
                term.open(document.getElementById('terminal'));
                term.writeln("socket init ok...");
            });
            // 读取服务器发来的数据
            sock.addEventListener("message",function (recv) {
                term.write(recv.data);
            });

            var message ="";
            term.on("data",function(data){
                console.log(message);
                if(data == "\r")
                {
                    term.writeln(message);
                    window.sock.send(message);
                    message = "";

                }else
                {
                    message = message +data;
                    term.write(data);
                }
            });
            window.sock = sock;
        });
</script>
</head>
</html>
from django.shortcuts import render,HttpResponse
from dwebsocket.decorators import accept_websocket
import paramiko

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

def ssh_cmd():
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    client.connect("192.168.1.20", username="root", password="123")
    ssh_session = client.get_transport().open_session()
    return ssh_session

@accept_websocket
def echo(request):
    sessions = ssh_cmd()
    if not request.is_websocket():
        return render(request,'index.html')
    else:
        for message in request.websocket:
            sessions.exec_command(message)
            ret = sessions.recv(2048)
            request.websocket.send(ret)

img

简单的隧道。

import paramiko

tran = paramiko.Transport(('192.168.1.20', 22,))
tran.start_client()
tran.auth_password('root', '123')
chan = tran.open_session()
chan.get_pty()
chan.invoke_shell()

while True:
    a = chan.recv(1024)
    print(a)
    chan.send('ls -lh\r')
<html>
<head>
    <link rel="stylesheet" href="https://www.blib.cn/cdn/xterm.css" />
    <link rel="stylesheet" href="https://www.blib.cn/cdn/bootstrap3.css" />
    <script src="https://www.blib.cn/cdn/xterm.js"></script>
    <script src="https://www.blib.cn/cdn/jquery.js"></script>
    <div id="terminal"></div>
    <script>
      var window_width = $(window).width();
      var window_height = $(window).height();
      var term = new Terminal(
            {
                cols: Math.floor(window_width/9),
                rows: Math.floor(window_height/20),
                useStyle:false,
                convertEol: true,
                cursorBlink:false,
                cursorStyle:null,
                rendererType: "canvas",
            }
    );
    </script>
    <script type="text/javascript">
       $(function () {
           var sock = new WebSocket("ws://" + window.location.host + "/echo/");
           // 打开 websocket 打开 web 终端
            sock.addEventListener("open",function () {
                term.open(document.getElementById('terminal'));
                term.writeln("socket init ok...");
            });
            // 读取服务器发来的数据
            sock.addEventListener("message",function (recv) {
                term.write(recv.data);
            });

            term.on("data",function(data){
                    term.write(data);
                    window.sock.send(data);
            });
            window.sock = sock;
        });
</script>
</head>
</html>
from django.shortcuts import render,HttpResponse
from dwebsocket.decorators import accept_websocket
import paramiko

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

def ssh_cmd():
    tran = paramiko.Transport(('192.168.1.20', 22,))
    tran.start_client()
    tran.auth_password('root', '123')
    chan = tran.open_session()
    chan.get_pty()
    chan.invoke_shell()
    return chan

@accept_websocket
def echo(request):
    sessions = ssh_cmd()
    if not request.is_websocket():
        return render(request,'index.html')
    else:
        for message in request.websocket:
            while True:
                ret = sessions.recv(2048)
                request.websocket.send(ret)

完成了 webssh 代码还不太稳定,完善后放出来。

img

img

img

img

代码,其实比想象中的简单得多,我尝试了很久。

<html>
<head>
    <link rel="stylesheet" href="https://www.blib.cn/cdn/xterm.css" />
    <link rel="stylesheet" href="https://www.blib.cn/cdn/bootstrap3.css" />
    <script src="https://www.blib.cn/cdn/xterm.js"></script>
    <script src="https://www.blib.cn/cdn/jquery.js"></script>
    <div id="terminal"></div>
    <script>
      var window_width = $(window).width();
      var window_height = $(window).height();
      var term = new Terminal(
            {
                cols: Math.floor(window_width/9),
                rows: Math.floor(window_height/20),
                useStyle:false,
                convertEol: true,
                cursorBlink:true,
                cursorStyle:null,
            });
        console.log("高度" + window_height + "宽度" + window_width);
        var sock = new WebSocket("ws://" + window.location.host + "/echo/");
        sock.addEventListener("open",function () {
            term.open(document.getElementById('terminal'));
        });
        sock.addEventListener("message",function (recv) {
            term.write(recv.data);
        });
        term.on("data",function(data){
            sock.send(data);
        });
        window.sock = sock;
</script>
</head>
</html>
from django.shortcuts import render,HttpResponse
from dwebsocket.decorators import accept_websocket
import paramiko

def ssh_cmd():
    tran = paramiko.Transport(('192.168.1.20', 22,))
    tran.start_client()
    tran.auth_password('root', '123')
    chan = tran.open_session()
    chan.get_pty(height=492,width=1312)
    chan.invoke_shell()
    return chan
sessions = ssh_cmd()

@accept_websocket
def echo(request):
    if not request.is_websocket():
        return render(request,'index.html')
    else:
        try:
            for message in request.websocket:
                ret = sessions.recv(10240)
                request.websocket.send(ret)
                sessions.send(message)
        except Exception:
            print("error")

最后加一个在线编辑器代码。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="https://www.blib.cn/cdn/codemirror/codemirror.css"/>
    <script src="https://www.blib.cn/cdn/codemirror/codemirror.js"></script>
</head>
<body>
<textarea class="form-control" id="code" name="code"></textarea>
    <script type="text/javascript" charset="utf-8">
        var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
            mode: "groovy",       // 设置高亮类型
            theme: "neat",        // 设置主题
            lineNumbers: true,	  // 显示行号
            foldGutter: true,
            gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
    });
        editor.setSize('500px', '400px');    // 设置框架大小
        editor.setValue("hello lyshark");    // 给代码框赋值
        editor.getValue();                   // 获取代码框的值
    </script>
</body>
</html>

dwebsocket 最终代码: 通过使用dwebsocket插件实现一个简单的WebSSH命令行工具.

<!--name: index.html-->
<html>
<head>
    <link rel="stylesheet" href="https://www.blib.cn/cdn/xterm.css" />
    <link rel="stylesheet" href="https://www.blib.cn/cdn/bootstrap3.css" />
    <script src="https://www.blib.cn/cdn/xterm.js"></script>
    <script src="https://www.blib.cn/cdn/jquery.js"></script>
    <div id="terminal"></div>
    <script>
      var window_width = $(window).width();
      var window_height = $(window).height();
      var term = new Terminal(
            {
                cols: Math.floor(window_width/9),
                rows: Math.floor(window_height/20),
                useStyle:false,
                convertEol: true,
                cursorBlink:true,
                cursorStyle:null,
            });
        console.log("高度" + window_height + "宽度" + window_width);
        var sock = new WebSocket("ws://" + window.location.host + "/echo/");
        sock.addEventListener("open",function () {
            term.open(document.getElementById('terminal'));
        });
        sock.addEventListener("message",function (recv) {
            term.write(recv.data);
        });
        term.on("data",function(data){
            sock.send(data);
        });
        window.sock = sock;
</script>
</head>
</html>
# name: views.py
from django.shortcuts import render,HttpResponse
from dwebsocket.decorators import accept_websocket
import paramiko

def ssh_cmd():
    tran = paramiko.Transport(('192.168.1.20', 22,))
    tran.start_client()
    tran.auth_password('root', '123')
    chan = tran.open_session()
    chan.get_pty(height=492,width=1312)
    chan.invoke_shell()
    return chan
sessions = ssh_cmd()

@accept_websocket
def echo(request):
    if not request.is_websocket():
        return render(request,'index.html')
    else:
        try:
            for message in request.websocket:
                ret = sessions.recv(4096)
                request.websocket.send(ret)
                sessions.send(message)
        except Exception:
            print("error")
from MyWeb import views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('echo/',views.echo)
]

批量CMD执行工具: 利用DjangoAdmin与Socket通信实现的主机批量执行并回显.

<!--name:index.html-->
{% extends "admin/base_site.html" %}
{% load i18n static %}
{% block content %}
    <link rel="stylesheet" href="https://www.blib.cn/cdn/xterm.css" />
    <link rel="stylesheet" href="https://www.blib.cn/cdn/bootstrap3.css" />
    <script src="https://www.blib.cn/cdn/xterm.js"></script>
    <script src="https://www.blib.cn/cdn/jquery.js"></script>
    <div class="panel panel-primary">
        <div class="panel-heading">
            <h3 class="panel-title">批量命令执行CMD工具</h3>
        </div>
        <div class="panel-body">
              <div id="terminal"></div>
        </div>
        <div class="panel-footer">
            <input type="text" id="address" placeholder="主机范围 127.0.0.1-100" style="width:200px;height:40px"/>
            <input type="text" id="command" placeholder="执行命令 ls -lh " style="width:400px;height:40px"/>
            <input type="button" id="send_message" value="批量执行">
        </div>
    </div>
    <script type="text/javascript">
        $(function(){
            var window_width = $(window).width()-200;
            var window_height = $(window).height()-300;
            var term = new Terminal(
            {
                cols: Math.floor(window_width/9),
                rows: Math.floor(window_height/20),
                convertEol: true,
                cursorBlink:false,
            });
            var sock = new WebSocket("ws://" + window.location.host + "/echo/");
            sock.onopen = function () {
                term.open(document.getElementById('terminal'));
                console.log('WebSocket Open');
            };
            sock.onmessage = function (recv) {
                if(recv.data.substring(0,7) == "[Suces]"){
                    term.writeln("\x1B[1;3;32m " + recv.data + "\x1B[0m");
                }else{
                    term.writeln("\x1B[1;3;31m " + recv.data + "\x1B[0m");
                }

            };
            $('#send_message').click(function () {
                var message ={"address":null,"command":null};
                message['address'] = $("#address").val();
                message['command'] = $("#command").val();
                var send_data = JSON.stringify(message);
                window.sock.send(send_data);
            });
            window.sock = sock;
        });
    </script>
{% endblock %}
# name:views.py
from django.shortcuts import render
from dwebsocket.decorators import accept_websocket
import paramiko,time

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

def ssh_shell(address,username,password,port,command):
    try:
        ssh.connect(address,port=port,username=username,password=password,timeout=1)
        stdin, stdout, stderr = ssh.exec_command(command)
        result = stdout.read()
        if not result:
            result=stderr.read()
        ssh.close()
        return result.decode()
    except Exception:
        return 0

def CalculationIP(Addr_Count):
    ret = []
    try:
        IP_Start = str(Addr_Count.split("-")[0]).split(".")
        IP_Heads = str(IP_Start[0] + "." + IP_Start[1] + "." + IP_Start[2] +".")
        IP_Start_Range = int(Addr_Count.split(".")[3].split("-")[0])
        IP_End_Range = int(Addr_Count.split("-")[1])
        for item in range(IP_Start_Range,IP_End_Range+1):
            ret.append(IP_Heads+str(item))
        return ret
    except Exception:
        return 0

@accept_websocket
def echo(request):
    if not request.is_websocket():
        return render(request, "index.html")
    else:
        for message in request.websocket:
            data = eval(message)
            Addr_list = CalculationIP(data['address'])
            command = data['command']
            for ip in Addr_list:
                ret = ssh_shell(ip,"root","123","22",command)
                if ret != 0:
                    times = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
                    retn = "[Suces] ---> " + str(times) + "      " +  command + "      " + ip
                    request.websocket.send(retn)
                else:
                    times = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
                    retn = "[Error] ---> " + str(times) + "      " +  command + "      " + ip
                    request.websocket.send(retn)
# name:urls.py
from MyWeb import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path("echo/",views.echo)
]