调用jar包把风电数据往hdfs写数据无权限问题 错误信息:hadoop.security.AccessControlException:Permission denied:user=gcl,access=write,inode:"":jeff:hive:-rw-r--r-- 首先想到的两个方法: 1、将hdfs-core.xml配置文件的dfs.permisssions参数修改为false 2、修改操作文件的权限 但是这两种方法都很僵,不够优雅
因为user=gcl,这里我所期望的是系统的用户名为hive,于是就想configuration这个配置类有没有在哪段源码里设置以哪个用户运行?
org.apache.hadoop.security.UserGroupInformation有一个静态方法:getCurrentUser()。它会返回一个UserGroupInformation类的实例,如果subject为空,或者这个subject中与org.apache.hadoop.security.User对应的Principal为空,那么说明尚未登录过,调用getLoginUser()创建UserGroupInformation的实例。 getLoginUser()的流程: 1.创建LoginContext: name:如果hadoop.security.authentication等于”kerberos”,那么是“hadoop-user-kerberos”或者“hadoop-keytab-kerberos”,否则是“hadoop-simple”。它的主要作用是作为appName传递给UserGroupInformation.HadoopConfiguration.getAppConfigurationEntry(String appName)方法。 subject: callbackHandler: 空 Configuration: UserGroupInformation.HadoopConfiguration的实例。 2.login.login(); 这个会调用HadoopLoginModule的login()和commit()方法。 HadoopLoginModule的login()方法是一个空函数,只打印了一行调试日志 LOG.debug("hadoop login"); commit()方法负责把Principal添加到Subject中。 此时一个首要问题是username是什么? 在使用了kerberos的情况下,从javax.security.auth.kerberos.KerberosPrincipal的实例获取username。 在未使用kerberos的情况下,优先读取HADOOP_USER_NAME这个系统环境变量,如果不为空,那么拿它作username。否则,读取HADOOP_USER_NAME这个java环境变量。否则,从com.sun.security.auth.NTUserPrincipal或者com.sun.security.auth.UnixPrincipal的实例获取username。 如果以上尝试都失败,那么抛出异常LoginException("Can’t find user name")。 最终拿username构造org.apache.hadoop.security.User的实例添加到Subject中。 配置完HADOOP_USER_NAME系统变量之后,文件夹所有者和使用者都将成为hive