0

我正在编写 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

4

2 回答 2

1

试试这个

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

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

于 2013-09-05T10:15:32.277 回答
0

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

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

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();
}
于 2013-09-05T11:09:36.627 回答