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

jopen 9年前發布 | 94K 次閱讀 WebSocket WebSocket 開發

 

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

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

按照慣例,先上圖:

Java用WebSocket + tail命令實現Web實時日志 </div>

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(); } }</pre>
    由于針對每個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();
    }
    }
    }

    由于用到tail命令,Java服務端需要部署在Linux系統上。

    Web前端

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>tail log</title>
    <script src="http://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>

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!