文章目录
在Linux操作系统中,经常需要查看日志文件的实时输出内容,通常会使用tail -f
或者tailf
命令。查看实时日志可能会需要首先SSH连上Linux主机,步骤很麻烦不说,如果是生产环境的服务器,可能还会控制各种权限。此时可以考虑基于Web显示实时日志。
由于传统的HTTP协议是请求/响应模式,而实时日志需要不定时的持续的输出,有新的日志内容时需要由服务器主动推送给客户端浏览器。所以这里使用的是HTML5的WebSocket协议。
按照惯例,先上图:
Web实时日志
JSR 356是Java实现WebSocket的一套规范,所以首先需要准备一个支持JSR 356的服务器,例如Tomcat、Jetty的最新版本。
JSR 356提供了注解@ServerEndpoint
,并需要指定一个路径,用于处理客户端WebSocket请求。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| 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;
("/log") public class LogWebSocketHandle {
private Process process; private InputStream inputStream;
public void onOpen(Session session) { try { process = Runtime.getRuntime().exec("tail -f /var/log/syslog"); inputStream = process.getInputStream(); TailLogThread thread = new TailLogThread(inputStream, session); thread.start(); } catch (IOException e) { e.printStackTrace(); } }
public void onClose() { try { if(inputStream != null) inputStream.close(); } catch (Exception e) { e.printStackTrace(); } if(process != null) process.destroy(); }
public void onError(Throwable thr) { thr.printStackTrace(); } }
|
由于针对每个WebSocket连接都会创建一个新的LogWebSocketHandle实例,所以可以不用像Servlet一样考虑线程安全问题。由于tail -f
命令的输入流会阻塞当前线程,所以一定要创建一个新的线程来读取tail -f
命令的返回结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| 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; }
public void run() { String line; try { while((line = reader.readLine()) != null) { session.getBasicRemote().sendText(line + "<br>"); } } catch (IOException e) { e.printStackTrace(); } } }
|
Web前端需要通过WebSocket连接到服务端,实时接收最新的日志内容并展示到页面上。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <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() { var websocket = new WebSocket('ws://localhost:8080/log'); websocket.onmessage = function(event) { $("#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