美文网首页
Java 执行命令

Java 执行命令

作者: HungryBird | 来源:发表于2019-03-13 21:04 被阅读0次

    在进行开发的时候, 我们有时候需要通过命令来执行别的程序,并获取返回结果。

        public static void main(String[] args) throws Exception{
    
            String cmd = "ls";
    
            Process ps = Runtime.getRuntime().exec(new String[]{"sh", "-c", cmd});
            
            String stdout = new String(readAll(ps.getInputStream()));
            String stderr = new String(readAll(ps.getErrorStream()));
    
            ps.waitFor();
    
            System.out.println("stdout is :" + stdout);
            System.out.println("stderr is :" + stderr);
            System.out.println("exit code is :" + exitCode);
        }
    
    
        static byte[] readAll(InputStream is) throws Exception{
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            byte[] bytes = new byte[1024];
            int n;
            while (( n = is.read(bytes)) != -1) {
                os.write(bytes, 0, n);
            }
            return os.toByteArray();
        }
    
    

    但是在实际使用过程中有时会出现问题, 调用命令启动的子进程会卡住,永远得不到返回。

    原因是: 子进程和父进程之间建立管道连接, 子进程的错误输出和标准输出会向两个不同的管道进行写入,而管道的缓冲区有大小限制,当子进程执行过程中错误输出过多,并且没有标准输出时。 java进程的读标准输出时会block住,而子进程把管道缓冲区打满,子进程也会block住,这样就会产生死锁。

    解决方案: 启动两个线程来读取输出

        public static void main(String[] args) throws Exception{
    
            String cmd = "ls";
    
            Process ps = Runtime.getRuntime().exec(new String[]{"sh", "-c", cmd});
    
            Future<String> stdoutFuture =
                    Executors.newSingleThreadExecutor().submit(() -> new String(readAll(ps.getInputStream())));
            Future<String> stderrFuture =
                    Executors.newSingleThreadExecutor().submit(() -> new String(readAll(ps.getErrorStream())));
    
            int exitCode = ps.waitFor();
    
            System.out.println("stdout is :" + stdoutFuture.get());
            System.out.println("stderr is :" + stderrFuture.get());
            System.out.println("exit code is :" + exitCode);
        }
    
    
        static byte[] readAll(InputStream is) throws Exception{
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            byte[] bytes = new byte[1024];
            int n;
            while (( n = is.read(bytes)) != -1) {
                os.write(bytes, 0, n);
            }
            return os.toByteArray();
        }
    
    

    相关文章

      网友评论

          本文标题:Java 执行命令

          本文链接:https://www.haomeiwen.com/subject/kmotmqtx.html