1.问题描述
在进行spark-sql查询时,以yarn client的模式提交spark任务,任务是创建SparkSession,并执行sql脚本,在执行sql的过程中报Permission Denied错误。如下图所示:
上面是最高层的报错堆栈,最底层的报错还在UnixFileSystem.createFileExeclusively报错。如下图所示:
创建文件时没有权限。
2.问题分析
根据错误堆栈信息,发现代码出错的地方在如下代码中,在创建sparksession时,需要创建临时文件,就是在创建临时文件时报错了
/**
* @param conf
* @return per-session temp file
* @throws IOException
*/
private static File createTempFile(HiveConf conf) throws IOException {
String lScratchDir = HiveConf.getVar(conf, HiveConf.ConfVars.LOCALSCRATCHDIR);
String sessionID = conf.getVar(HiveConf.ConfVars.HIVESESSIONID);
return FileUtils.createTempFile(lScratchDir, sessionID, ".pipeout");
}
对应的HiveConf参数定义如下
LOCALSCRATCHDIR("hive.exec.local.scratchdir", "${system:java.io.tmpdir}" + File.separator + "${system:user.name}", "Local scratch space for Hive jobs"),
HIVESESSIONID("hive.session.id", "", “"),
java.io.tmpdir的默认值为“/tmp/”,也就是说,文件一般在/tmp/目录下。
3.解决方案
这个报错根据场景的不同对应不同的解决方案。
如果设置了hive.exec.local.scratchdir参数,只要把对应的目录权限修改即可。当前环境对应的scratchdir为/data/emr/hive/tmp/目录,所以只需要把/data/emr/hive/tmp/目录权限修改为777即可。
如果没有设置hive.exec.local.scratchdir参数,scratchdir默认值与当前任务的启动用户相关,用户名也是一层子目录。理论上来说不会有这个问题,所以不设置hive.exec.local.scratchdir参数也是一种结局方案。