Hadoop集群环境部署在几个Linux服务器上,现在想使用windows上的Java客户端来操作集群中的HDFS文件,但是在客户端运行时出现了如下的认证错误,被折磨了几天,问题终得以解决。以此文记录问题的解决过程。

(如果想看最终解决问题的方法拉到最后,如果想看我的问题解决思路请从上向下看)

问题描述
上传文件的代码:

package com.cys.mapreduce;import java.io.IOException;
import java.util.StringTokenizer;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;public class WordsCount {public static class TokenizerMapper extendsMapper<Object, Text, Text, IntWritable> {private final static IntWritable one = new IntWritable(1);private Text word = new Text();public void map(Object key, Text value, Context context)throws IOException, InterruptedException {String line = value.toString();StringTokenizer itr = new StringTokenizer(line);while (itr.hasMoreTokens()) {word.set(itr.nextToken().toLowerCase());context.write(word, one);}}}public static class IntSumReducer extendsReducer<Text, IntWritable, Text, IntWritable> {private IntWritable result = new IntWritable();public void reduce(Text key, Iterable<IntWritable> values,Context context) throws IOException, InterruptedException {int sum = 0;for (IntWritable val : values) {sum += val.get();}result.set(sum);context.write(key, new IntWritable(sum));}}public static void main(String[] args) throws Exception {Configuration conf = new Configuration();String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();if (otherArgs.length != 2) {System.err.println("Usage: wordcount <in> <out>");System.exit(2);}@SuppressWarnings("deprecation")Job job = new Job(conf, "word count");job.setJarByClass(WordsCount.class);job.setMapperClass(TokenizerMapper.class);job.setCombinerClass(IntSumReducer.class);job.setReducerClass(IntSumReducer.class);job.setOutputKeyClass(Text.class);job.setOutputValueClass(IntWritable.class);FileInputFormat.addInputPath(job, new Path("hdfs://master:9000/input"));FileOutputFormat.setOutputPath(job, new Path("hdfs://master:9000/out3"));System.exit(job.waitForCompletion(true) ? 0 : 1);}
}

win7下eclipse中错误的详细描述如下:

org.apache.hadoop.security.AccessControlException: org.apache.hadoop.security .AccessControlException: Permission denied: user=Administrator, access=WRITE, inode="hadoop": hadoop:supergroup:rwxr-xr-x

其实这个错误的原因很容易看出来,用户Administator在hadoop上执行写操作时被权限系统拒绝.

解决问题的过程
看到这个错误的,第一步就是将这个错误直接入放到百度google里面进行搜索。找到了N多篇文章,但是主要的思路就如此篇文章所写的两个解决办法:http://www.cnblogs.com/acmy/archive/2011/10/28/2227901.html

1、在hdfs的配置文件中,将dfs.permissions修改为False

2、执行这样的操作 hadoop fs -chmod 777 /user/hadoop

对于上面的第一个方法,我试了行不通,不知道是自己设置错误还是其他原因,对我此法不可行,第二个方法可行。第二个方法是让我们来修改HDFS中相应文件夹的权限,后面的/user/hadoop这个路径为HDFS中的文件路径,这样修改之后就让我们的administrator有在HDFS的相应目录下有写文件的权限(所有的用户都是写权限)。

虽然上面的第二步可以解决问题了,上传之后的文件所有者为Administrator,但是总感觉这样的方法不够优雅,而且这样修改权限会有一定的安全问题,总之就是看着不爽,就在想有没有其他的办法?

问题分析
开始仔细的观察了这个错误的详细信息,看到user=Administrator, access=WRITE。这里的user其实是我当前系统(运行客户端的计算机的操作系统)的用户名,实际期望这里的user=hadoop(hadoop是我的HADOOP上面的用户名),但是它取的是当前的系统的用户名,很明显,如果我将当前系统的用户名改为hadoop,这个肯定也是可以行得通的,但是如果后期将开发的代码部署到服务器上之后,就不能方便的修改用户,此方法明显也不够方便。

现在就想着Configuration这个是一个配置类,有没有一个参数是可以在某个地方设置以哪个用户运行呢?搜索了半天,无果。没有找到相关的配置参数。

最终只有继续分析代码, FileSystem fs = FileSystem.get(URI.create(dest), conf);代码是在此处开始对HDFS进行调用,所以就想着将HADOOP的源码下下来,debug整个调用过程,这个user=Administator是在什么时间赋予的值。理解了调用过程,还怕找不到解决问题的办法么?

跟踪代码进入 FileSystem.get-->CACHE.get()-->Key key = new Key(uri, conf);到这里的时候发现key值里面已经有Administrator了,所以关键肯定是在new key的过程。继续跟踪UserGroupInformation.getCurrentUser()-->getLoginUser()-->login.login()到这一步的时候发现用户名已经确定了,但是这个方法是Java的核心源码,是一个通用的安全认证,但对这一块不熟悉,但是debug时看到subject里面有NTUserPrincipal:Administator,所以就想着搜索一下这个东西是啥,结果就找到了下面这一篇关键的文章:

http://www.udpwork.com/item/7047.html

在此篇文章里面作者分析了hadoop的整个登录过程,对于我有用的是其中的这一段:

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中。

看完这一段,我明白了执行login.login的时候调用了hadoop里面的HadoopLoginModule方法,而关键是在commit方法里面,在这里优先读取HADOOP_USER_NAME系统环境变量,然后是java环境变量,如果再没有就从NTUserPrincipal等里面取。关键代码为:

if (!isSecurityEnabled() && (user == null)) {
  String envUser = System.getenv(HADOOP_USER_NAME);
  if (envUser == null) {
    envUser = System.getProperty(HADOOP_USER_NAME);
  }
  user = envUser == null ? null : new User(envUser);
}
OK,看到这里我的需求也就解决了,只要在系统的环境变量里面添加HADOOP_USER_NAME=hadoop(HDFS上的有权限的用户,具体看自己的情况),或者在当前JDK的变量参数里面添加HADOOP_USER_NAME这个Java变量即可。我的情况添加系统环境变量更方法。

如果是在Eclipse里面运行,修改完环境变量后,记得重启一下eclipse,不然可能不会生效。

解决办法

1、在系统的环境变量或java JVM变量里面添加HADOOP_USER_NAME,这个值具体等于多少看自己的情况,以后会运行HADOOP上的Linux的用户名。(修改完重启eclipse,不然可能不生效)2、将当前系统的帐号修改为hadoop3、使用HDFS的命令行接口修改相应目录的权限,hadoop fs -chmod 777 /user,后面的/user是要上传文件的路径,不同的情况可能不一样,比如要上传的文件路径为hdfs://namenode/user/xxx.doc,则这样的修改可以,如果要上传的文件路径为hdfs://namenode/java/xxx.doc,则要修改的为hadoop fs -chmod 777 /java或者hadoop fs -chmod 777 /,java的那个需要先在HDFS里面建立Java目录,后面的这个是为根目录调整权限。4、右击计算机-->管理--->用户和组-->admin。。。改为与Linux下集群主机名相同

Permission denied: user=administrator, access=WRITE 问题解决相关推荐

  1. HDFS客户端的权限错误:Permission denied: user=Administrator, access=WRITE,....

    错误的详细描述如下: org.apache.hadoop.security.AccessControlException: org.apache.hadoop.security .AccessCont ...

  2. hdfs上传文件没有权限写入的问题解决put: Permission denied: user=root, access=WRITE

    问题: 如题,在上传文件的时候出现没有权限写入的问题: 命令: hdfs dfs -put dummy_log_data /user/impala/data/logs/year=2013/month= ...

  3. 访问HDFS的权限问题:Permission denied: user=xxx, access=WRITE, inode=“xxxxxxxx“:

    问题描述 今天在 idea 中写 scala 的代码访问服务器的 HDFS,报访问HDFS的权限问题:Permission denied: user=xxx, access=WRITE, inode= ...

  4. Hive JDBC:Permission denied: user=anonymous, access=EXECUTE, inode=”/tmp”

    今天使用JDBC来操作Hive时,首先启动了hive远程服务模式:hiveserver2 &(表示后台运行),然后到eclipse中运行程序时出现错误: Permission denied: ...

  5. Hadoop报错AccessControlException: Permission denied: user=vincent, access=WRITE, inode=/:iie4bu:supe

    尝试使用Java操作Hadoop,代码如下: /*** 使用Java API操作HDFS文件系统*/ public class HDFSAPP {public static void main(Str ...

  6. 远程连接:hive 报错:Permission denied: user=anonymous, access=EXECUTE

    远程连接hive Error: Failed to open new session: java.lang.RuntimeException: java.lang.RuntimeException: ...

  7. Hive报错:Hive JDBC:Permission denied: user=anonymous, access=EXECUTE, inode=”/tmp”

    1.美图 今天使用JDBC来操作Hive时,首先启动了hive远程服务模式:hiveserver2 &(表示后台运行),然后到eclipse中运行程序时出现错误: Permission den ...

  8. hadoop 权限错误 Permission denied: user=root, access=WRITE, inode=/:hdfs:super

    关于不能执行Hadoop命令 并报权限问题执行错误1.Permission denied: user=root, access=WRITE, inode="/":hdfs:supe ...

  9. mkdir: Permission denied: user=root, access=WRITE, inode=/lcy/test5.txt:hdfs:hdfs:drwxr-xr-x

    环境: centos 7 hadoop2.7 今天使用root用户hadoop上传文件测试的时候,怎么弄都无法上传成功,报错 #hdfs dfs -mkdir -p /lcy/test5.txt mk ...

最新文章

  1. python argparse库_python标准库之argparse
  2. 2022.3.25黄花酢浆草
  3. YII 增加登陆认证
  4. web 项目集成福昕_项目学生:Web服务集成
  5. 洛谷 P1272 重建道路
  6. Enterprise Library 系列教程
  7. 关于linux内核中使用的时钟
  8. ios 获取沙盒文件名_IOS获取各种文件目录路径的方法
  9. 【python】读取json文件
  10. clousx6机器人怎么导入词库_clousx6
  11. HBase简介、搭建环境及安装部署
  12. python histogram函数_Python numpy.histogram_bin_edges函数方法的使用
  13. [Eigen]Eigen的单位矩阵C++
  14. 企业公众号内容规划:企业公众号做什么内容易传播分享?
  15. 运动蓝牙耳机排行榜,六款适合运动的运动耳机推荐
  16. 我深爱的Java,对不起,我出轨了!!!呸!渣男!
  17. 计算机凭据分配在哪里,电脑策略没有凭据分配怎么办
  18. Python爬虫之初识简介以及舆情系统简介【爬虫篇一】
  19. mysql连接与嵌套查询_数据库之嵌套查询与连接查询
  20. 《基于数字信号处理的相干光通信技术》读书笔记chapter I——导论

热门文章

  1. SAP SMTP邮箱配置全过程
  2. 查看服务器GPU型号
  3. 微信公众平台测试号登录入口地址
  4. SQLite源代码分析----------分词器③
  5. git 回退远端master/develop分支版本
  6. 使用微软云服务器搭建Hadoop集群
  7. OpenGL-曲面细分
  8. 案例精选 | 冷饭变盛宴?一文谈尽边缘计算
  9. Error: spawn node.cmd ENOENT node自启动工具supervisor cmd运行报错解决方法
  10. 十款开源在线视频播放器