【问题标题】:Calling a shell script from java hangs从 java 调用 shell 脚本挂起
【发布时间】:2010-08-06 16:27:16
【问题描述】:

所以我正在尝试执行一个 shell 脚本,该脚本从 Java 文件中产生大量输出(以 100 MB 为单位)。 这会挂起进程并且永远不会完成。

但是,在 shell 脚本中,如果我将脚本的输出重定向到某个日志文件或 /dev/null Java 文件,Java 文件会立即执行并完成。

是因为Java程序永远不会完成的数据量吗? 如果是这样,是否有任何此类文件?还是对数据量(记录)有任何限制?

您可以通过以下方式模拟此场景。

Java 文件如下所示:

import java.io.InputStream;

public class LotOfOutput {

    public static void main(String[] args) {
        String cmd = "sh a-script-which-outputs-huuggee-data.sh"; 
        try {
            ProcessBuilder pb = new ProcessBuilder("bash", "-c", cmd);
            pb.redirectErrorStream(true);
            Process shell = pb.start();
            InputStream shellIn = shell.getInputStream();
            int shellExitStatus = shell.waitFor();
            System.out.println(shellExitStatus);
            shellIn.close();
        } catch (Exception ignoreMe) {
        }
    }
}

脚本“a-script-which-outputs-huuggee-data.sh”可能如下所示:

#!/bin/sh
# Toggle the line below
exec 3>&1 > /dev/null 2>&1

count=1
while [ $count -le 1000 ]
do
        cat some-big-file
        ((count++))
done

echo
echo Yes I m done

答对的免费啤酒。 :)

【问题讨论】:

    标签: java shell


    【解决方案1】:

    这是因为您没有从 Process' 输出中读取数据。

    根据class' Javadocs,如果您不这样做,那么您可能会陷入僵局;该进程填充其 IO 缓冲区并等待“shell”(或侦听进程)从中读取并清空它。同时,您应该执行此操作的进程正在阻塞等待进程退出。

    您需要调用 getInputStream() 并可靠地读取(可能来自另一个线程)以停止进程阻塞。

    还可以查看Five Java Process PitfallsWhen Runtime.exec() Won't - 两篇关于Process 常见问题的信息性文章。

    【讨论】:

    【解决方案2】:

    您永远不会读取输入流,因此它可能会阻塞,因为输入缓冲区已满。

    【讨论】:

      【解决方案3】:

      输入/输出缓冲区的大小有限(取决于操作系统)。如果我没记错的话,这至少不是 Windows XP。尝试创建一个尽可能快地读取 InputStream 的线程。

      类似的东西:

      class StdInWorker
                  implements Worker
          {
              private BufferedReader br;
              private boolean run = true;
              private int linesRead = 0;
      
              private StdInWorker (Process prcs)
              {
                  this.br = new BufferedReader(
                          new InputStreamReader(prcs.getInputStream()));
              }
      
              public synchronized void run ()
              {
                  String in;
                  try {
                      while (this.run) {
                          while ((in = this.br.readLine()) != null) {
                              this.buffer.add(in);
                              linesRead++;
                          }
      
                          Thread.sleep(50);
                      }
                  }
                  catch (IOException ioe) {
                      ioe.printStackTrace();
                  }
                  catch (InterruptedException ie) {}
              }
          }
      }
      

      【讨论】:

      • 你能说一下工人阶级是什么
      猜你喜欢
      • 1970-01-01
      • 2021-06-08
      • 1970-01-01
      • 2012-06-04
      • 2013-09-22
      • 2012-03-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多