在java应用程序中执行shell脚本

时间:2013-09-05 10:10:26

标签: java linux shell

我正在编写java应用程序,它给了我一个端口号。正在聆听特定港口的应用程序。

我想获得端口号。正在侦听端口10001的应用程序

Process p = Runtime.getRuntime().exec("lsof -i:10001 | awk '{print $2}'");
InputStream is=p.getInputStream();
byte b[]=new byte[is.available()];
is.read(b,0,b.length);
System.out.println(new String(b));
p.waitFor();
System.out.println("exit: " + p.exitValue());
p.destroy();

lsof -i:10001 | awk '{print $2}'当我在shell中执行它时,它会得到输出

PID
8092

但是在java应用程序中它给了我exit: 1。为什么它不在java中运行?我也可以只获得端口吗?即代替PID 8091我想要8092

2 个答案:

答案 0 :(得分:1)

试试这个

String[] cmd = { "/bin/sh", "-c", "lsof -i:10001 | awk '{print $2}'" };
Process p = Runtime.getRuntime.exec(cmd);

即我们使用-c选项运行shell,这意味着第3个参数是shell脚本字符串

答案 1 :(得分:0)

您无法直接在Runtime.exec中使用管道(仅通过运行/bin/sh流程并让 处理管道)。更好的方法可能是将lsof作为外部进程,然后在Java代码中提取第二个字段,而不是使用awk

另请注意,available()方法返回流知道它可以立即为您提供的多个字节而不会阻塞,但这并不一定意味着以后将无法使用更多字节。使用此方法的返回值来分配用于保存此流中所有数据的缓冲区是“永远不正确的”。 (quote from InputStream JavaDoc)。你需要继续阅读,直到你击中EOF。 Apache commons-io提供useful utility methods来帮助解决这个问题。

ProcessBuilder pb = new ProcessBuilder("lsof", "-i:10001");
pb.redirectError(ProcessBuilder.Redirect.to(new File("/dev/null")));
Process p = pb.start();
try {
  List<String> lines = IOUtils.readLines(p.getOutputStream());
  if(lines.size() > 1) {
    // more than one line, so the second (i.e. lines.get(1)) will have the info
    System.out.println(lines.get(1).split("\s+")[1]);
  } else {
    System.out.println("Nothing listening on port 10001");
  }
} finally {
  p.getOutputStream().close();
  p.waitFor();
}