本次實驗將使用Django 3.0 配合 dwebsocket websocket組件,實現一個網頁版的SSH命令行工具,其支持 vim , 支持 ping等交互命令,惟一的一個小缺點是略卡,不知道是我電腦問題仍是這個socket框架不穩定呢,若是作項目建議不要手擼代碼,其實已經有很是好的解決方案了 https://github.com/huashengdun/websshjavascript
基本用法css
<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
<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")
光標問題已經解決了,找了好久的,操蛋啊。java
<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")
來咱們繼續,加上邊框,進行定製。jquery
{% 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")
繼續改造啊,先玩着,後期上websocket.git
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) ]
Dwebsocket
網上找到一個老版本的,改造了一下 能夠支持 django 3.0 。github
index.htmlweb
<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.pyajax
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), ]
頁面加載後自動鏈接shell
<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>
<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)#發送消息到客戶端
繼續嘗試,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)
簡單的隧道。
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 代碼還不太穩定,完善後放出來。
代碼,其實比想象中的簡單得多,我嘗試了好久。
<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>