HDFS客戶端的許可權錯誤:Permission denied
搭建了一個Hadoop的環境,Hadoop叢集環境部署在幾個Linux伺服器上,現在想使用windows上的Java客戶端來操作叢集中的HDFS檔案,但是在客戶端執行時出現瞭如下的認證錯誤,被折磨了幾天,問題終得以解決。以此文記錄問題的解決過程。
(如果想看最終解決問題的方法拉到最後,如果想看我的問題解決思路請從上向下看)
問題描述
上傳檔案的程式碼:
- private static void uploadToHdfs() throws FileNotFoundException,IOException {
- //我的檔案地址
-
String localSrc = "E:\\快盤\\技術文件\\hadoop\\HDFS初步研究.pdf"
- //存放在雲端的目的地址
- String dest = "hdfs://192.168.2.156:9000/user/HDFS初步研究.pdf";
- InputStream in = new BufferedInputStream(new FileInputStream(localSrc));
- //得到配置物件
- Configuration conf = new Configuration();
- // conf.set("fs.default.name","hdfs://192.168.2.156:9000");
-
//檔案系統
- FileSystem fs = FileSystem.get(URI.create(dest), conf);
- //輸出流
- OutputStream out = fs.create(new Path(dest), new Progressable() {
- @Override
- public void progress() {
- System.out.println("上傳完一個設定快取區大小容量的檔案!");
- }
- });
-
//連線兩個流,形成通道,使輸入流向輸出流傳輸資料
- IOUtils.copyBytes(in, out, 4096, true);
- }
錯誤的詳細描述如下:
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等裡面取。關鍵程式碼為:
- 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、將當前系統的帳號修改為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中匯入相應的依賴,匯入