0

我在大学的一些机器上设置了一个 Hadoop YARN 集群(所有机器都运行 Linux Fedora 25)。在 YARN 中运行 mapreduce 作业时,我无法接收对单独程序的调用的输出。有趣的是,如果我在本地运行我的工作(在 mapred-site.xml 中配置),我调用程序并接收其输出的方法就可以正常工作。下面是我的 executeShellCommand 类,它在我的第一个地图任务中被实例化并使用。

public class ExecuteShellCommand {


    public String executeCommand(String command) {

        StringBuffer output = new StringBuffer();
        Process p;
        try {
            String [] args = command.split(" ");
            String cmd = args[0];
            ProcessBuilder pb = new ProcessBuilder().command(cmd, args[1], args[2], args[3], args[4], args[5], args[6], args[7]).directory(new File("path to executable"));
            p = pb.start();
            BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
            p.waitFor();
            String line = "";
            while ((line = reader.readLine())!= null) {
                output.append(line + "\n");

            }

        } catch (Exception e) {
            e.printStackTrace();
            return e.toString();
            }
    return output.toString();

    }

}

我一定要检查的事情:

1) 为所有需要的文件/目录适当地设置了权限

2)地图任务以当前用户(我)运行,所以非法访问没有问题

3)我没有收到文件未找到异常,所以我正在调用的程序的路径是正确的

4) 检查进程 p 的输入/输出流(输入流设置为 java.lang.UNIXProcess$ProcessPipeInputStream@1000e80,输出流为空)

5)我没有调用我需要使用的程序,而是尝试了一个简单的“echo”命令,但也无法接收到该输出。

6)我也尝试过使用

p = Runtime.getRuntime().exec("myCommand")

但结果是一样的(没有收到输出)

正如我已经提到的,当我在本地运行作业时,我的 executeCommand 方法运行良好,并从我调用的程序返回输出。只有在 YARN 中才会出现问题。我有一种感觉,要么没有从正确的缓冲区读取,要么发出给 ProcessBuilder 的命令从未真正执行过。我对如何调试这里发生的事情感到非常困惑,任何提示将不胜感激!

4

1 回答 1

0

经过数小时尝试各种解决方案后,我想出了如何从 ProcessBuilder 生成的进程中获取错误流。结果是,当我为进程设置工作目录时,我忘记将路径更新为我传递给它的参数之一。哦!!!

于 2016-12-12T00:50:21.743 回答