Java用WebSocket + tail命令實現Web實時日志


原文:http://blog.csdn.net/xiao__gui/article/details/50041673

 

在Linux操作系統中,經常需要查看日志文件的實時輸出內容,通常會使用tail -f或者tailf命令。查看實時日志可能會需要首先SSH連上Linux主機,步驟很麻煩不說,如果是生產環境的服務器,可能還會控制各種權限。基於Web的實時日志可以解決這個問題。

由於傳統的HTTP協議是請求/響應模式,而實時日志需要不定時的持續的輸出,由服務器主動推送給客戶端瀏覽器。所以這里使用的是HTML5的WebSocket協議。

按照慣例,先上圖: 
這里寫圖片描述

Java后台

JSR 356是Java實現WebSocket的一套規范,所以需要一個支持JSR 356的服務器,例如Tomcat、Jetty的最新版本。

JSR 356提供了注解@ServerEndpoint,並需要指定一個路徑,用於處理客戶端WebSocket請求。

import java.io.IOException;
import java.io.InputStream;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/log")
public class LogWebSocketHandle {

    private Process process;
    private InputStream inputStream;

    /**
     * 新的WebSocket請求開啟
     */
    @OnOpen
    public void onOpen(Session session) {
        try {
            // 執行tail -f命令
            process = Runtime.getRuntime().exec("tail -f /var/log/syslog");
            inputStream = process.getInputStream();

            // 一定要啟動新的線程,防止InputStream阻塞處理WebSocket的線程
            TailLogThread thread = new TailLogThread(inputStream, session);
            thread.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * WebSocket請求關閉
     */
    @OnClose
    public void onClose() {
        try {
            if(inputStream != null)
                inputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(process != null)
            process.destroy();
    }

    @OnError
    public void onError(Throwable thr) {
        thr.printStackTrace();
    }
}

由於針對每個WebSocket連接都會創建一個新的LogWebSocketHandle實例,所以可以不用像Servlet一樣考慮線程安全問題。由於tail -f命令的輸入流會阻塞當前線程,所以一定要創建一個新的線程來讀取tail -f命令的返回結果:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import javax.websocket.Session;

public class TailLogThread extends Thread {

    private BufferedReader reader;
    private Session session;

    public TailLogThread(InputStream in, Session session) {
        this.reader = new BufferedReader(new InputStreamReader(in));
        this.session = session;

    }

    @Override
    public void run() {
        String line;
        try {
            while((line = reader.readLine()) != null) {
                // 將實時日志通過WebSocket發送給客戶端,給每一行添加一個HTML換行
                session.getBasicRemote().sendText(line + "<br>");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Web前端

Web前端需要通過WebSocket連接到服務端,實時接收最新的日志內容並展示到頁面上。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>tail log</title>
<script src="//cdn.bootcss.com/jquery/2.1.4/jquery.js"></script>
</head>
<body>
    <div id="log-container" style="height: 450px; overflow-y: scroll; background: #333; color: #aaa; padding: 10px;">
        <div>
        </div>
    </div>
</body>
<script>
    $(document).ready(function() {
        // 指定websocket路徑
        var websocket = new WebSocket('ws://localhost:8080/log');
        websocket.onmessage = function(event) {
            // 接收服務端的實時日志並添加到HTML頁面中
            $("#log-container div").append(event.data);
            // 滾動條滾動到最低部
            $("#log-container").scrollTop($("#log-container div").height() - $("#log-container").height());
        };
    });
</script>
</body>
</html>

完成編碼后,就可以部署了。由於用到tail命令,該項目需要部署在Linux系統上。

Demo on GitHub:https://github.com/wucao/websocket-tail-demo


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM