- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在解析执行这个复合命令的结果
ntpq -c peers | awk ' $0 ~ /^*/ {print $9}'
为了获取 Activity ntp服务器的偏移量。
这是定期使用和执行的java代码
public Double getClockOffset() {
Double localClockOffset = null;
try {
String[] cmd = {"/bin/sh",
"-c",
"ntpq -c peers | awk \' $0 ~ /^\\*/ {print $9}\'"};
Process p = Runtime.getRuntime().exec(cmd);
p.waitFor();
BufferedReader buf = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = buf.readLine();
if (!StringUtils.isEmpty(line)) {
localClockOffset = Double.parseDouble(line.trim());
} else {
// Log "NTP -> Empty line - No active servers - Unsynchronized"
}
} catch (Exception e) {
// Log exception
}
return localClockOffset;
}
ntpq 结果示例
> remote refid st t when poll reach delay offset jitter
> ==============================================================================
> *server001s1 .LOCL. 1 u 33 64 377 0.111 -0.017 0.011
> +server002s1 10.30.10.6 2 u 42 64 377 0.106 -0.006 0.027
> +server003s1 10.30.10.6 2 u 13 64 377 0.120 -0.009 0.016
请注意 awk 搜索以“*”开头的第一行并提取其第九列。在示例中:-0.017
问题是有时我会收到 no-active-servers 日志消息 - 旨在在没有带“*”的服务器时出现 - 而通过控制台执行命令会返回一个数字。
我知道我没有关闭该代码中的 BufferedReader
但这是此行为的原因吗?在每个方法调用中都会创建一个新实例(并在垃圾收集之前保持打开状态),但我认为这不应该是导致此问题的原因。
最佳答案
Runtime.exec()
只是调用其中的 ProcessBuilder,就像这样:
public Process More ...exec(String[] cmdarray, String[] envp, File dir)
throws IOException {
return new ProcessBuilder(cmdarray)
.environment(envp)
.directory(dir)
.start();
}
因此,使用它代替 ProcessBuilder
没有任何问题。
问题是你调用了:
p.waitFor();
在您获得 InputStream
之前。
这意味着当您获得 InputStream
时,该进程已经终止,并且输出流数据可能对您可用,也可能不可用,具体取决于操作系统缓冲实现的细微差别以及精确的操作时间。
因此,如果您将 waitFor()
移至底部,您的代码应该会开始更可靠地工作。
然而,在 Linux 下,您通常应该能够从 PIPE 缓冲区读取剩余数据,即使在写入过程结束后也是如此。
还有 UNIXProcess OpenJDK 中的实现实际上明确地使用了它,并在进程退出后尝试耗尽剩余数据,以便可以回收文件描述符:
/** Called by the process reaper thread when the process exits. */
synchronized void processExited() {
synchronized (closeLock) {
try {
InputStream in = this.in;
// this stream is closed if and only if: in == null
if (in != null) {
byte[] stragglers = drainInputStream(in);
in.close();
this.in = (stragglers == null) ?
ProcessBuilder.NullInputStream.INSTANCE :
new ByteArrayInputStream(stragglers);
}
} catch (IOException ignored) {}
}
}
这似乎足够可靠,至少在我的测试中是这样,所以很高兴知道您正在运行哪个特定版本的 Linux|Unix 和 JRE。
您是否也考虑过应用程序级问题的可能性?IE。 ntpq
并不能真正保证总是返回 *
行。
所以,最好从管道中删除 awk
部分,看看是否始终会有一些输出。
另一件需要注意的事情是,如果您的 shell 管道步骤之一失败(例如 ntpq 本身),您还将得到一个空输出,因此您还必须跟踪 STDERR(例如通过将其与 STDOUT 合并ProcessBuilder
)。
旁注
在开始使用数据之前执行 waitFor
在任何情况下都是一个坏主意,因为如果您的外部进程将产生足够的输出来填充管道缓冲区,它就会挂起等待某人阅读它,这永远不会发生,因为您的 Java 进程将同时被锁定在 waitFor
中。
关于java - 空字符串解析ntpq命令结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46583758/
我正在开发一个 JSP Web 应用程序,用于监视办公室中不同 HP-ux 和 Linux 服务器的系统参数。我正在使用 jsch 来在远程系统上执行命令。我的问题是 jsch 对于像 ntpq -p
在我们的代码中,我们使用 ntpd 从服务器获取时间并设置时间。执行 ntpd 命令后,我们运行“ntpq -p”来检查服务器偏移量。我们在不同的进程中并在完成该 ntpq 之后运行以下 ntpd 命
我是一名优秀的程序员,十分优秀!