【问题标题】:How to wait for multi-threaded shell script execution to finish called inside my web service?如何等待多线程 shell 脚本执行完成在我的 Web 服务中调用?
【发布时间】:2016-11-16 08:53:12
【问题描述】:

我有一个使用 processBuilder 执行 myscript.sh 的 java restful 服务方法。我的脚本接受一个输入(例如 - myscript.sh /path/to-a/folder)。 在脚本里面是这样的

-> execute a command which is multithreaded i.e parallel processing
-> echo "my message"

现在,当从 linux 命令行调用我的脚本时,它执行得很好。首先所有线程运行完成,然后在终端上显示线程命令执行的一些文本输出,然后显示我的消息。

但是当我使用 processBuilder 从 java 调用相同的脚本时,最后一条回显消息立即出现并且执行结束。

按照我从 java 调用脚本的方式

ProcessBuilder processBuilder = new ProcessBuilder("/bin/bash","/path/to/myscript.sh","/path/to/folder/data");
Process proc = processBuilder.start();
StringBuffer output = new StringBuffer();
        BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
        String line = "";
        while((line = reader.readLine()) != null){
            output.append(line + "\n");
        }

        System.out.println("### " + output);

我不知道发生了什么,如何调试也。 有人可以告诉我如何在从终端或从 java processBuilder 运行时从 shell 脚本中获得相同的行为吗?

【问题讨论】:

  • 你能发布你的脚本在做什么吗?上面看起来不错,除非有一些异常处理。
  • 您是否在 shell 脚本的后台运行任何可执行文件?如果是这样,您的脚本可能在完成之前就返回了......因此会杀死可执行文件(或使其成为孤立的)。
  • 您希望脚本在其并行工作完成之前一直阻塞吗?还是没有等待脚本完成的 Java 代码?

标签: java multithreading bash process


【解决方案1】:

使用 ProcessBuilder.redirectErrorStream(boolean redirectErrorStream) 和参数 true 将错误合并到输出中。或者,您也可以使用 shell 命令语法 cmd 2>&1 将错误与输出合并。

这些是您可能立即获得最后一个echo 语句的输出的一些情况(而不是脚本需要时间来运行并返回正确的结果):

  • 缺少环境变量
  • 启动的 bash 需要 source .bashrc 或者类似的资源文件
  • 启动的 bash 可能不在正确的目录中运行(您可以在 ProcessBuilder 中设置)
  • 启动的 bash 可能在其 PATH 中找不到某些脚本/可执行文件
  • 启动的 bash 可能无法在任何可执行文件的路径中找到合适的库

一旦合并错误,您就可以自己调试并查看错误。

【讨论】:

    【解决方案2】:

    在您的上下文中,可以通过两种方式生成单独的进程:

    1) 重击

    /path/to/executables/executable &
    

    这将生成一个新的可执行文件,您需要等待它完成。
    Here's an answer that will help you.

    2)Java

    Process exec = Runtime.getRuntime().exec(command);
    status = exec.waitFor();
    

    基本上,您需要等待进程结束才能开始读取其 std/err 流。
    如果我正确理解了问题,只需将这一行添加到您的代码中就足够了:status = exec.waitFor()(在您获取流之前)

    这是 Process.waitFor() 的 JavaDoc:

    如有必要,使当前线程等待,直到此 Process 对象表示的进程终止。如果子进程已经终止,则此方法立即返回。如果子进程尚未终止,则调用线程将被阻塞,直到子进程退出。

    返回: 此 Process 对象表示的子进程的退出值。按照惯例,值 0 表示正常终止。 抛出: InterruptedException - 如果当前线程在等待时被另一个线程中断,则等待结束并抛出 InterruptedException

    【讨论】:

      猜你喜欢
      • 2016-05-23
      • 2014-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多