从java调用shell脚本挂起

时间:2010-08-06 16:27:17

标签: java shell

所以我试图执行一个shell脚本,它从Java文件中产生大量输出(以100s为单位)。 这会挂起过程,永远不会完成。

但是,在shell脚本中,如果我将脚本的输出重定向到某个日志文件或/ dev / null 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

免费啤酒以获得正确答案。 :)

3 个答案:

答案 0 :(得分:5)

这是因为你没有从Process'输出中读取。

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

您需要调用getInputStream()并从中可靠地读取(可能来自其他线程)以停止进程阻止。

另请查看Five Java Process PitfallsWhen Runtime.exec() Won't - 有关Process常见问题的资料性文章。

答案 1 :(得分:2)

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

答案 2 :(得分:0)

输入/输出缓冲区的大小有限(取决于操作系统)。如果我没记错的话,这至少不是Windows XP或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) {}
        }
    }
}