首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

如何通过 java 实现在多台 Linux 服务器间自动执行各种命令或查询日志-2

如何通过 java 实现在多台 Linux 服务器间自动执行各种命令或查询日志-2

如何动态读取服务器相关日志在多台 job servers 中,由于配置了负载均衡,因此 job 就会被分发到不同的 server 上,所以对应 job 的日志可能会出现在不同的 server 上。通常我们需要根据界面上的 ID 从一个日志文件先找出相关的 JobId,然后再从其他日志文件中再找出具体的错误日志信息。
实现代码如下:
清单 2. 动态读取服务器日志
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
//日志 1 中特殊字符信息
String uniqeStr = "RunID: 123";
//日志 1 文件位置
String serverlogFilePath = "/opt/server/log/server.log";
//日志 2 中特殊字符信息
String jobIdExpr = "id=[0-9]+";
//日志 2 文件位置
String joblogFilePath = "/opt/server/log/job.log";

JSch sshSingleton = new JSch();

Properties userProp = new Properties();
userProp.load(new FileReader("user.properties"));
String userName = userProp.getProperty("username");
String password = userProp.getProperty("password");

Properties serversProp = new Properties();
serversProp.load(new FileReader("servers.properties"));

Pattern p = Pattern.compile(jobIdExpr);
for (Map.Entry<Object, Object> serverProp : serversProp.entrySet()) {
            String name = (String) serverProp.getKey();
            String server = (String) serverProp.getValue();

            Session session = sshSingleton.getSession(userName, server);
session.setPassword(password);

Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);
            session.connect();

//打开执行管道
ChannelExec channel = (ChannelExec) session.openChannel("exec");
BufferedReader in = new BufferedReader(new InputStreamReader(
                    channel.getInputStream()));
//设置命令,从日志 1 中找出关键字符信息
channel.setCommand("cat " + serverlogFilePath + " |grep -w "
                    + uniqeStr);
            channel.connect();
String msg;
String jobId = null;
while ((msg = in.readLine()) != null) {
                Matcher m = p.matcher(msg);
if (m.find()) {
                    jobId = m.group();
break;
                }
            }
//关闭第一个执行管道
            channel.disconnect();
            
if (jobId != null) {
//日志 1 中发现关键字符信息后,在同一服务器中日志文件 2 中继续查找
System.out.println("found log in jobServer: " + name);

//另外再打开一个新的执行管道
channel = (ChannelExec) session.openChannel("exec");
in = new BufferedReader(new InputStreamReader(
                        channel.getInputStream()));
String cmd = "cat " + joblogFilePath + " |grep -A 10 " + jobId;

                channel.setCommand(cmd);
                channel.connect();
//输出需要查找的日志信息
while ((msg = in.readLine()) != null) {
System.out.println(msg);
                }

                channel.disconnect();
            }

            session.disconnect();

if (jobId != null) {
//已经在这台服务器中找到日志,不需要继续去其他服务器中查找了
break;
            }
        }




如何实现自动上传下载文件在测试过程中,我们经常需要上传更新一些配置文件或者下载服务器上的一些日志文件,下面我们就以一台服务器做为上传下载的示例。
实现代码如下:
清单 3. 自动上传下载文件
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
String serverFile = "/opt/log/1.log";
String localFolder = "C:/tmp";

String localFile = "C:/tmp/user.xml";
String serverFolder = "/tmp/";

JSch sshSingleton = new JSch();

Properties userProp = new Properties();
userProp.load(new FileReader("user.properties"));
String userName = userProp.getProperty("username");
String password = userProp.getProperty("password");

String server = "192.168.0.1";
//设置端口
int port = 22;
        Session session = sshSingleton.getSession(userName, server, port);
        session.setPassword(password);

Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
        session.setConfig(config);
        session.connect();
//打开 ftp 管道
Channel channel = session.openChannel("sftp");
        channel.connect();
        ChannelSftp c = (ChannelSftp) channel;
//转到根目录,便于使用绝对路径来进行文件传输
c.cd("/");

//从服务器上下载日志文件 1.log 到本地目录 C:/tmp
        c.get(serverFile, localFolder);
         
//上传配置文件 user.xml 到服务器上,如果服务器上已经存在该文件,则覆盖它
c.put(localFile, serverFolder, ChannelSftp.OVERWRITE);
         
        session.disconnect();




展望我们现有的改进方式不过是重新修改 SSHXcute 的代码让其能够支持多个服务器之间的自动切换,还没有对其完全自动化,我们期望的前景是能够配置一个让开发人员完全不需要进行任何代码开发的第三方服务器来存储并且代理实现所有的配置命令,并且给用户一个可以配置的界面,让用户对其进行新的命令和执行方式的配置 (例如是否可以进行自动化的时间配置)。
图 5. 使用 jsch 搭建 web 版应用流程图总结实现自动化遍历服务器,动态读取错误日志能够大大缩短开发测试人员分析问题的时间,提高解决问题的效率。但遇到复杂的错误时,单从错误日志并不能完全地查出根本所在,因此我们需要不断地扩展其他功能以应对各种复杂的情况。我们将会在后续的文章中对功能进一步深入细化。
返回列表