关于 CliDriver, 参考 Hive源码分析:CLI入口类
这个入口天生是为 Hive 的 shell 提供的,当我在自己的应用里想提交一个 Hive 任务时,却发现不能直接使用(之前 MR 的 RunJar 就可以)。
正如上面的 Hive 源码分析讲的, CliDriver 做了很多的工作,那我只能 hack 一下了。
拷贝了 CliDriver 的源码后,要做的工作有
- hack log4j 为了使用自己的配置
- 重新定义输出流以获取执行 HQL 的结果
hack log4j 很容易做到,有这么一段代码,重新初始化了log4j
boolean logInitFailed = false;
String logInitDetailMessage;
try {
logInitDetailMessage = LogUtils.initHiveLog4j();
} catch (LogInitializationException e) {
logInitFailed = true;
logInitDetailMessage = e.getMessage();
}
这个导致我们在外边无论怎么捣腾都没法配置日志系统,注释掉这段代码就 OK 了。
重新定义输出流需要看这里
CliSessionState ss = new CliSessionState(new HiveConf(SessionState.class));
ss.in = System.in;
try {
ss.out = new PrintStream(System.out, true, "UTF-8");
ss.info = new PrintStream(System.err, true, "UTF-8");
ss.err = new CachingPrintStream(System.err, true, "UTF-8");
} catch (UnsupportedEncodingException e) {
return 3;
}
重新定义下
ss.out = new YourHivePrintStream();
这些做完后,并不能执行需要 MR 的Hive, 问题是你必须解决 UGI 的冲突,不然你会遇到各种没有权限的异常,比如
[25-11:04:58,499] [ERROR] [main] [hive.ql.Driver] Authorization failed:No privilege 'Select' found for inputs { database:db, table:tb}. Use show grant to get more details.
这里有一个大坑,你想找到权限异常的原因,根本无法理解这个逻辑,权限这个东西是在 HDFS 端定义好的,登录到 HDFS 看到权限配置都正常的啊,而且直接使用 Hive 命令行都能正常执行的好吧
最后,盯着日志从头看,发现有个警告
[25-11:04:53,106] [WARN ] [main] [hadoop.security.UserGroupInformation] No groups available for user gdpi
[25-11:04:53,108] [WARN ] [main] [hadoop.security.UserGroupInformation] No groups available for user gdpi
还连续警告了两次,只能查看源码来找原因了,首先找到这句警告信息的出处
public synchronized String[] getGroupNames() {
ensureInitialized();
try {
List<String> result = groups.getGroups(getShortUserName());
return result.toArray(new String[result.size()]);
} catch (IOExc