有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

exec在Java中执行命令而不重定向输出

如何从Java程序运行外部命令(通过shell),以便不发生重定向,并等待命令结束?我希望外部程序的文件描述符与Java程序的文件描述符相同。特别是我不希望将输出重定向到Java程序正在读取的管道。让Java程序中继输出不是一个解决方案

这意味着^{}的简单调用不是解决方案。我假定涉及^{},但如何指定输出和错误流必须与调用Java进程相同

class A {
    public static void main(String[] args) {
        try {
            ProcessBuilder pb = new ProcessBuilder("echo", "foo");
            /*TODO: pb.out = System.out; pb.err = System.err;*/
            Process p = pb.start();
            p.waitFor();
        } catch (Exception e) {
            System.err.println(e);
            System.exit(1);
        }
    }
}

(这可能是正确的方法,也可能不是正确的方法。)

换句话说,我正在寻找Java的system,但我能找到的(大致上)是popen

下面是一个中继无法工作的示例:如果子进程同时写入stdout和stderr,并且Java程序正在中继,那么Java程序无法知道子进程中write调用的顺序。因此,如果两个流最终位于同一个文件中,那么Java程序在stdout和stderr上的输出顺序将明显不同。混合使用stdout和stderr当然不是一个解决方案,因为调用方可能希望将它们分开

虽然我认为这个问题是大家都感兴趣的,但Linux特定的解决方案可以解决我眼前的问题


共 (3) 个答案

  1. # 1 楼答案

    您可以看看NuProcess项目。免责声明:是我写的。它提供来自派生进程的非阻塞I/O。您仍然需要在Java中进行中继(您会收到回调),但因为它在Linux中使用epoll(),所以我希望它能够保持底层程序的顺序。只有一个线程正在对管道进行epoll(),因此不会出现任何线程调度顺序问题

    我敢肯定,MacOS X或任何BSD变体都会100%保留订单,因为它使用的是一个绝对有序的kqueue。无论如何,您可能想尝试一下,编写代码和测试都很简单

  2. # 2 楼答案

    这就是在Java7中引入的^{}/^{}的意图。使用^{}将使子进程与Java进程共享stderr/stdout:

    class A {
        public static void main(String[] args) {
            try {
                ProcessBuilder builder = new ProcessBuilder("echo", "foo");
                builder.redirectError(ProcessBuilder.Redirect.INHERIT);
                builder.redirectOutput(ProcessBuilder.Redirect.INHERIT);
                Process p = builder.start();
                p.waitFor();
            } catch (Exception e) {
                System.err.println(e);
                System.exit(1);
            }
        }
    }
    
  3. # 3 楼答案

    不能。默认情况下,子进程的所有标准I/O都重定向到父进程(运行java程序的jvm)

    from the javadoc of the Process class

    By default, the created subprocess does not have its own terminal or console. All its standard I/O (i.e. stdin, stdout, stderr) operations will be redirected to the parent process, where they can be accessed via the streams obtained using the methods getOutputStream(), getInputStream(), and getErrorStream(). The parent process uses these streams to feed input to and get output from the subprocess. Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, or even deadlock.