由于系统刚刚上线,各种未知bug层出不穷,应用服务和数据库服务双双被隔离,无法被外界访问,无法抓住问题的源头,基于运维的需要就在系统上添加了查看运行日志的功能。现有多个子系统应用分别部署在不同的服务器里,只能通过外网子应用访问内网子应用,现在想通过外网子应用与内网子应用间的通讯,让外网可以查看内网子应用的日志。现以部署在外网的应用为例,查看外网日志,记录下工作例程。外网子应用是部署在Windows server的Tomcat下,查看Tomcat的输出日志。
功能很简单,点击查看后,可以以一定的时间间隔不停地将日志输出在屏幕上,并提供暂停和中断按钮。先配置好Tomcat运行日志重定向到日志文件。
1.View
在页面上布局操作按钮和输出日志,输出日志以背景为黑色,字体为蓝色,代码如下:
- <div id=“body”>
- <div class=“well with-header”>
- <div class=“header bg-themeprimary”>
- <strong>查看日志</strong>
- </div>
- <form id=“defaultForm” class=“form form-horizontal bv-form” role=“form” action=“ckrzsj!show.do” method=“post”>
- <div class=“form-group”>
- <div class=“col-sm-1”>
- <button id=“ckrqsj” type=“button” onclick=“javascript:tockrz();” class=“btn btn-primary input-sm”><i class=“fa fa-print”></i>CheckLog</button>
- </div>
- <div class=“col-sm-1”>
- <button id=“ckrqsj2” type=“button” onclick=“javascript:terminate();” class=“btn btn-primary input-sm”
- style=“display:none;”>
- <i class=“fa fa-ban”></i>Terminate</button>
- </div>
- </div>
- <div class=“form-group”>
- <div style=“margin-bottom: 5px;background-color: black;color: green;font-weight: bold;font-size: 14px;’Times New Roman,Georgia,Serif'”
- class=“well bordered-left bordered-pink”>
- <div class=“row”>
- <div class=“col-sm-12” id=“logs”>
- </div>
- </div>
- </div>
- </div>
- </form>
- </div>
- </div>
JavaScript上以10秒时间间隔异步读取当前读取行数至日志文件末尾的数据,并更新当前读取行数。
- <script type=“text/javascript”>
- var line = 1;//访问日志的当前行数
- var timeout = 0;
- var isStoping = false;
- function tockrz(){
- isStoping = !isStoping;
- if(isStoping){
- $(“#ckrqsj”).html(“<i class=’fa fa-ban’></i>Stop”);
- ckrz();
- timeout =setInterval(ckrz, 10000);
- $(“#ckrqsj2”).show();
- }
- else {
- $(“#ckrqsj”).html(“<i class=’fa fa-print’></i>CheckLog”);
- clearInterval(timeout);
- $(“#ckrqsj2”).hide();
- }
- }
- function ckrz(){
- $.ajax({
- url:“<%=path%>/ckrzsj!getRz.do”,
- type:“post”,
- async: false,
- cache: false,
- dataType:“json”, //这里返回的类型有:json,html,xml,text
- data:{
- line:line
- },
- beforeSend:function(){
- },
- success:function(data,textStatus){
- var datas = “”;
- var lines = data.lineList;
- line = data.line;
- for(var i=0;i<lines.length;i++){
- datas += lines[i];
- }
- $(‘#logs’).append(‘<p>’+datas+'</p>’);
- // 滚到屏幕下方 window.scrollTo(0,document.body.scrollHeight);
- }
- });
- }
- function terminate(){ // 中断后重置数据
- line = 1;
- isStoping = false;
- $(“#ckrqsj”).html(“<i class=’fa fa-print’></i>CheckLog”);
- clearInterval(timeout);
- $(“#logs”).empty();
- $(“#ckrqsj2”).hide();
- }
- </script>
2.Action
先判断当前操作系统类型,并调用相应系统的查看日志方法,并将结果返回给页面。
- public class CkrzAction {
- private int line;
- public int getLine() {
- return line;
- }
- public void setLine(int line) {
- this.line = line;
- }
- public String show(){
- return “show”;
- }
- public String getRz() throws Exception{
- HttpServletResponse response = ServletActionContext.getResponse();
- response.setContentType(“text/json;charset=UTF-8”);
- response.setHeader(“Cache-Control”, “no-cache”);
- PrintWriter out = response.getWriter();
- List<String> lines = new ArrayList<String>();
- int l = line;
- if(!OSType.isWindows()) {
- l = LinuxCall.callCmd(lines, line);
- }
- else {
- l = WindowCall.callCmd(lines, line);
- }
- Map<String, Object> datas = new HashMap<String,Object>();
- datas.put(“lineList”, lines);
- datas.put(“line”, l);
- out.println(JSONObject.fromObject(datas));
- out.flush();
- out.close();
- return null;
- }
- }
3.查看日志方法
Windows下直接读取文件日志,有点坑。。。
- public class WindowCall {
- private static String logFile = “D:\\apache-tomcat-8.0.24\\logs\\catalina.out”;
- static {
- InputStream input = LinuxCall.class.getClassLoader().getResourceAsStream(“logPath.properties”);
- Properties p = new Properties();
- try {
- p.load(input);
- logFile = p.getProperty(“logpath”);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- public static int callCmd(List<String> lines,int line) throws Exception{
- if(lines==null){
- return 1;
- }
- BufferedReader read = null;
- try{
- read = new BufferedReader(new InputStreamReader(new FileInputStream(new File(logFile))));
- String l = null;
- int startline = 0;
- while((l = read.readLine())!=null){
- if(++startline>=line){
- line++;
- lines.add(l);
- }
- }
- }
- finally{
- if(read!=null) {
- read.close();
- }
- }
- return line;
- }
- public static void main(String[] args) {
- try {
- List<String> lines = new ArrayList<String>();
- WindowCall.callCmd(lines,1);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
Linux下直接调用shell命令,频繁使用,性能损耗较大。
- public class LinuxCall {
- private static String logFile = “/home/tomcat/logs/catalina.out”;
- static {
- InputStream input = LinuxCall.class.getClassLoader().getResourceAsStream(“logPath.properties”);
- Properties p = new Properties();
- try {
- p.load(input);
- logFile = p.getProperty(“logpath”);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- public static int callCmd(List<String> lines,int line) throws Exception{
- if(lines==null){
- return 1;
- }
- String cmd = “nl “ + logFile + “|sed -n ‘” + line + “,$p'”;
- String[] cmds = {“/bin/sh”,“-c”,cmd};
- Process pro = Runtime.getRuntime().exec(cmds);
- pro.waitFor();
- InputStream in = pro.getInputStream();
- BufferedReader read = new BufferedReader(new InputStreamReader(in));
- String l = null;
- while((l = read.readLine())!=null){
- line++;
- lines.add(l);
- }
- return line;
- }
- public static void main(String[] args) {
- try {
- List<String> lines = new ArrayList<String>();
- LinuxCall.callCmd(lines,1);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
4.日志路径
logPath.properties
#logpath=/home/tomcat/logs/catalina.out
logpath=D\:\\apache-tomcat-8.0.24\\logs\\catalina.out
5.系统类型
通过JVM调用系统参数,判断操作系统类型
- public class OSType {
- private static String os = System.getProperty(“os.name”).toLowerCase();
- private OSType(){}
- public static String getOsName(){
- return os;
- }
- public static boolean isWindows(){
- return os.indexOf(“windows”) >= 0;
- }
- public static boolean isLinux(){
- return os.indexOf(“linux”) >= 0;
- }
- public static void main(String[] args) {
- System.out.println(OSType.isWindows());
- System.out.println(OSType.isLinux());
- System.out.println(os);
- }
- }
6.结果
在Action层加上子系统间的通讯服务,并将View与其他层的分离,就可以达到目的了。还有就是日志I/O频繁的问题,考虑到日志重定向到文件时按日期分割,减少文件大小,后面又要改程序。最后就是,只做日志下载功能不就可以了,干嘛还这么麻烦。。。
One thought on “Web下查看Tomcat日志–Java”