java - 在 Java 中执行外部命令的经典问题?

标签 java redirect stream command external

好吧 - 这对很多人来说都是一个问题 - 由于我还没有看到有效的答案,我想我应该表达这个问题,以便解决这个问题的人可以告诉我们其他人。

问题是下面三分之二的代码工作得很好。

reader3 的实例演示了该问题。 Reader3 无法读取外部文件成功启动的结果。尝试在 stdin 或 stderr InputStream 上执行任何类型的读取(realine 等)将永远阻塞:

package Problems;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class RunningProblem {

public static class RunningReader implements Runnable {

    private Process proc;
    private String sName;

    private RunningReader(Process proc1, String sName) {
        this.proc = proc1;
        this.sName = sName;
    }

    public void run() {
        try {                
            // InputStreamReader in = new InputStreamReader(proc.getInputStream());
            // BufferedReader reader = new BufferedReader(in);

            InputStreamReader err = new InputStreamReader(proc.getErrorStream());
            BufferedReader reader = new BufferedReader(err);

            String line = reader.readLine();
            while (line != null) {
                System.out.println(sName + ": " + line);
                line = reader.readLine();
            }
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

public static void main(String[] args) {
    ExecutorService pool = Executors.newFixedThreadPool(3);
    try {
        Runtime rt = Runtime.getRuntime();

        Process proc1 = rt.exec("ps ax");
        RunningReader reader1 = new RunningReader(proc1, "reader1");

        Process proc2 = rt.exec("ls -l /");
        RunningReader reader2 = new RunningReader(proc2, "reader2");

        Process proc3 = rt.exec("/bin/tar");
        RunningReader reader3 = new RunningReader(proc3, "reader3");

        pool.execute(reader3);
        pool.execute(reader2);
        pool.execute(reader1);

    } catch (Exception ex) {
        System.err.println(ex.getMessage());
    } finally {
        pool.shutdown();
    }
    System.out.println("Launcher.main() Exited.");
}

}

最佳答案

您没有显示程序产生的输出,但我猜可能是这样,ps axls -l/不会产生输出,但/bin/tar会产生输出。原因是,前两个命令会在 stdout 上生成输出,但不会在 stderr 上生成输出,而后者会在 stderr 上生成输出(因为您没有向 tar 提供有效参数),但不会在 stdout 上生成输出。

以下是在 shell 中运行命令时的区别:

[axe@gromp tmp]$ ps ax > ps-std.txt 2> ps-err.txt
[axe@gromp tmp]$ ls -l / > ls-std.txt 2> ls-err.txt
[axe@gromp tmp]$ /bin/tar > tar-std.txt 2> tar-err.txt
[axe@gromp tmp]$ ls -lrt
total 18
-rw-r--r-- 1 axe users    0 Mar  5 19:40 ps-err.txt
-rw-r--r-- 1 axe users 7191 Mar  5 19:40 ps-std.txt
-rw-r--r-- 1 axe users    0 Mar  5 19:40 ls-err.txt
-rw-r--r-- 1 axe users  937 Mar  5 19:40 ls-std.txt
-rw-r--r-- 1 axe users    0 Mar  5 19:41 tar-std.txt
-rw-r--r-- 1 axe users  142 Mar  5 19:41 tar-err.txt
[axe@gromp tmp]$ 

使用 > 重定向标准输出,使用 2> 将错误输出重定向到不同的文件,您可以看到 tarstderr 上生成消息,在 stdout 上生成另外两个消息(其他文件的文件大小为零,没有输出)。

可能是这样吗?如果你运行会发生什么,例如。 G。 echo "Foo" 而不是 tar 作为第三个进程?

关于java - 在 Java 中执行外部命令的经典问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5205849/

相关文章:

java - 使用递归求出可被 x 整除的数字之和

java - 从 ISO/IEC 19794-4 图像数据文件创建图像

java - 成功登录后,Spring 总是重新编辑到默认目标 URL

ios - 重定向到 native 邮件应用程序的 AppStore

c# - 处理临时文件流

java - 保存列表的大小而不更新它

java - 编译 Android 应用程序时出错 - 任务 :app:transformClassesWithDexForDebug 执行失败

.htaccess - 301 从 old.com 重定向到 new.com

c# - 如何跳过流中的字节

c++ - istream 不消耗字符?