Java本地调用shell遇到的问题

前言

上周接了个任务,写一个monitor定时采集服务器上指定的几个应用的数据,包括像CPU占用率、线程数、句柄数等等。不是很难,但是要下发的shell命令很多,采集的数据也很多,而且为了方便本地调试,就准备写两套代码。一套用于本地远程登录服务器下发shell,一套用于当monitor程序部署到服务器上本地执行shell。本篇就来讲一讲我在服务器本地执行shell遇到的坑。。。

Java要想下发shell命令怎么做呢?

  1. 远程:这个调用比较简单,要用到第三方库jcraft来做ssh连接,然后下发shell命令用Expect4j比较方便,但是最终返回出来的数据不太好处理,一大串字符串,我要的数据就那么几个,用正则来慢慢匹配只有。远程下发shell的网上资料很多,我现有的代码与公司业务结合比较紧密,不方便贴出来,可自定搜索。
  2. 本地:本地执行shell可以用jdk自带的Runtime和ProcessBuilder,推荐使用ProcessBuilder。

Runtime

eg:

1
2
String s = "ps -ef|grep abc";
Runtime.getRuntime().exec(s);

Runtime下面其实也是调用的ProcessBuilder,所以我推荐直接使用ProcessBuilder算了。。。

Runtime里面用到ProcessBuilder

ProcessBuilder

ProcessBuilder相对于Runtime传参要复杂一些,都是以数组或列表的形式。

eg:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
List<String> commmands = new ArrayList<>();
commmands.add("ps aux | grep abc");

ProcessBuilder pb = new ProcessBuilder(commmands);
Process process = pb.start();

BufferedReader std = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder strBuilder = new StringBuilder();

String stdLine;
while((stdLine = std.readLine()) != null) {
System.out.println(stdLine);
strBuilder.append(stdLine).append("\r\n");
}

但是要注意了,这样会出问题。因为ProcessBuilder要求我们如果要执行的命令带有参数,我们需要把命令拆分开来,一个一个的放到数组里面才能正常执行,但是这样很不友好呀,我一个命令很长很长的时候怎办呢?这个时候可以用到sh -c。

我们可以man一下sh的用法,sh -c 后面跟字符串,这样就可以放入一个完整的命令啦。

所以修改一下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
List<String> commmands = new ArrayList<>();
commmands.add("sh");
commmands.add("-c");
commmands.add("ps aux | grep abc");

ProcessBuilder pb = new ProcessBuilder(commmands);
Process process = pb.start();

BufferedReader std = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder strBuilder = new StringBuilder();

String stdLine;
while((stdLine = std.readLine()) != null) {
System.out.println(stdLine);
strBuilder.append(stdLine).append("\r\n");
}

然后再执行发现返回结果里面有grep命令本身的进程信息,所以过滤掉,修改命令

1
ps aux | grep abc   =>   ps aux | grep abc | grep -v grep

当然如果和我一样用的windows系统,不好调试的话可以参考我之前文章

IDEA调试Jar包

zhangxingrui wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!