大致思路:
1.利用tornado提供的websocket功能与浏览器建立长连接,读取实时日志并输出到浏览器
2.写一个实时读取日志的脚本,利用saltstack远程执行,并把实时日志发往redis中。
3.tornado读取redis中的信息,发往浏览器。
此过程用到了redis的发布和订阅功能。
先看一下tornado中是如何处理的:
import os
import sys
import tornado.websocket
import tornado.web
import tornado.ioloop
import redis
import salt.client
from tornado import gen
from tornado.escape import to_unicode
from logs.utility import get_last_lines
from logs import settings
class 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:
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 style='color:{}'>{}</span>" .format(color, line)
class EchoWebSocket (tornado.websocket.WebSocketHandler) :
def open (self) :
print("WebSocket opened" )
@gen.coroutine
def on_message (self, message) :
log = message