django自動化運維平臺-web頁面實時顯示tomcat啓動日誌,給予tornado和redis

先來發大概的技術實現,參考好多博客,地址忘記了 後面看到再加javascript

用腳本將要查看的日誌文件讀取出來,使用redis的發佈訂閱模式將內容發佈到redis的指定頻道html

寫一個websocket服務端監聽一個端口,等待長鏈接接入java

       在websocket裏面 使用redis的發佈訂閱模式訂閱指定頻道,若是有用戶訪問進來就把訂閱內容推送出去python

在html創建與websocket的長鏈接,顯示websocket返回的內容linux

 

 

讀取日誌文件腳本:web

# coding:utf8
import paramiko
import select
import redis
import sys

#此方法是進行實時返回,例如tail -f這樣的命令,本次監控就用的是此方法。
def send_content_redis(ip, port, user, pwd, subscribe, logfile):
    redis_config = {
        "host": "xx.xx.xx.xx",
        "port": 6379
    }
    redis_pool = redis.ConnectionPool(**redis_config)
    r = redis.Redis(connection_pool=redis_pool)
    r.pubsub_channels(subscribe)

    # 進行鏈接
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    client.connect(ip, port, username=user, password=pwd, timeout=4)
    # 開啓channel 管道
    transport = client.get_transport()
    channel = transport.open_session()
    channel.get_pty()
    tail = 'tail -f %s' %logfile
    #將命令傳入管道中
    channel.exec_command(tail)
    while True:
        #判斷退出的準備狀態
        if channel.exit_status_ready():
            break
        try:
            # 經過socket進行讀取日誌,我的理解,linux至關於客戶端,我本地至關於服務端請求獲取數據(此處如有理解錯誤,望請指出。。謝謝)
            rl, wl, el = select.select([channel], [], [])
            if len(rl) > 0:
                recv = channel.recv(10240)
                # 此處將獲取的數據解碼成gbk的存入本地日誌
                print(recv.decode('utf-8', 'ignore'))
                r.publish(subscribe, recv.decode('utf-8', 'ignore'))
        # 鍵盤終端異常
        except KeyboardInterrupt:
            channel.send("\x03")  # 發送 ctrl+c
            channel.close()
    client.close()

def main():
    send_content_redis(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5], sys.argv[6])
  


if __name__ == '__main__':
    main()

websocket 服務端代碼redis

# coding:utf8
import os
import sys
import tornado.websocket
import tornado.web
import tornado.ioloop
from tornado import gen
from tornado.escape import to_unicode
import redis
import subprocess


class SubWebSocket(tornado.websocket.WebSocketHandler):
    """
    此handler處理遠程日誌查看
    """
    # 容許跨域請求 
    def check_origin(self, origin):
        return True

    def open(self, *args, **kwargs):
        print("opened")
        self.ip = self.get_argument('ip', '')
        self.redis_ip = self.get_argument('redis_ip', '')
        self.redis_port = self.get_argument('redis_port', '')
        self.pubscribe = self.get_argument('pubscribe', '')
        self.user = self.get_argument('user', '')
        self.password = self.get_argument('password', '')
        self.port = self.get_argument('port', '')
        self.logfile = self.get_argument('logfile', '')
        self.sub = subprocess.Popen('python 1.py %s %s %s %s %s %s' %(self.ip, self.port, self.user, self.password, self.pubscribe, self.logfile ), shell=True)

    @gen.coroutine
    def on_message(self, message):
        r = redis.StrictRedis(host=self.redis_ip)
        # 訂閱頻道,服務器和日誌路徑肯定一個頻道
        channel = r.pubsub()
        channel.subscribe(self.pubscribe)
        try:
            while True:
                data = channel.get_message()
                if not data:
                    # 若是讀取不到消息,間隔必定時間,避免無謂的CPU消耗
                    yield gen.sleep(0.05)
                    continue
                if data["type"] == "message":
                    line = data["data"]
                    self.write_message(line)
        except tornado.websocket.WebSocketClosedError:
            self.close()

    def on_close(self):
        print("closed")
        self.sub.kill()



class Application(tornado.web.Application):
    def __init__(self):
        handlers = [
            (r'/', MainHandler),  # 提供瀏覽頁面,頁面中的JS與服務器創建鏈接
            (r'/log', 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):
        self.render("index.html")

def main():
    app = Application()
    app.listen(8888)
    tornado.ioloop.IOLoop.current().start()


if __name__ == '__main__':
    main()
                                              

 

html代碼:shell

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript">
      window.onload = function(){
            if("WebSocket" in window){
              console.log('瀏覽器支持websocket!');var ws = new WebSocket("ws://xx.xx.xx.xx:8888/log?ip={{ip}}&" +
                  "redis_ip={{redis_ip}}&redis_port={{redis_port}}&pubscribe={{pubscribe}}&" +
                  "user={{user}}&password={{password}}&port={{port}}&logfile={{logfile}}");
              var div = document.getElementById('content');
              ws.onopen = function () {
                  ws.send('websocket 連接創建第一次發送數據!');
                  console.log('第一次發送數據結束!');
              };
              ws.onmessage = function (evt) {
                  console.log("開始接收數據!");
                  var received_msg = evt.data;
                  div.innerText = div.innerText  + received_msg;
                  content_end.scrollIntoView();

              };
            }else{
                console.log("你的瀏覽器不支持websocket")
            }

        }
    </script>
</head>
<body>
      <div id="sse">
         <h3>服務啓動日誌{{salt_key_id}}</h3>
      </div>
      <div id="content">

      </div>
      <div id="content_end" style="height:100px; overflow:hidden">


     </div>
</body>
</html>

遇到的問題:跨域

開始使用的一個單獨的index.html調試的代碼沒問題,放到項目中出現了不能跨域請求的問題 ,而後我就把跨域請求關掉了,不檢查是否跨域瀏覽器

相關文章
相關標籤/搜索