代码之家  ›  专栏  ›  技术社区  ›  pavanlimo

从java调用shell脚本挂起

  •  1
  • pavanlimo  · 技术社区  · 15 年前

    这会挂起进程,并且永远不会完成。

    但是,在shell脚本中,如果我将脚本的输出重定向到某个日志文件或/dev/null,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 回复  |  直到 15 年前
        1
  •  6
  •   Andrzej Doyle    15 年前

    那是因为你不是在看报纸 Process '输出。

    根据 class' Javadocs ,如果不这样做,可能会导致死锁;进程填充其IO缓冲区,并等待“shell”(或侦听进程)从中读取并清空它。同时,您的进程(应该这样做)正在阻塞,等待进程退出。

    你会想打电话的 getInputStream() 并可靠地读取(可能来自另一个线程)以停止进程阻塞。

    还可以看看 Five Java Process Pitfalls When Runtime.exec() Won't -这两篇文章都是关于 过程

        2
  •  2
  •   Paul Tomblin    15 年前

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

        3
  •  0
  •   Matti Lyra    15 年前

    大致如下:

    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) {}
            }
        }
    }