首页 > 网站 > 建站经验 > 正文

django+tornado实现实时查看远程日志的方法

2019-11-02 14:12:31
字体:
来源:转载
供稿:网友

大致思路:

1.利用tornado提供的websocket功能与浏览器建立长连接,读取实时日志并输出到浏览器

2.写一个实时读取日志的脚本,利用saltstack远程执行,并把实时日志发往redis中。

3.tornado读取redis中的信息,发往浏览器。

此过程用到了redis的发布和订阅功能。

先看一下tornado中是如何处理的:

import osimport sysimport tornado.websocketimport tornado.webimport tornado.ioloopimport redisimport salt.clientfrom tornado import genfrom tornado.escape import to_unicodefrom logs.utility import get_last_linesfrom logs import settingsclass SubWebSocket(tornado.websocket.WebSocketHandler): """ 此handler处理远程日志查看 """ def open(self, *args, **kwargs):  print("opened") @gen.coroutine def on_message(self, message):  # 主机名,要查看的日志路径,运行脚本的命令这些信息从浏览器传过来  hostname, log_path, cmd = message.split("||")  local = salt.client.LocalClient()  r = redis.StrictRedis(host=settings.REDIS_HOST, port=settings.REDIS_PORT,        password=settings.REDIS_PASSWD, db=5)  # 订阅频道,服务器和日志路径确定一个频道  key = settings.LOG_KEY.format(server=hostname.strip(), log_path=log_path.strip())  channel = r.pubsub()  channel.subscribe(key)  # 异步方式执行命令,远程运行脚本  local.cmd_async(hostname, "cmd.run", [cmd])  try:   while True:    data = channel.get_message()    if not data:     # 如果读取不到消息,间隔一定时间,避免无谓的CPU消耗     yield gen.sleep(0.05)     continue    if data["type"] == "message":     line = format_line(data["data"])     self.write_message(line)  except tornado.websocket.WebSocketClosedError:   self.close() def on_close(self):  global FLAG  FLAG = False  print("closed")def format_line(line): line = to_unicode(line) if "INFO" in line:  color = "#46A3FF" elif "WARN" in line:  color = "#FFFF37" elif "ERROR" in line:  color = "red" elif "CRITICAL" in line:  color = "red" else:  color = "#FFFFFF" return "<span >{}</span>".format(color, line)class EchoWebSocket(tornado.websocket.WebSocketHandler): def open(self):  print("WebSocket opened") @gen.coroutine def on_message(self, message):  log = message  print "log file: ", log  try:   with open(log, 'r') as f:    for line in get_last_lines(f):     line1 = format_line(line)     self.write_message(line1)    while True:     line = f.readline()     if not line:      yield gen.sleep(0.05)      continue     self.write_message(format_line(line.strip()))  except tornado.websocket.WebSocketClosedError as e:   print e   self.close() # def check_origin(self, origin): #  print origin, self.request.headers.get("Host") #  # super(EchoWebSocket, self).check_origin() #  return True def on_close(self):  print("WebSocket closed")class Application(tornado.web.Application): def __init__(self):  handlers = [   (r'/log/', MainHandler), # 提供浏览页面,页面中的JS与服务器建立连接   (r'/log/local', EchoWebSocket), # 处理本地日志实时查看,比较简单   (r'/log/remote', SubWebSocket), # 处理远程日志实时查看,稍微复杂  ]  settings = {   "debug": True,   "template_path": os.path.join(os.path.dirname(__file__), "templates"),   "static_path": os.path.join(os.path.dirname(__file__), "static"),  }  super(Application, self).__init__(handlers, **settings)class MainHandler(tornado.web.RequestHandler): def get(self):  # 要查看的日志路径  log = self.get_argument("log", None)  # hostname实际上是saltstack中这台机器对应的minion id  hostname = self.get_argument("hostname", None)  # 本地日志还是远程日志  type = self.get_argument("type", "local")  # 运行读取实时日志的脚本,参数比较多,后面会有  cmd = self.get_argument("cmd", "")  context = {   "log": log,   "hostname": hostname,   "type": type,   "cmd": cmd,  }  self.render("index.html", **context)
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表