1. 程式人生 > >HDFS客戶端的許可權錯誤:Permission denied

HDFS客戶端的許可權錯誤:Permission denied

搭建了一個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上執行寫操作時被許可權系統拒絕.

解決問題的過程

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,所以就想著搜尋一下這個東西是啥,結果就找到了下面這一篇關鍵的文章:

在此篇文章裡面作者分析了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 JVM變數裡面新增HADOOP_USER_NAME,這個值具體等於多少看自己的情況,以後會執行HADOOP上的Linux的使用者名稱。(修改完重啟eclipse,不然可能不生效)

2、將當前系統的帳號修改為hadoop   {  在程式前面加入系統變數:System.setProperty("HADOOP_USER_NAME", "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目錄,後面的這個是為根目錄調整許可權。

我喜歡第一個方法。

相關推薦

HDFS客戶許可權錯誤Permission denied

搭建了一個Hadoop的環境,Hadoop叢集環境部署在幾個Linux伺服器上,現在想使用windows上的Java客戶端來操作叢集中的HDFS檔案,但是在客戶端執行時出現瞭如下的認證錯誤,被折磨了幾天,問題終得以解決。以此文記錄問題的解決過程。 (如果想看最終解決問題

Spark/HDFS上傳檔案錯誤Permission denied

問題描述 今天用spark將RDD結果輸出到HDFS時,因為CDH叢集重新配置的原因,許可權沒有設定好。導致寫檔案出bug。 錯誤情況 org.apache.hadoop.security.AccessControlException: Permission denied: use

PHP 操作檔案沒有許可權Permission denied

問題 在本地使用PHP指令碼操作檔案可以成功,等放到伺服器上就不行。 檢視apache日誌: #cd /var/log/httpd #tac error_log 顯示: cannot create directory '_TEST1': Permission

【github常見操作和常見錯誤錯誤提示Permission denied (publickey). fatal: Could not read from remote repository.

(1)首先新建 SSH key,在git shell(或者git bash等命令視窗),注意大小寫: $ ssh-keygen -t rsa -C “郵箱名” 然後會出現: Generating public/private rsa key

使用HDFS客戶java api讀取hadoop集群上的信息

tor ioe get tro names uri context add 集群配置 本文介紹使用hdfs java api的配置方法。 1、先解決依賴,pom <dependency> <groupId>org.apach

安裝mysql後連接出錯(錯誤Access denied for user 'root'@'localhost' (using password: YES)")的解決辦法

access 設置 lec 提示 回車 eight png varchar oot   前幾天下載了mysql5.7正常安裝後,用navicat for mysql連接時提示“Access denied for user [email protec

Android開發 adb命令提示Permission denied (轉)

模擬 ont lang rmi title fontsize fcm hbm ssi 如題:模擬器版本->android 7.1.1 遇到這樣的情況把模擬器root一下就好了:su root =============2017年4月3日20:57:33========

連接MySQL數據庫出現錯誤Access denied for user 'root'@'localhost' (using password:YES)

回車 發現 using 命令行 denied sql數據庫 roo 成功 host   自己在重拾MySQL數據庫的時候,第一次連接數據庫時候出現Access denied for user ‘root‘@‘localhost‘ (using password:YES)的錯

linux 下apche無法監聽口解決辦法(Permission denied: make_sock: could not bind to address)

gas his sys linux. ngs eui ner 一是 fix 想建立一個測試用的虛擬主機,遇到了這個問題:[root@localhost html]# service httpd startStarting httpd: httpd: Could not re

在ADUC中設置登錄到工作站功能,導致遠程桌面訪問客戶 報錯系統管理員已經限制你登錄的計算機

登錄 遇到 解決 nag net 計算機 preview 錯誤 報錯 在ADUC中設置登錄到工作站功能 遠程時錯誤提示:系統管理員已經限制你登錄的計算機。請在其他計算機上嘗試登錄。如果問題依然存在,請與系統管理員活技術支持聯系 經過我的研究,有兩種解決方案。 1 關閉nla

sqoop往遠程hdfs寫入數據時出現Permission denied 的問題

工具 port miss sqoop工具 數據 了解 log 如果 原因 猜測出現該問題的原因是sqoop工具用的是執行sqoop工具所用的本地用戶名。 如果遠程hdfs用的用戶是hdfs,那麽我本地還需要建一個名為hdfs的用戶? 其實不需要,只要為用戶增加一個環境變

驗證客戶的合法性

處理 .com 得到 加密算法 提前 send class code 不同 通常會用hmac模塊,和hashlib中的加鹽加密算法類似 服務器端提前和客戶端約定好key ,然後可以用os模塊裏的urandom來生成一組隨機的字節 把隨機字節發送給客戶端去加密處理 ,服務器

同一個hdfs客戶 切換不同叢集環境

是通過兩個配置檔案來切換到不同叢集環境的, hdfs-site.xml和core-site.xml   現在我建立兩個目錄: ~/dev/hadoop 開發環境目錄 ~/prod/hadoop 產品環境目錄 好了,現在我把開發環境叢集的core-site.xml和h

支付寶客戶架構解析iOS 容器化框架初探

1. 前言 由本章節開始,我們將從支付寶客戶端的架構設計方案入手,細分拆解客戶端在“容器化框架設計”、“網路優化”、“效能啟動優化”、“自動化日誌收集”、“RPC 元件設計”、“移動應用監控、診斷、定位”等具體實現,帶領大家進一步瞭解支付寶在客戶端架構上的迭代與優化歷程。 本節將介紹支付寶 iOS 容器化

支付寶客戶架構解析Android 客戶啟動速度優化之「垃圾回收」

前言 《支付寶客戶端架構解析》系列將從支付寶客戶端的架構設計方案入手,細分拆解客戶端在“容器化框架設計”、“網路優化”、“效能啟動優化”、“自動化日誌收集”、“RPC 元件設計”、“移動應用監控、診斷、定位”等具體實現,帶領大家進一步瞭解支付寶在客戶端架構上的迭代與優化歷程。 本節將介紹支付寶 Andro

《Spring Cloud微服務實戰》讀書筆記之客戶負載均衡Spring Cloud Ribbon - 4

摘要 客戶端負載均衡元件部署在客戶端,由客戶端維護要訪問的服務端清單(清單來源於服務註冊中心)。在Spring Cloud 中預設使用Ribbon作為客戶端負載均衡。 關鍵詞:客戶端負載均衡,Ribbon 一、什麼是客戶端負載均衡 負載均衡是對系統高可用、緩解網路壓力、處理能力擴容的重要手段之一。通常

支付寶客戶架構解析iOS 客戶啟動效能優化初探

前言 《支付寶客戶端架構解析》系列將從支付寶客戶端的架構設計方案入手,細分拆解客戶端在“容器化框架設計”、“網路優化”、“效能啟動優化”、“自動化日誌收集”、“RPC 元件設計”、“移動應用監控、診斷、定位”等具體實現,帶領大家進一步瞭解支付寶在客戶端架構上的迭代與優化歷程。 啟動應用是使用者使用任何一款

支付寶客戶架構分析自動化日誌收集及分析

前言 《支付寶客戶端架構解析》系列將從支付寶客戶端的架構設計方案入手,細分拆解客戶端在“容器化框架設計”、“網路優化”、“效能啟動優化”、“自動化日誌收集”、“RPC 元件設計”、“移動應用監控、診斷、定位”等具體實現,帶領大家進一步瞭解支付寶在客戶端架構上的迭代與優化歷程。 本節將結合禾兮

hdfs客戶例項(kerberos+simple)

1.非安全模式 在非安全模式下,訪問hdfs檔案系統的客戶端程式碼如下: package ntci.hadoop.hdfs.test; import org.apache.hadoop.classification.InterfaceAudience; import org.apache.h

大資料-Hadoop生態(7)-HDFS客戶的API操作

1 客戶端環境準備 根據自己電腦的作業系統拷貝對應的編譯後的hadoop jar包到非中文路徑 配置HADOOP_HOME的環境變數,並且在path中配置hadoop的bin 重啟電腦   2. HdfsClientDemo 建立一個Maven專案,在pom.xml中匯入相應的依賴,匯入