Web下查看Tomcat日志–Java

    由于系统刚刚上线,各种未知bug层出不穷,应用服务和数据库服务双双被隔离,无法被外界访问,无法抓住问题的源头,基于运维的需要就在系统上添加了查看运行日志的功能。现有多个子系统应用分别部署在不同的服务器里,只能通过外网子应用访问内网子应用,现在想通过外网子应用与内网子应用间的通讯,让外网可以查看内网子应用的日志。现以部署在外网的应用为例,查看外网日志,记录下工作例程。外网子应用是部署在Windows server的Tomcat下,查看Tomcat的输出日志。
    功能很简单,点击查看后,可以以一定的时间间隔不停地将日志输出在屏幕上,并提供暂停和中断按钮。先配置好Tomcat运行日志重定向到日志文件。

1.View

在页面上布局操作按钮和输出日志,输出日志以背景为黑色,字体为蓝色,代码如下:

  1. <div id=“body”>
  2.         <div class=“well with-header”>
  3.             <div class=“header bg-themeprimary”>
  4.                 <strong>查看日志</strong>
  5.             </div>
  6.             <form id=“defaultForm” class=“form form-horizontal bv-form” role=“form” action=“ckrzsj!show.do” method=“post”>
  7.                 <div class=“form-group”>
  8.                     <div class=“col-sm-1”>
  9.                         <button id=“ckrqsj” type=“button” onclick=“javascript:tockrz();” class=“btn btn-primary input-sm”><i class=“fa fa-print”></i>CheckLog</button>
  10.                     </div>
  11.                     <div class=“col-sm-1”>
  12.                         <button id=“ckrqsj2” type=“button” onclick=“javascript:terminate();” class=“btn btn-primary input-sm”
  13.                             style=“display:none;”>
  14.                         <i class=“fa fa-ban”></i>Terminate</button>
  15.                     </div>
  16.                 </div>
  17.                 <div class=“form-group”>
  18.                     <div style=“margin-bottom: 5px;background-color: black;color: green;font-weight: bold;font-size: 14px;’Times New Roman,Georgia,Serif'”
  19.                         class=“well bordered-left bordered-pink”>
  20.                             <div class=“row”>
  21.                                 <div class=“col-sm-12” id=“logs”>
  22.                                 </div>
  23.                             </div>
  24.                     </div>
  25.                 </div>
  26.             </form>
  27.         </div>
  28.     </div>

JavaScript上以10秒时间间隔异步读取当前读取行数至日志文件末尾的数据,并更新当前读取行数。

  1. <script type=“text/javascript”>
  2.         var line = 1;//访问日志的当前行数
  3.         var timeout = 0;
  4.         var isStoping = false;
  5.         function tockrz(){
  6.             isStoping = !isStoping;
  7.             if(isStoping){
  8.                 $(“#ckrqsj”).html(“<i class=’fa fa-ban’></i>Stop”);
  9.                 ckrz();
  10.                 timeout =setInterval(ckrz, 10000);
  11.                 $(“#ckrqsj2”).show();
  12.             }
  13.             else {
  14.                 $(“#ckrqsj”).html(“<i class=’fa fa-print’></i>CheckLog”);
  15.                 clearInterval(timeout);
  16.                 $(“#ckrqsj2”).hide();
  17.             }
  18.         }
  19.         function ckrz(){
  20.             $.ajax({
  21.                 url:“<%=path%>/ckrzsj!getRz.do”,
  22.                 type:“post”,
  23.                 async: false,
  24.                 cache: false,
  25.                 dataType:“json”//这里返回的类型有:json,html,xml,text
  26.                 data:{
  27.                     line:line
  28.                 },
  29.                 beforeSend:function(){
  30.                 },
  31.                 success:function(data,textStatus){
  32.                     var datas = “”;
  33.                     var lines = data.lineList;
  34.                     line = data.line;
  35.                     for(var i=0;i<lines.length;i++){
  36.                         datas += lines[i];
  37.                     }
  38.                     $(‘#logs’).append(‘<p>’+datas+'</p>’);
  39.    // 滚到屏幕下方                 window.scrollTo(0,document.body.scrollHeight); 
  40.                 }
  41.             });
  42.         }
  43.         function terminate(){ // 中断后重置数据
  44.             line = 1;
  45.             isStoping = false;
  46.             $(“#ckrqsj”).html(“<i class=’fa fa-print’></i>CheckLog”);
  47.             clearInterval(timeout);
  48.             $(“#logs”).empty();
  49.             $(“#ckrqsj2”).hide();
  50.         }
  51.     </script>

2.Action

先判断当前操作系统类型,并调用相应系统的查看日志方法,并将结果返回给页面。

  1. public class CkrzAction {
  2.     private int line;
  3.     public int getLine() {
  4.         return line;
  5.     }
  6.     public void setLine(int line) {
  7.         this.line = line;
  8.     }
  9.     public String show(){
  10.         return “show”;
  11.     }
  12.     public String getRz() throws Exception{
  13.         HttpServletResponse response = ServletActionContext.getResponse();
  14.         response.setContentType(“text/json;charset=UTF-8”);
  15.         response.setHeader(“Cache-Control”“no-cache”);
  16.         PrintWriter out = response.getWriter();
  17.         List<String> lines = new ArrayList<String>();
  18.         int l = line;
  19.         if(!OSType.isWindows()) {
  20.             l = LinuxCall.callCmd(lines, line);
  21.         }
  22.         else {
  23.             l = WindowCall.callCmd(lines, line);
  24.         }
  25.         Map<String, Object> datas = new HashMap<String,Object>();
  26.         datas.put(“lineList”, lines);
  27.         datas.put(“line”, l);
  28.         out.println(JSONObject.fromObject(datas));
  29.         out.flush();
  30.         out.close();
  31.         return null;
  32.     }
  33. }

3.查看日志方法

Windows下直接读取文件日志,有点坑。。。

  1. public class WindowCall {
  2.     private static String logFile = “D:\\apache-tomcat-8.0.24\\logs\\catalina.out”;
  3.     static {
  4.         InputStream input = LinuxCall.class.getClassLoader().getResourceAsStream(“logPath.properties”);
  5.         Properties p = new Properties();
  6.         try {
  7.             p.load(input);
  8.             logFile = p.getProperty(“logpath”);
  9.         } catch (IOException e) {
  10.             e.printStackTrace();
  11.         }
  12.     }
  13.     public static int callCmd(List<String> lines,int line) throws Exception{
  14.         if(lines==null){
  15.             return 1;
  16.         }
  17.         BufferedReader read = null;
  18.         try{
  19.             read = new BufferedReader(new InputStreamReader(new FileInputStream(new  File(logFile))));
  20.             String l = null;
  21.             int startline = 0;
  22.             while((l = read.readLine())!=null){
  23.                 if(++startline>=line){
  24.                     line++;
  25.                     lines.add(l);
  26.                 }
  27.             }
  28.         }
  29.         finally{
  30.             if(read!=null) {
  31.                 read.close();
  32.             }
  33.         }
  34.         return line;
  35.     }
  36.     public static void main(String[] args) {
  37.         try {
  38.             List<String> lines = new ArrayList<String>();
  39.             WindowCall.callCmd(lines,1);
  40.         } catch (Exception e) {
  41.             e.printStackTrace();
  42.         }
  43.     }
  44. }

Linux下直接调用shell命令,频繁使用,性能损耗较大。

  1. public class LinuxCall {
  2.     private static String logFile = “/home/tomcat/logs/catalina.out”;
  3.     static {
  4.         InputStream input = LinuxCall.class.getClassLoader().getResourceAsStream(“logPath.properties”);
  5.         Properties p = new Properties();
  6.         try {
  7.             p.load(input);
  8.             logFile = p.getProperty(“logpath”);
  9.         } catch (IOException e) {
  10.             e.printStackTrace();
  11.         }
  12.     }
  13.     public static int callCmd(List<String> lines,int line) throws Exception{
  14.         if(lines==null){
  15.             return 1;
  16.         }
  17.         String cmd = “nl “ + logFile + “|sed -n ‘” + line + “,$p'”;
  18.         String[] cmds = {“/bin/sh”,“-c”,cmd};
  19.         Process pro = Runtime.getRuntime().exec(cmds);
  20.         pro.waitFor();
  21.         InputStream in = pro.getInputStream();
  22.         BufferedReader read = new BufferedReader(new InputStreamReader(in));
  23.         String l = null;
  24.         while((l = read.readLine())!=null){
  25.             line++;
  26.             lines.add(l);
  27.         }
  28.         return line;
  29.     }
  30.     public static void main(String[] args) {
  31.         try {
  32.             List<String> lines = new ArrayList<String>();
  33.             LinuxCall.callCmd(lines,1);
  34.         } catch (Exception e) {
  35.             e.printStackTrace();
  36.         }
  37.     }
  38. }

4.日志路径

logPath.properties
#logpath=/home/tomcat/logs/catalina.out
logpath=D\:\\apache-tomcat-8.0.24\\logs\\catalina.out

5.系统类型

通过JVM调用系统参数,判断操作系统类型

  1. public class OSType {
  2.     private static String os = System.getProperty(“os.name”).toLowerCase();
  3.     private OSType(){}
  4.     public static String getOsName(){
  5.         return os;
  6.     }
  7.     public static boolean isWindows(){
  8.         return os.indexOf(“windows”) >= 0;
  9.     }
  10.     public static boolean isLinux(){
  11.         return os.indexOf(“linux”) >= 0;
  12.     }
  13.     public static void main(String[] args) {
  14.         System.out.println(OSType.isWindows());
  15.         System.out.println(OSType.isLinux());
  16.         System.out.println(os);
  17.     }
  18. }

6.结果

进入页面:
startLog

点击查看:
logresult

在Action层加上子系统间的通讯服务,并将View与其他层的分离,就可以达到目的了。还有就是日志I/O频繁的问题,考虑到日志重定向到文件时按日期分割,减少文件大小,后面又要改程序。最后就是,只做日志下载功能不就可以了,干嘛还这么麻烦。。。

One thought on “Web下查看Tomcat日志–Java

发表评论

电子邮件地址不会被公开。 必填项已用*标注

3 + 21 = ?