我在大学的一些机器上设置了一个 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 的命令从未真正执行过。我对如何调试这里发生的事情感到非常困惑,任何提示将不胜感激!