首页 > Web开发 > 详细

对webssh实现命令回放功能

时间:2019-08-31 17:35:08      阅读:198      评论:0      收藏:0      [点我收藏+]

想要实现webssh的命令记录功能需要一个前端的组件 asciinema

django服务端代码

 1 class WebSSH(WebsocketConsumer):
 2     message = {status: 0, message: None}
 3     """
 4     status:
 5         0: ssh 连接正常, websocket 正常
 6         1: 发生未知错误, 关闭 ssh 和 websocket 连接
 7 
 8     message:
 9         status 为 1 时, message 为具体的错误信息
10         status 为 0 时, message 为 ssh 返回的数据, 前端页面将获取 ssh 返回的数据并写入终端页面
11     """
12 
13     def connect(self):
14         try:
15             self.accept()
16             logger.info(open connet service ssh)
17 
18             query_string = self.scope[query_string]
19             logger.info(query_string)
20             connet_argv = QueryDict(query_string=query_string, encoding=utf-8)
21             logger.info(connet_argv)
22             serverid = connet_argv.get(unique)
23             width = connet_argv.get(width)
24             height = connet_argv.get(height)
25             appid = connet_argv.get(appid,‘‘)
26             execuserid = connet_argv.get(execuserid,‘‘)
27 
28             width = int(width)
29             height = int(height)
30 
31             service = models.ServiceModel.objects.get(id=serverid)
32 
33             host = service.ipaddress
34             port = str(service.port)
35             user = system_config.log_user
36             logger.info({} {} {} {} {}.format(serverid,height,serverid,host,user))
37             self.ssh = SSH(websocker=self, message=self.message)
38             self.execuserid = execuserid
39             self.serverid = serverid
40 
41 
42             self.ssh.connect(
43                 host=host,
44                 user=user,
45                 port=port,
46                 pty_width=width,
47                 pty_height=height
48             )
49             if appid:
50                 app = models.ApplicationModel.objects.get(id=appid)
51                 self.ssh.shell(/home/{}/showlog.sh {}\n.format(user,app.tomcatname))
52 
53         except Exception as e:
54             logger.info(e)
55             self.message[status] = 1
56             self.message[message] = str(e)
57             message = json.dumps(self.message)
58             self.send(message)
59             self.close()
60 
61     def disconnect(self, close_code):
62         try:
63             self.ssh.close()
64         except:
65             pass
66 
67     def receive(self, text_data=None, bytes_data=None):
68         data = json.loads(text_data)
69         if type(data) == dict:
70             status = data[status]
71             if status == 0:
72                 data = data[data]
73                 self.ssh.shell(data,self) #这里执行命令的时候把对象本身传进去(用了channels和xterm.js通过websocket实现的webssh是一个字符一个字符发送的,在parimako这个模块中做了一系列的命令组装,组成一个完整的shell命令)
74 
75             else:
76                 cols = data[cols]
77                 rows = data[rows]
78                 self.ssh.resize_pty(cols=cols, rows=rows)
79 
80     def savecommend(self,commend):   #这里是保存命令的方法
81         servicecommit = ServiceCommitModel()
82         servicecommit.service_id = self.serverid
83         servicecommit.user_id = self.execuserid
84         json_commend = json.dumps(commend)
85         servicecommit.commitname = json_commend[1:-1]
86         servicecommit.save()
87         logger.info(json_commend)

 

 1 import paramiko
 2 from threading import Thread
 3 from libs.ansible_libs.tools import get_key_obj
 4 import socket
 5 import json
 6 import logging
 7 
 8 
 9 class SSH:
10     def __init__(self, websocker, message):
11         self.websocker = websocker
12         self.message = message
13 
14     def connect(self, host, user, password=None, pkey=None, port=22, timeout=120,
15                 term=xterm, pty_width=80, pty_height=24):
16         try:
17             ssh_client = paramiko.SSHClient()
18             ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
19 
20             if password:
21                 ssh_client.connect(username=user, password=password, hostname=host, port=port, timeout=timeout)
22             else:
23                 ssh_client.connect(username=user, hostname=host, port=port, timeout=timeout)
24 
25             transport = ssh_client.get_transport()
26             self.channel = transport.open_session()
27             self.channel.get_pty(term=term, width=pty_width, height=pty_height)
28             self.channel.invoke_shell()
29 
30             for i in range(2):
31                 recv = self.channel.recv(1024).decode(utf-8)
32                 self.message[status] = 0
33                 self.message[message] = recv
34                 message = json.dumps(self.message)
35                 self.websocker.send(message)
36 
37         except socket.timeout as e:
38             self.message[status] = 1
39             self.message[message] = ssh 连接超时
40             message = json.dumps(self.message)
41             logging.info(connet server timeout)
42             self.websocker.send(message)
43             self.websocker.close()
44         except Exception as e:
45             self.message[status] = 1
46             self.message[message] = str(e)
47             message = json.dumps(self.message)
48             logging.info(connet server custom)
49             self.websocker.send(message)
50             self.websocker.close()
51 
52     def resize_pty(self, cols, rows):
53         self.channel.resize_pty(width=cols, height=rows)
54 
55 
56     def django_to_ssh(self, data):
57         try:
58             self.channel.send(data)
59             return
60         except:
61             self.close()
62 
63     def websocket_to_django(self,httpobj):
64         try:
65             while True:
66                 data = self.channel.recv(1024).decode(utf-8)
67                 if not len(data):
68                     return
69                 self.message[status] = 0
70                 self.message[message] = data
71                 message = json.dumps(self.message)  
72                 self.websocker.send(message)
73                 print(data)
74                 try:
75                     if httpobj:
76                         httpobj.savecommend(str(data))  在这里做命令记录,把命令保存到数据库
77                 except Exception as e:
78                     print(e)
79                 # httpobj.savecommend(data)
80         except Exception as e:
81             print(e)
82             self.close()
83 
84     def close(self):
85         self.message[status] = 1
86         self.message[message] = 关闭连接
87         message = json.dumps(self.message)
88         self.websocker.send(message)
89         self.channel.close()
90         self.websocker.close()
91 
92     def shell(self, data, httpobj=None):
93         Thread(target=self.django_to_ssh, args=(data,)).start()
94         Thread(target=self.websocket_to_django, args=(httpobj,)).start()  #这里是返回到前端的线程,在这个线程中做命令的记录

当需要查看命令回放的时候

 1 class CommandData(LoginRequiredMixin,View):
 2     def get(self,request):
 3         ‘‘‘
 4         获取用户选择的参数以返回视频文件
 5         :param request:
 6         :return:
 7         ‘‘‘
 8         serverid = request.GET.get(sid)
 9         end_time = request.GET.get(end_time)
10         start_time = request.GET.get(start_time)
11         userid = request.GET.get(uid)
12         servers = ServiceModel.objects.all()
13         users = User.objects.all()
14         datas = ServiceCommitModel.objects.filter(date__gte=start_time,date__lte=end_time,service_id=serverid,user_id=userid).values(commitname)
15         # fileurl = ‘/home/PyObject/static/image/demo/demo.json‘
16         fileurl = /opt/object/static/image/demo/demo.json
17         datalist = list()
18         playindex = 0
19         with open(fileurl,wb) as f:
20             f.write(bytes({"version": 2, "width": 1500, "height": 1000, "timestamp": 1559530296, "env": {"SHELL": "/bin/bash", "TERM": "xterm-256color"}}\n,encoding=utf-8)) #这里是asciinema需要的文件头
21             for data in datas:
22                 playindex += 0.4  #设置播放速度
23 
24                 commitname = data[commitname]
25 
26                 linestr = [{}, "o", "{}"]\n.format(playindex,commitname) #把命令写入到asciiname文件里面(必须按照这种格式)
27                 # print(type(commitname),print(commitname))
28                 f.write(bytes(linestr,encoding=utf-8)) 以二进制格式写入
29             # datalist.append(data[‘commitname‘])
30         # print(json.dumps(datalist))
31         # return JsonResponse({
32         #     ‘datas‘: json.dumps(datalist)
33         # })
34         player = ok
35         return render(request,command/playbackcommend.html,locals()) 返回页面

前端网页:

在html中导入asciinema的js和css文件

<div class="row">
    {% if player %}
         <asciinema-player src="{% static ‘image/demo/demo.json‘ %}" cols="260" rows="40"></asciinema-player>
    {% endif %}
</div>

这样就实现了webssh的命令回放功能

 

对webssh实现命令回放功能

原文:https://www.cnblogs.com/arrow-kejin/p/11439721.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!