由于系统刚刚上线,各种未知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频繁的问题,考虑到日志重定向到文件时按日期分割,减少文件大小,后面又要改程序。最后就是,只做日志下载功能不就可以了,干嘛还这么麻烦。。。
本文由 wenqy 创作,采用 知识共享署名4.0
国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Nov 8,2020