我正在编写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
答案 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();
}