实现hive proxy3-日志目录权限问题解决

  使用proxy之后,目录名为proxy之后的用户名目录,但是生成的文件属主是当前登陆用户,导致不能正常写入,日志目录的创建在org.apache.hadoop.hive.ql.history.HiveHistoryImpl类中,
更改后的构造方法(增加了proxy之后的代码):

public HiveHistoryImpl(SessionState ss) {
  try {
    console = new LogHelper(LOG);
    if(ss.getConf().getBoolVar(HiveConf.ConfVars.HIVE_USE_CUSTOM_PROXY)){
       LOG.warn("user custom proxy,gen history log file");
        proxyUser = ss.getConf().getVar(HiveConf.ConfVars.HIVE_CUSTOM_PROXY_USER);
        if(("").equals(proxyUser)||proxyUser == null||("hdfs").equals(proxyUser)){
            console.printError("gen history file,use proxy,but proxy user is " + proxyUser);
            return;
        }
        conf_file_loc = System.getProperty("java.io.tmpdir") + File.separator + proxyUser;
    }else {
        conf_file_loc = ss.getConf().getVar(
        HiveConf.ConfVars.HIVEHISTORYFILELOC);
    }
    LOG.warn("user history log dir is " + conf_file_loc);
    if ((conf_file_loc == null) || conf_file_loc.length() == 0) {
      console.printError("No history file location given");
      return;
    }
    // Create directory
    File histDir = new File(conf_file_loc);
    if (!histDir.exists()) { //目录的创建逻辑
      if (!histDir.mkdirs()) {
        console.printError("Unable to create log directory " + conf_file_loc);
        return;
      }
    }
    do {
      histFileName = conf_file_loc + File.separator + "hive_job_log_" + ss.getSessionId() + "_"
        + Math.abs(randGen.nextInt()) + ".txt";
    } while (! new File(histFileName).createNewFile());
    console.printInfo("Hive history file=" + histFileName);
    histStream = new PrintWriter(histFileName);
    HashMap<String, String> hm = new HashMap<String, String>();
    hm.put(Keys.SESSION_ID.name(), ss.getSessionId());
    log(RecordTypes.SessionStart, hm);
  } catch (IOException e) {
    console.printError("FAILED: Failed to open Query Log : " + histFileName
        + " " + e.getMessage(), "\n"
        + org.apache.hadoop.util.StringUtils.stringifyException(e));
  }
}

日志目录的创建相关代码:

    // Create directory
    File histDir = new File(conf_file_loc);
    if (!histDir.exists()) { //目录的创建逻辑
      if (!histDir.mkdirs()) {
        console.printError("Unable to create log directory " + conf_file_loc);
        return;
      }
    }

一个思路,我们可以把这个目录的权限设大一点,比如777,这里调用了File.mkdirs()方法
(File的mkdirs方法,存在返回false,不存在返回true,创建失败返回false),在File类中最终调用了FileSystem.createDirectory()方法,在File的源码中我们可以看到有如下方法可以设置目录的权限:

    public boolean setWritable( boolean writable, boolean ownerOnly) {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkWrite( path);
        }
        if (isInvalid()) {
            return false ;
        }
        return fs.setPermission(this, FileSystem ACCESS_WRITE, writable, ownerOnly);
    }

可以通过这个方法来更改日志目录的权限,更改HiveHistoryImpl相关的代码如下:

private boolean createDir;
.....
// Create directory
File histDir = new File(conf_file_loc);
if (!histDir.exists()) {
  if (!histDir.mkdirs()) {
    console.printError("Unable to create log directory " + conf_file_loc);
    return;
  }else{
    LOG.warn("create dir success,start chmod,dir is " + histDir);
    createDir = histDir.setWritable(true,false);
  }
}else{
    LOG.warn("dir already exists,start chmod,dir is " + histDir);
    createDir = histDir.setWritable(true,false);
}
do {
  histFileName = conf_file_loc + File.separator + "hive_job_log_" + ss.getSessionId() + "_"
    + Math.abs(randGen.nextInt()) + ".txt";
} while (! new File(histFileName).createNewFile());

不过这里有个限制,因为不能更改别的用户的日志目录权限,因此要求是新建目录(不能更改旧的目录),最好的方法还是日志文件不要用proxy之后的用户文件就可以啦。

你可能感兴趣的:(hive,权限,日志文件)