HDFS客户端的权限错误:Permission denied

本文介绍了在Windows环境下通过Java客户端操作Hadoop集群HDFS文件时遇到的权限问题,并提供了三种解决方案,包括设置环境变量HADOOP_USER_NAME。

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

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

问题描述

上传文件的代码:

  1.     private static void uploadToHdfs() throws FileNotFoundException,IOException {   
  2.         //我的文件地址   
  3.         String localSrc = "E:\\快盘\\技术文档\\hadoop\\HDFS初步研究.pdf";   
  4.         //存放在云端的目的地址   
  5.         String dest = "hdfs://192.168.2.156:9000/user/HDFS初步研究.pdf";   
  6.         InputStream in = new BufferedInputStream(new FileInputStream(localSrc));   
  7.         //得到配置对象   
  8.         Configuration conf = new Configuration();   
  9. //        conf.set("fs.default.name","hdfs://192.168.2.156:9000");   
  10.         //文件系统   
  11.         FileSystem fs = FileSystem.get(URI.create(dest), conf);   
  12.         //输出流   
  13.         OutputStream out = fs.create(new Path(dest), new Progressable() {   
  14.             @Override  
  15.             public void progress() {   
  16.                 System.out.println("上传完一个设定缓存区大小容量的文件!");   
  17.             }   
  18.         });   
  19.         //连接两个流,形成通道,使输入流向输出流传输数据   
  20.         IOUtils.copyBytes(in, out, 4096true);   
  21.     }  

错误的详细描述如下:

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等里面取。关键代码为:

  1. if (!isSecurityEnabled() && (user == null)) {   
  2.   String envUser = System.getenv(HADOOP_USER_NAME);   
  3.   if (envUser == null) {   
  4.     envUser = System.getProperty(HADOOP_USER_NAME);   
  5.   }   
  6.   user = envUser == null ? null : new User(envUser);   
  7. }  

OK,看到这里我的需求也就解决了,只要在系统的环境变量里面添加HADOOP_USER_NAME=hadoop(HDFS上的有权限的用户,具体看自己的情况),或者在当前JDK的变量参数里面添加HADOOP_USER_NAME这个Java变量即可。我的情况添加系统环境变量更方法。

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

解决办法

最终,总结下来解决办法大概有三种:

1、在系统的环境变量或java工程的变量里面添加HADOOP_USER_NAME,这个值具体等于多少看自己的情况,以后会运行HADOOP上的Linux的用户名。(修改完重启eclipse,不然可能不生效)

2、将当前系统的帐号修改为hadoop

3、使用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目录,后面的这个是为根目录调整权限。

我喜欢第一个方法。


转自:http://www.huqiwen.com/2013/07/18/hdfs-permission-denied/

hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_3.3.3.xml tar: hadoop-3.3.6: Cannot mkdir: Permission denied tar: hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_3.3.3.xml: Cannot open: No such file or directory hadoop-3.3.6/share/hadoop/hdfs/jdiff/Null.java tar: hadoop-3.3.6: Cannot mkdir: Permission denied tar: hadoop-3.3.6/share/hadoop/hdfs/jdiff/Null.java: Cannot open: No such file or directory hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_2.8.3.xml tar: hadoop-3.3.6: Cannot mkdir: Permission denied tar: hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_2.8.3.xml: Cannot open: No such file or directory hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_3.3.5.xml tar: hadoop-3.3.6: Cannot mkdir: Permission denied tar: hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_3.3.5.xml: Cannot open: No such file or directory hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_2.8.0.xml tar: hadoop-3.3.6: Cannot mkdir: Permission denied tar: hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_2.8.0.xml: Cannot open: No such file or directory hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_3.0.3.xml tar: hadoop-3.3.6: Cannot mkdir: Permission denied tar: hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_3.0.3.xml: Cannot open: No such file or directory hadoop-3.3.6/share/hadoop/hdfs/jdiff/hadoop-hdfs_0.22.0.xml tar: hadoop-3.3.6: Cannot mkdir: Permission denied tar: hadoop-3.3.6/share/hadoop/hdfs/jdiff/hadoop-hdfs_0.22.0.xml: Cannot open: No such file or directory hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_2.9.1.xml tar: hadoop-3.3.6: Cannot mkdir: Permission denied tar: hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_2.9.1.xml: Cannot open: No such file or directory hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_3.1.1.xml tar: hadoop-3.3.6: Cannot mkdir: Permission denied tar: hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_3.1.1.xml: Cannot open: No such file or directory hadoop-3.3.6/share/hadoop/hdfs/jdiff/hadoop-hdfs_0.20.0.xml tar: hadoop-3.3.6: Cannot mkdir: Permission denied tar: hadoop-3.3.6/share/hadoop/hdfs/jdiff/hadoop-hdfs_0.20.0.xml: Cannot open: No such file or directory hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_3.0.0-alpha4.xml tar: hadoop-3.3.6: Cannot mkdir: Permission denied tar: hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_3.0.0-alpha4.xml: Cannot open: No such file or directory hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_3.2.0.xml tar: hadoop-3.3.6: Cannot mkdir: Permission denied tar: hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_3.2.0.xml: Cannot open: No such file or directory hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_2.9.2.xml tar: hadoop-3.3.6: Cannot mkdir: Permission denied tar: hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_2.9.2.xml: Cannot open: No such file or directory hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_3.0.0-alpha2.xml tar: hadoop-3.3.6: Cannot mkdir: Permission denied tar: hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_3.0.0-alpha2.xml: Cannot open: No such file or directory hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_3.0.2.xml tar: hadoop-3.3.6: Cannot mkdir: Permission denied tar: hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_3.0.2.xml: Cannot open: No such file or directory hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_2.10.0.xml tar: hadoop-3.3.6: Cannot mkdir: Permission denied tar: hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_2.10.0.xml: Cannot open: No such file or directory hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_3.1.0.xml tar: hadoop-3.3.6: Cannot mkdir: Permission denied tar: hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_3.1.0.xml: Cannot open: No such file or directory hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_3.0.1.xml tar: hadoop-3.3.6: Cannot mkdir: Permission denied tar: hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_3.0.1.xml: Cannot open: No such file or directory hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_3.2.1.xml tar: hadoop-3.3.6: Cannot mkdir: Permission denied tar: hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_3.2.1.xml: Cannot open: No such file or directory hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_3.2.4.xml tar: hadoop-3.3.6: Cannot mkdir: Permission denied tar: hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_3.2.4.xml: Cannot open: No such file or directory hadoop-3.3.6/share/hadoop/hdfs/jdiff/hadoop-hdfs_0.21.0.xml tar: hadoop-3.3.6: Cannot mkdir: Permission denied tar: hadoop-3.3.6/share/hadoop/hdfs/jdiff/hadoop-hdfs_0.21.0.xml: Cannot open: No such file or directory hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_3.1.3.xml tar: hadoop-3.3.6: Cannot mkdir: Permission denied tar: hadoop-3.3.6/share/hadoop/hdfs/jdiff/Apache_Hadoop_HDFS_3.1.3.xml: Cannot open: No such file or directory hadoop-3.3.6/share/hadoop/hdfs/hadoop-hdfs-client-3.3.6-tests.jar tar: hadoop-3.3.6: Cannot mkdir: Permission denied tar: hadoop-3.3.6/share/hadoop/hdfs/hadoop-hdfs-client-3.3.6-tests.jar: Cannot open: No such file or directory hadoop-3.3.6/share/hadoop/hdfs/hadoop-hdfs-httpfs-3.3.6.jar tar: hadoop-3.3.6: Cannot mkdir: Permission denied tar: hadoop-3.3.6/share/hadoop/hdfs/hadoop-hdfs-httpfs-3.3.6.jar: Cannot open: No such file or directory tar: Exiting with failure status due to previous errors jtx@ubuntu:~$
最新发布
09-28
<think>我们当前需要解决的是在解压hadoop-3.3.6时出现的两个问题: 1. Cannot mkdir: Permission denied (创建目录权限被拒绝) 2. Cannot open: No such file or directory (无法打开:没有这样的文件或目录) 根据引用中提供的信息,我们可以总结出以下可能的原因和解决方案: 对于第一个问题:Cannot mkdir: Permission denied - 原因:当前用户对目标目录没有写权限。 - 解决方案: a) 使用管理员权限(sudo)执行解压命令(如果解压到系统目录如/usr/local,通常需要sudo)。 b) 更改目标目录的所有权,使得当前用户有权限写入(如引用[1]中提到的`chown`命令)。 c) 或者将hadoop解压到当前用户有权限的目录,例如用户主目录下的某个目录。 对于第二个问题:Cannot open: No such file or directory - 原因:可能是解压命令中指定的文件路径不正确,或者文件确实不存在(可能是下载不完整或路径错误)。 - 解决方案: a) 检查文件路径是否正确,确保解压命令中指定的压缩包文件存在。 b) 检查当前目录下是否存在该压缩包,可以使用`ls`命令查看。 c) 如果文件不存在,重新下载hadoop-3.3.6压缩包。 此外,根据引用[3]和引用[4]的信息,我们还需要注意在后续配置Hadoop环境时,确保环境变量设置正确,并且使用正确的用户权限来执行Hadoop相关命令。 具体步骤建议如下: 1. 确保下载的hadoop-3.3.6压缩包完整存在,并且存放的目录当前用户有读取权限。 2. 选择一个合适的解压目录: - 如果希望解压到系统目录(如`/usr/local`),则需要使用sudo权限,命令如下: ```bash sudo tar -xzvf hadoop-3.3.6.tar.gz -C /usr/local ``` - 如果使用当前用户主目录下的目录,例如`~/apps`,则不需要sudo: ```bash tar -xzvf hadoop-3.3.6.tar.gz -C ~/apps ``` 3. 如果解压过程中出现权限问题,可以尝试先更改目标目录的所有权(如果目标目录已经存在且属于其他用户): ```bash sudo chown -R $USER:$USER /usr/local/hadoop # 如果之前已经创建了hadoop目录且权限不对 ``` 或者,在解压后更改整个解压目录的所有权(如果使用sudo解压,那么解压出来的文件属于root,需要更改所有权以便普通用户使用): ```bash sudo chown -R hadoop:hadoop /usr/local/hadoop-3.3.6 # 假设你有一个hadoop用户和组,或者使用你自己的用户名和组 ``` 注意:这里的用户和组应该替换成你自己的。 4. 对于文件不存在的错误,请检查当前目录下是否有`hadoop-3.3.6.tar.gz`文件,或者检查你输入的文件名是否正确(注意大小写和版本号)。 5. 解压完成后,按照引用[3]中的示例配置环境变量(注意路径要根据实际解压目录调整): 修改`~/.bashrc`或`~/.bash_profile`,添加类似以下内容(具体路径根据实际情况): ```bash export JAVA_HOME=/path/to/your/jdk export HADOOP_HOME=/usr/local/hadoop-3.3.6 # 或者你解压到的目录 export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin ``` 然后执行`source ~/.bashrc`使环境变量生效。 6. 后续在运行Hadoop时,如果出现权限问题(如引用[2]和引用[4]),可能需要使用HDFS的命令来设置目录权限,例如: ```bash hdfs dfs -chmod 777 / # 不推荐,这里只是示例,实际生产环境需要严格控制权限 ``` 或者使用正确的用户来执行命令(如hdfs用户)。 注意:在Linux系统中,操作权限是非常重要的,尤其是在多用户环境下。请根据实际需求和安全策略来分配合适的权限。 综上所述,我们按照步骤来解决解压时的问题。 请用户按照上述步骤尝试解决问题。 </think>针对解压 Hadoop 3.3.6 时出现的权限不足和文件不存在问题,结合引用内容提供以下解决方案: ### 📂 一、解决权限问题(Cannot mkdir: Permission denied) 1. **更改解压目录所有权** 使用管理员权限将目标目录所有权赋予当前用户(替换 `your_user` 为实际用户名): ```bash sudo chown -R your_user:your_user /usr/local/hadoop ``` 如引用[1]的操作: ```bash chown -R hadoop:hadoop hadoop-0.20.2/ ``` 2. **使用 sudo 解压** 若需解压到系统目录(如 `/usr/local`),需提升权限: ```bash sudo tar -xzvf hadoop-3.3.6.tar.gz -C /usr/local ``` 3. **修改目录权限** 解压后赋予目录读写权限(参考引用[2]): ```bash sudo chmod 777 /usr/local/hadoop # 临时方案,生产环境需严格权限控制 ``` ### 🔍 二、解决文件不存在问题(Cannot open: No such file or directory) 1. **检查文件路径** 确认压缩包存在且路径正确: ```bash ls -l hadoop-3.3.6.tar.gz ``` 2. **完整下载压缩包** 重新下载并校验哈希值(官网提供 SHA-256): ```bash wget https://archive.apache.org/dist/hadoop/core/hadoop-3.3.6/hadoop-3.3.6.tar.gz sha256sum hadoop-3.3.6.tar.gz ``` 3. **修复环境变量配置** 如引用[3]所示,确保 `$HADOOP_HOME` 等变量正确定义: ```bash export HADOOP_HOME=/usr/local/hadoop export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin source ~/.bashrc # 立即生效 ``` ### ⚙️ 三、后续配置建议 1. **HDFS 权限修复** 若启动后出现 `Permission denied`(参考引用[4]): ```bash hdfs dfs -chmod 777 / # 临时开放根目录权限 hadoop fs -mkdir /user # 创建用户目录 ``` 2. **日志目录处理** 手动创建缺失目录并赋权(引用[1][3]): ```bash mkdir -p /usr/local/hadoop/logs chown -R hadoop:hadoop /usr/local/hadoop/logs ``` 3. **用户切换** 始终使用专属 Hadoop 用户操作(避免 root 权限问题): ```bash su - hadoop # 切换到hadoop用户 ``` ### 💡 根本原因总结 | 问题类型 | 主要原因 | 解决方案 | |----------|----------|----------| | **权限拒绝** | 用户对目录无写权限 | `chown`/`chmod` 赋权或使用 `sudo` | | **文件不存在** | 压缩包路径错误/下载不完整 | 检查路径/重新下载校验 | | **后续报错** | 环境变量缺失或权限配置错误 | 完善环境变量/HDFS显式赋权 | > ✨ **关键提示**:解压后需完整配置 `hadoop-env.sh` 中的 `JAVA_HOME` 和 `HADOOP_LOG_DIR`(参考引用[3]),否则启动时仍可能报错。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值