指南:從基礎(chǔ)操作到生產(chǎn)排錯)
先把結(jié)論說在前頭Hadoop HDFS 常用Shell命令是每個接觸大數(shù)據(jù)的人都繞不過去的基礎(chǔ)功。我在實際維護集群時最深的體會是圖形界面適合看趨勢但真要解決問題還是得靠命令行。這篇文章不打算變成一本命令手冊的復(fù)制粘貼而是從“怎么用、為什么這么用、踩過哪些坑”三個角度把HDFS Shell命令里最值得掌握的部分拆細(xì)。我盡量把命令執(zhí)行后的輸出也一并貼出來權(quán)當(dāng)圖文詳解式的文字截圖。這樣你不僅能看明白命令長什么樣還能知道看到什么結(jié)果才算正常。剛接觸Hadoop的同學(xué)可以按順序照做已經(jīng)入門的開發(fā)者也能在后面的報錯排查里找到有價值的東西。1. 為什么HDFS命令行至今無法被替代1.1 一次凌晨巡檢留下的深刻印象有一回某個模擬數(shù)據(jù)處理項目在凌晨突然報數(shù)倉接口文件缺失。我打開Web UI想看看目錄結(jié)果一層一層點進(jìn)去翻了好幾個分區(qū)目錄才覺得不對勁。后來換回終端先執(zhí)行hdfs dfs -ls -R /data/dw再配合hdfs dfs -du -h /data/dw/2024*幾秒鐘就鎖定了問題某個分區(qū)目錄下有一批大小為0的空文件明顯是寫任務(wù)中途失敗留下的臟數(shù)據(jù)。清掉之后重啟任務(wù)問題馬上解決。這件事給我的沖擊很大。圖形界面在“隨便看看”的時候確實方便可一旦遇到需要橫向?qū)Ρ?、批量定位、快速統(tǒng)計場景命令行的效率是UI完全追不上的。尤其是當(dāng)你需要同時對比幾十個目錄的文件數(shù)量、大小和修改時間用鼠標(biāo)去逐個點擊幾乎不可想象。命令行把文件系統(tǒng)最核心的元信息直接擺在終端里方便你用管道和文本工具繼續(xù)篩選。1.2 命令行相比Web UI的四個核心優(yōu)勢我記得剛從開發(fā)環(huán)境轉(zhuǎn)入真實集群環(huán)境時第一個被糾正的習(xí)慣就是“能用終端解決的事不要去點頁面”。原因其實很樸素主要就這四點。批量操作能力。UI適合單看一個路徑但一行hdfs dfs -rm -r /data/tmp/*可以遞歸清理掉一大批臨時目錄。配合通配符和參數(shù)處理成千上萬個文件不是問題。腳本化與自動化。命令天然能被封裝到Shell腳本和調(diào)度系統(tǒng)里。比如每天凌晨用腳本先判斷目標(biāo)目錄是否存在再把當(dāng)天結(jié)果上傳進(jìn)去。這套流程用UI根本沒法做而且容易在手工操作時漏掉某個步驟。更細(xì)膩的元信息。執(zhí)行hdfs dfs -ls能看到文件權(quán)限、副本數(shù)、所屬用戶和組、大小、修改時間。這些信息對排查副本丟失、歸屬關(guān)系混亂、小文件異常都極有價值。Web UI雖然也有展示但輸出格式和批量對比能力差遠(yuǎn)了。遠(yuǎn)程執(zhí)行友好。只要網(wǎng)絡(luò)可達(dá)在任意節(jié)點打開終端就能執(zhí)行命令不需要額外打開瀏覽器、登錄管理界面更不用等待頁面刷新。人在機房、出差、在家里處理問題體驗差距非常明顯??偠灾钚胁皇欠恋K你使用HDFS的門檻恰恰是讓你能自主掌控文件系統(tǒng)的鑰匙。搞懂它很多問題就變得不那么嚇人。2. HDFS Shell命令體系拆解常用命令一張速查表2.1 命令入口hdfs dfs 與 hadoop fs 并不沖突開始記命令前先花十秒鐘理解一下邏輯。老版本的Hadoop里大家習(xí)慣用hadoop fs -ls /后來版本逐漸統(tǒng)一成hdfs dfs -ls /。在實際絕大多數(shù)發(fā)行版里兩者指向同一個FileSystem Shell所以混用基本不會出錯。但我的建議是盡量用hdfs dfs因為表達(dá)更準(zhǔn)確而且有些第三方組件解析命令時只認(rèn)hdfs dfs。確認(rèn)命令版本可以用hdfs version正常會輸出類似Hadoop 3.3.4這樣的版本信息。接著可以試試最基礎(chǔ)的查看根目錄hdfs dfs -ls /如果配置沒有問題輸出會像這樣Found 2 items drwxr-xr-x - hadoop supergroup 0 2024-05-10 09:00 /data drwxr-xr-x - hadoop supergroup 0 2024-05-10 09:10 /user如果配置了NameNode高可用或者想臨時指定別的集群也可以顯式加-fs參數(shù)hdfs dfs -fs hdfs://testcluster -ls /這個“指定文件系統(tǒng)”的技巧在排查跨集群問題時尤其有用。2.2 高頻文件操作命令演示與輸出字段講解常用文件操作命令先整理成一張速查表后面再逐一展開。命令作用常用參數(shù)典型場景-ls列出文件/目錄-R遞歸、-h人類可讀查看路徑是否存在、目錄結(jié)構(gòu)-cat輸出文件內(nèi)容-text兼容文本與序列文件抽樣查看小文件內(nèi)容-put本地上傳到HDFS-f覆蓋、-p保留權(quán)限向集群導(dǎo)入數(shù)據(jù)-getHDFS文件下載到本地-f覆蓋、-p保留權(quán)限、-ignorecrc導(dǎo)出結(jié)果數(shù)據(jù)-rm刪除文件/目錄-r遞歸、-skipTrash跳過回收站清理臨時數(shù)據(jù)這些命令在實戰(zhàn)里出現(xiàn)頻率最高。ls不用說cat適合快速看一眼小文件內(nèi)容很多人不知道它還能配合-text讀取SequenceFile等格式雖然不是萬能但比盲猜字段方便多了。put和get是對應(yīng)的。put把本地文件上傳get把HDFS文件拉回來。rm則要特別小心默認(rèn)刪除會進(jìn)回收站如果想立刻釋放空間加-skipTrash但要確認(rèn)真的不再需要。舉一組最基礎(chǔ)的執(zhí)行序列hdfs dfs -ls -h /data hdfs dfs -cat /data/test.txt hdfs dfs -put ./test.txt /data/ hdfs dfs -get /data/test.txt ./test_download.txt hdfs dfs -rm -r /data/tmp執(zhí)行l(wèi)s -h時文件大小會自動顯示成可讀的K/M/G格式非常直觀。理解了這些命令之后再看ls的輸出字段很多初學(xué)者會一臉懵。以這一行為例-rw-r--r-- 3 hdfs supergroup 2048 2024-05-10 12:00 /data/test.txt字段依次是文件類型與權(quán)限位副本數(shù)所屬用戶所屬組文件大小字節(jié)修改時間完整路徑。目錄那一行的副本數(shù)位置通常顯示-因為目錄本身不產(chǎn)生副本。這個細(xì)節(jié)對于判斷“為什么這個文件占用了三倍空間”很有幫助——副本數(shù)越高實際占用物理空間就越大。2.3 目錄操作、權(quán)限與副本設(shè)置命令文件操作之外目錄操作和權(quán)限管理同樣繞不開。我常用的命令包括hdfs dfs -mkdir -p /user/warehouse/dw/dim hdfs dfs -chmod -R 750 /user/warehouse hdfs dfs -chown -R hadoop:hadoop /user/warehouse hdfs dfs -setrep -w 3 /data/test.txtmkdir -p會自動創(chuàng)建父目錄不用像手動逐層創(chuàng)建那樣麻煩。chmod、chown與Linux的權(quán)限模型很像但因為HDFS支持遞歸權(quán)限位所以要注意-R是否會導(dǎo)致權(quán)限范圍過大或誤設(shè)。生產(chǎn)環(huán)境里最常見的權(quán)限問題大多是某個目錄只允許特定用戶訪問卻因為遞歸chmod -R 777被上層目錄的權(quán)限沖掉。setrep可以動態(tài)調(diào)整單文件的副本數(shù)。比如某個臨時數(shù)據(jù)熱度很高想臨時提高備份數(shù)hdfs dfs -setrep -w 5 /data/hot.txt-w表示等待副本操作完成。這個命令在原本副本數(shù)不足、但HDFS集群節(jié)點數(shù)不夠時很容易觸發(fā)寫入失敗后面會專門講。2.4 集群健康檢查常用的兩個命令別忘了兩個常被歸在“Shell命令”范疇但面向集群整體的工具h(yuǎn)dfs dfsadmin -report和hdfs fsck。執(zhí)行hdfs dfsadmin -report可以快速查看NameNode是否處于Active狀態(tài)、Live節(jié)點數(shù)量、DFS已用空間、剩余空間等。輸出類似Configured Capacity: 53687091200 (50 GB) Present Capacity: 48234496000 (44.92 GB) DFS Remaining: 30000000000 (27.94 GB) DFS Used: 12000000000 (11.17 GB) DFS Used%: 24.88% Live Datanodes (3):看到Live節(jié)點數(shù)明顯下降或者DFS Used%異常升高通常就是集群出問題的前兆。hdfs fsck /data/test.txt -files -blocks -locations更適合檢查某個文件或目錄的塊健康狀態(tài)。它會告訴我們一個文件被切成了幾個塊每個塊有哪些副本是否滿足最小副本數(shù)。在排查數(shù)據(jù)丟失或副本不足時這條命令幾乎是必查項hdfs fsck /data/tmp -files -blocks -locations如果輸出里有UNDER REPLICATED字樣說明部分塊副本數(shù)低于配置要求需要關(guān)注磁盤或DataNode狀態(tài)。3. 手把手實操從連接到上傳下載的完整記錄3.1 先確認(rèn)本地客戶端與集群連接狀態(tài)理論知識說多了容易空直接走一遍完整流程。我在一臺測試機上使用偽分布式HDFS環(huán)境來演示你在真實集群里的操作基本一致。進(jìn)入終端先確認(rèn)客戶端的部署和集群地址配置正常最穩(wěn)妥的辦法就是列一下根目錄hdfs dfs -ls /如果能出現(xiàn)/data、/user這類目錄說明客戶端已經(jīng)可以正常連接NameNode。如果提示連接超時或UnknownHostException多半是core-site.xml里的fs.defaultFS沒有配好。接著可以用hdfs dfs -mkdir -p /data/tmp/20240510新建一個演示目錄并執(zhí)行echo hello hdfs local.txt準(zhǔn)備一個本地文件。準(zhǔn)備工作完成后就進(jìn)入上傳環(huán)節(jié)。3.2 上傳文件到一個新目錄的完整流程上傳本地local.txt到剛創(chuàng)建的目錄hdfs dfs -put local.txt /data/tmp/20240510/沒有任何輸出通常代表成功。這時用ls -h確認(rèn)hdfs dfs -ls -h /data/tmp/20240510輸出Found 1 items -rw-r--r-- 3 hadoop supergroup 12 B 2024-05-10 12:30 /data/tmp/20240510/local.txt如果想確認(rèn)內(nèi)容沒丟直接查看hdfs dfs -cat /data/tmp/20240510/local.txt輸出hello hdfs。這里補充一句-put和-copyFromLocal功能基本一致日常二選一即可。部分老腳本保留-copyFromLocal不影響使用。上傳時常用的參數(shù)是-f用于覆蓋同名文件。比如數(shù)據(jù)回流任務(wù)重復(fù)執(zhí)行可以使用hdfs dfs -put -f local.txt /data/tmp/20240510/local.txt這樣即使目標(biāo)已存在也不會直接報錯。還有一個容易忽略的點上傳大文件時HDFS會按照塊大小拆分并分布式存儲所以你不會看到單個物理文件而是通過NameNode元數(shù)據(jù)虛擬出一個完整文件。這個認(rèn)知對后面排查空間占用很重要。3.3 下載文件并校驗一致性的三個步驟下載通常用gethdfs dfs -get /data/tmp/20240510/local.txt ./download.txt本地會生成download.txt正常情況內(nèi)容和遠(yuǎn)端一致。為了確保數(shù)據(jù)在傳輸過程中沒有損壞可以用diff快速比較diff local.txt download.txt沒有任何輸出就代表一致。如果一個大文件做完整性校驗更適合用md5sum或sha256sum分別計算本地和遠(yuǎn)端文件的哈希值然后對比。HDFS底層雖然通過CRC校驗保護塊數(shù)據(jù)但客戶端、網(wǎng)絡(luò)、中間環(huán)節(jié)依然可能出意外腳本里加一步校驗會穩(wěn)妥很多。get還支持-p保留HDFS文件權(quán)限和時間戳這在跨環(huán)境同步元數(shù)據(jù)時很有用不過日常導(dǎo)出數(shù)據(jù)一般用不上。3.4 數(shù)據(jù)移動、復(fù)制與空間統(tǒng)計的實用場景實戰(zhàn)中數(shù)據(jù)放錯目錄是家常便飯。比如文件被傳到了/data/tmp/20240510/現(xiàn)在想轉(zhuǎn)移到/data/input/直接mv就行hdfs dfs -mv /data/tmp/20240510/local.txt /data/input/mv在HDFS上只是更新元數(shù)據(jù)里的路徑信息不涉及數(shù)據(jù)塊的物理遷移所以速度非??旒词刮募资瓽B也不會有明顯等待。這一點和Linux的mv在同一文件系統(tǒng)內(nèi)移動類似。想復(fù)制一份用于測試可以用cphdfs dfs -cp /data/input/local.txt /data/backup/cp會實際復(fù)制塊數(shù)據(jù)大文件耗時較長所以不要在高峰期復(fù)制超大目錄。需要統(tǒng)計目錄大小用hdfs dfs -du -h -s /data/input輸出像120M 360M /data/input這種格式第一個數(shù)字是文件邏輯大小第二個數(shù)字是考慮副本后的實際占用空間??吹絻烧卟罹嗪艽缶驮撘庾R到副本數(shù)偏高或者小文件過多。整體文件系統(tǒng)的空間用hdfs dfs -df -h /查看即可。4. 生產(chǎn)環(huán)境高頻報錯排查與避坑實錄4.1 “No such file or directory”不等于文件真的不存在執(zhí)行hdfs dfs -ls /some/path時最常出現(xiàn)的就是No such file or directory。但很多時候路徑明明存在為什么還會報錯我踩過的坑無非這么幾類路徑隨手寫成絕對路徑卻漏了根斜杠父目錄確實存在但自己沒有讀取權(quán)限NameNode不會直接告訴你而是包裝成“路徑不存在”客戶端連接的集群和實際數(shù)據(jù)所在集群不是同一個以及少數(shù)情況下確實輸錯了名字。排錯第一步先確認(rèn)路徑是否存在hdfs dfs -test -e /data/input/local.txt echo exists || echo not exists-test -e返回值可以用來判斷在腳本里非常順手。如果想一層一層找可以用hdfs dfs -ls -R /data | grep local.txt再配合fs.defaultFS檢查當(dāng)前連接的是不是目標(biāo)集群。4.2 “Permission denied”背后的身份與權(quán)限模型HDFS權(quán)限提示常長這樣Permission denied: userdev, accessREAD_EXECUTE, inode/user/prod/data:hadoop:supergroup:drwxr-x---這個提示的意思是當(dāng)前執(zhí)行命令的本地用戶是dev但目錄/user/prod/data屬于hadoop權(quán)限位也不允許其他用戶讀取進(jìn)來。很多人第一反應(yīng)是“把權(quán)限改掉”但這在真實生產(chǎn)環(huán)境往往不能隨意改得看業(yè)務(wù)和審計要求??梢韵炔榭茨夸洰?dāng)前的歸屬和權(quán)限hdfs dfs -ls -d /user/prod/data然后找管理員協(xié)助要么對特定用戶開放指定權(quán)限要么調(diào)整目錄歸屬sudo -u hdfs hdfs dfs -chown -R prod:hadoop /user/prod/data這里用sudo -u hdfs是讓超級用戶執(zhí)行變更。如果在集群里有Kerberos或者Ranger權(quán)限體系處理方式會更復(fù)雜但核心邏輯不變先搞清楚當(dāng)前身份再決定是按用戶授權(quán)還是修改歸屬。還有一個值得養(yǎng)成的習(xí)慣不要在生產(chǎn)集群上用root用戶執(zhí)行一攬子HDFS命令。雖然本地身份可以偽裝但留下的文件歸屬很亂后續(xù)會讓所有人頭疼。4.3 文件寫入失敗、DataNode空間不足與副本問題上傳大文件失敗的經(jīng)典報錯之一長這樣File /data/tmp/xxx could only be replicated to 0 nodes instead of minReplication(1)這句話翻譯過來是NameNode想把文件塊復(fù)制到至少1個DataNode上但一個都沒成。原因通常是數(shù)據(jù)節(jié)點沒有可用存儲、DataNode進(jìn)程掛了、或者網(wǎng)絡(luò)層面不健康。先看整體狀態(tài)hdfs dfsadmin -report重點看Live Datanodes數(shù)量以及DFS Remaining。如果剩余空間很低就要清理臨時數(shù)據(jù)或擴容。如果節(jié)點數(shù)足夠且空間充足再用hdfs fsck / -files -blocks看是否存在大量副本缺失的塊。還有一個容易忽視的場景集群只有1個DataNode但默認(rèn)副本數(shù)寫的是3寫入同樣會失敗。單機演示環(huán)境經(jīng)常這樣。臨時解決辦法是把文件副本數(shù)調(diào)低到1hdfs dfs -setrep -w 1 /data/tmp/xxx不過這只適用于測試生產(chǎn)環(huán)境副本數(shù)是集群容錯的基礎(chǔ)不要為了省空間隨意調(diào)低。4.4 回收站引起的“文件刪了空間卻沒釋放”很多人第一次清理HDFS時會覺得奇怪rm刪完文件為什么dfsadmin -report里可用空間沒變化問題出在HDFS默認(rèn)的回收站機制。刪除的文件并不會立刻消失而是被移動到當(dāng)前用戶目錄下的.Trash比如/user/hadoop/.Trash。只有超過fs.trash.interval配置的時間后文件才會被真正清除。這個設(shè)計是為了防止誤刪但也會讓磁盤空間“看起來沒釋放”。如果確認(rèn)這批數(shù)據(jù)確實不要了可以先看回收站里有什么hdfs dfs -ls /user/hadoop/.Trash然后決定保留還是徹底清除。徹底刪除時加-skipTrashhdfs dfs -rm -r -skipTrash /data/tmp/old_data這個參數(shù)能救急但一定慎用因為跳過了回收站就等于沒有反悔機會。生產(chǎn)環(huán)境清理過期的臨時表或日志時建議先看清楚路徑再執(zhí)行最好把待刪路徑寫入文本文件二次核對不要隨手一條rm -skipTrash。5. 讓HDFS Shell命令真正好用的小技巧5.1 用通配符與find命令批量定位文件HDFS Shell支持路徑通配符比如查看目錄里所有.log文件hdfs dfs -ls /data/logs/*.log不過這里要注意通配符的解析由Shell和HDFS客戶端共同完成不是所有版本都完全一致。如果是在腳本里做更復(fù)雜的模糊查找新版HDFS提供了find命令hdfs dfs -find /data/logs -name *.log它會遞歸搜索匹配的文件路徑輸出比ls -R | grep干凈很多。配合-print參數(shù)還能控制輸出格式。在舊版本沒有這個命令的環(huán)境里也可以退而求其次用hdfs dfs -ls -R /data/logs | grep \.log$。5.2 每個命令都可以用-help快速查參數(shù)命令記不全太正常了我剛上手的時候也一樣。好就好在HDFS Shell自帶查詢工具直接在命令后加-help就能看到參數(shù)說明。例如hdfs dfs -help put輸出會列出put的完整用法及所有參數(shù)含義比如-f、-p。寫腳本前花半分鐘查一下比自己硬記或搜索都靠譜。這里還推薦一個習(xí)慣把-help當(dāng)成“離線文檔”隨身帶不依賴瀏覽器也不容易分心。5.3 在Shell腳本里封裝的三個防御習(xí)慣我在長期使用HDFS Shell的過程中總結(jié)出三個非常管用的防御習(xí)慣。第一個刪除前先判斷路徑是否存在。前面提過用hdfs dfs -test -e這是寫自動調(diào)度腳本的關(guān)鍵。否則路徑不存在時rm的退出碼是非0整個任務(wù)可能被判定失敗。if hdfs dfs -test -e $hdfs_path; then hdfs dfs -rm -r -skipTrash $hdfs_path fi第二個上傳后檢查遠(yuǎn)端文件大小。腳本執(zhí)行完put后可以再用du -s獲取遠(yuǎn)端字節(jié)數(shù)對比本地文件大小local_size$(stat -c%s local.txt) remote_size$(hdfs dfs -du -s /data/input/local.txt | awk {print $1}) if [ $local_size -eq $remote_size ]; then echo upload ok else echo upload failed fi注意du -s輸出第一列是字節(jié)數(shù)不加-h才方便腳本數(shù)值比較。第三個在腳本開頭用set -euo pipefail。這能讓腳本在遇到錯誤時及時退出避免一連串依賴前一步結(jié)果的命令在失敗后繼續(xù)執(zhí)行制造更多臟數(shù)據(jù)。這三個習(xí)慣不算高深但確實幫我躲過了好幾次“明明沒報錯、數(shù)據(jù)卻少了一批”的問題。在這套工具用熟之后你會發(fā)現(xiàn)HDFS Shell命令并沒有想象中那么可怕。它本質(zhì)上是給了你一把直接操作集群文件系統(tǒng)的鑰匙。我在實際環(huán)境里反復(fù)使用后最深的體會是越是基礎(chǔ)的東西越值得認(rèn)真打磨。多花一點時間把 ls、put、get、rm 以及對應(yīng)的參數(shù)和異常輸出搞清楚未來處理線上問題時能省下大量精力。你不需要一下子記住全部命令但至少要把最常用的六個記熟其余的隨時交給-help就行。