【问题标题】:Run command line process from Java synchronously从 Java 同步运行命令行进程
【发布时间】:2021-11-06 03:56:47
【问题描述】:

我正在从 Java 运行命令行程序(ClamAV 病毒扫描程序),如下所示。我需要同步运行它,因为它在 AWS Lambda 中运行,如果它异步运行,则 lambda 将提前终止。似乎“很多”次它没有完成就出来了。解决此问题的最佳方法是什么?我添加了丑陋的线程。睡眠稍微改善了一些情况。我实际上不介意走那条路,但需要找到它应该睡觉的确切地方。请帮忙!

    Runtime rt = Runtime.getRuntime();
    Process proc = rt.exec(command);
    BufferedReader inputReader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
    BufferedReader errorReader = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
    String line;
    StringBuilder out = new StringBuilder();
    int exitValue = proc.waitFor();
    logger.info("Exit Value:" + exitValue);
    while ((line = inputReader.readLine()) != null) {
        out.append("\n").append(line);
    }
    if (exitValue != 0) {
        while ((line = errorReader.readLine()) != null) {
            out.append("\n").append(line);
            logger.error(line);
        }
    }

【问题讨论】:

  • 在进程终止之前,对 waitFor 的调用不应返回。您正在运行的命令是什么?也许命令本身(clamav)分叉并返回?如果是这样,那么 Java 代码本身就没有问题。当你运行这个时你得到什么输出?
  • 在大多数情况下,我确实得到了 clamscan(命令)的完整输出。但有时它会在没有输出的情况下返回。输出是进程的标准输出。
  • 您无法可靠地读取已终止进程的输出(或错误)。 您已阅读流之后致电proc.waitFor()

标签: java aws-lambda


【解决方案1】:

exec 方法在 javadoc 所述的不同进程中执行:

单独的进程中执行指定的字符串命令。

你可以做的是让主线程处于等待状态,直到你知道被分离的线程已经完成了他的任务。您可以使用 Process 类的方法 waitFor 来做到这一点:

如有必要,使当前线程等待,直到此 Process 对象表示的进程终止

【讨论】:

  • watiFor 是否有可能等到进程完成,但收集进程的输出需要几秒钟?这只是我的猜测。如果我用 5 秒执行 waitFor(),它会等待 5 秒,还是会在有退出信号时立即出现?
  • 确保刷新流。可能只是流没有被刷新。
  • 你的意思是 inputReader.close() 和 errorReader.close() ? proc.destroy() 是否也需要做什么或需要?谢谢!
  • 我只是想在尝试之前确认一下。 proc.destroy() 实际上在某些情况下会出错,可能是因为它已经关闭了?
猜你喜欢
  • 1970-01-01
  • 2012-04-10
  • 1970-01-01
  • 2021-04-08
  • 2011-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多