简介这份资源是《大数据技术原理与应用》课程实验二的完整报告文档面向正在学习Hadoop与HDFS的高校学生及大数据入门者帮助解决HDFS Shell命令与Java API操作不熟练、实验报告无从下手的问题。压缩包内仅含1个docx文件约3.4MB内容涵盖实验环境说明、Shell命令操作与Java编程实现两大部分并附有完整代码与运行截图。实验以Ubuntu 16.04、Hadoop 3.1.3、JDK 1.8及Eclipse为平台通过hdfs dfs -put、-test -e、-appendToFile、-copyFromLocal -f等命令演示文件上传、存在性判断、追加与覆盖操作同时用Configuration、FileSystem、Path等类实现文件判断与本地复制到HDFS的Java程序。读者可据此快速理解HDFS在Hadoop体系中的存储角色掌握Shell与API两种交互方式为后续MapReduce与HBase学习打下基础。目前已有10214人学习下载适合作为实验参考与排错对照。1. 实验二熟悉常用的HDFS操作到底在练什么很多人第一次看到“实验二熟悉常用的HDFS操作”这个标题以为就是背几个命令——ls、put、get、rm敲一遍交截图完事。但真正做过生产环境HDFS运维的人知道这个实验的核心不是命令本身而是让你建立对分布式文件系统读写流程的肌肉记忆。你敲的每一条hdfs dfs -put背后都走了一遍NameNode元数据写入、DataNode管道复制、客户端确认的完整链路。实验二之所以叫“熟悉”是因为后面所有MapReduce、Spark、Hive的任务数据入口和出口都绕不开这些操作。如果你连-put和-copyFromLocal的区别都说不清后面调优根本无从下手。这篇笔记面向正在做这个实验的学生也面向刚转大数据方向、需要把HDFS操作从“会敲”变成“懂为什么”的工程师。我会把命令拆开把参数讲透把踩过的坑摆出来让你做完这个实验不是交差而是真的能拿去干活。2. HDFS常用命令拆解从Shell到读写流程2.1 先搞懂hdfs dfs和hadoop fs到底用哪个实验环境里通常两个命令都能跑hadoop fs和hdfs dfs。很多教程混着写导致新手以为随便用哪个都行。实际上hadoop fs是一个更通用的文件系统接口它不仅能操作HDFS还能操作本地文件系统、S3等只要在core-site.xml里配置了对应的fs.defaultFS。而hdfs dfs是专门针对HDFS的客户端命令它底层调用的就是hadoop fs但只认HDFS的路径。我一般建议在实验里统一用hdfs dfs因为你的目标就是熟悉HDFS用专用命令能避免路径歧义。比如你写hadoop fs -ls /如果fs.defaultFS没配好它可能去列本地根目录你还在那纳闷为什么没有HDFS的文件。用hdfs dfs -ls /它明确走HDFS报错也是HDFS的报错排查方向清晰。# 查看当前HDFS根目录下的内容 hdfs dfs -ls / # 递归查看所有文件包括子目录 hdfs dfs -ls -R / # 查看HDFS集群的总体使用情况 hdfs dfs -df -h /这三条命令是实验第一步。-ls不带参数默认列当前用户家目录带/才是根目录。-R递归在目录层级深的时候很有用但生产环境慎用文件多了输出能刷屏。-df -h看的是HDFS整体容量-h把字节转成人类可读的KB/MB/GB不加-h你看到的就是一串数字还得自己算。2.2 上传文件put、copyFromLocal、moveFromLocal的区别实验里最常考的操作就是上传。三个命令长得像但行为差异直接影响你后续实验数据还在不在。# 1. 从本地复制到HDFS本地文件保留 hdfs dfs -put /home/student/data.txt /user/student/ # 2. 效果同上但更明确表达“从本地复制” hdfs dfs -copyFromLocal /home/student/data.txt /user/student/ # 3. 从本地移动到HDFS本地文件被删除 hdfs dfs -moveFromLocal /home/student/data.txt /user/student/ # 4. 从标准输入读取并写入HDFS echo hello hdfs | hdfs dfs -put - /user/student/stdin.txt-put和-copyFromLocal在绝大多数场景下等价但-copyFromLocal语义更清晰源必须是本地路径。-put其实也能接受标准输入用-表示这是它比-copyFromLocal多出来的能力。-moveFromLocal要小心实验里如果你把唯一的数据源移走了本地没了后面想重做就得重新生成数据。我踩过一次坑用-moveFromLocal上传了实验数据结果本地文件被删想改个参数重跑发现源没了只能从HDFS再-get下来白白多一步。参数方面-put支持-f强制覆盖、-p保留权限和时间戳、-l允许追加。实验里如果目标文件已存在不加-f会报File already exists这是新手最常见的报错之一。2.3 下载文件get和copyToLocal的坑下载操作对应-get和-copyToLocal关系跟上传那边一样。# 下载到本地当前目录 hdfs dfs -get /user/student/data.txt # 下载并重命名 hdfs dfs -get /user/student/data.txt ./renamed.txt # 下载整个目录到本地 hdfs dfs -get /user/student/output/ ./local_output/ # 合并下载把HDFS上多个分块文件合并成一个本地文件 hdfs dfs -getmerge /user/student/output/part-* ./merged.txt-getmerge是实验里容易被忽略但非常实用的命令。MapReduce输出通常是part-r-00000这样的多个分块文件你想在本地看完整结果一个个-get再手动拼太蠢。-getmerge直接把匹配到的所有文件按字典序合并下载成一个文件。注意它只做拼接不排序如果分块之间有顺序要求得自己保证。另一个坑是权限。HDFS上的文件如果属主不是你-get会报Permission denied。实验环境里通常用同一个用户操作但如果你切换过用户或者用了sudo就可能遇到。解决方法是确认HDFS文件权限或者用有权限的用户操作。2.4 查看和统计cat、text、tail、du、count怎么选实验报告里经常要求“查看文件内容”和“统计文件信息”命令选不对要么看不到要么看错。# 查看小文件内容直接输出到终端 hdfs dfs -cat /user/student/data.txt # 查看压缩文件或序列文件自动解压/解码 hdfs dfs -text /user/student/data.gz # 查看文件末尾1KB适合大文件快速预览 hdfs dfs -tail /user/student/largefile.txt # 查看文件或目录的磁盘占用大小 hdfs dfs -du -h /user/student/ # 统计目录下的文件数和总大小 hdfs dfs -count /user/student/-cat适合小文件大文件用-cat会把整个文件刷到终端卡死你的Shell。-text比-cat多了解压和序列化解码能力处理.gz、.snappy、SequenceFile时用它。-tail默认显示最后1KB可以加-f持续跟踪类似Linux的tail -f但HDFS上文件一般不频繁追加-f用得少。-du和-count的区别要记牢-du显示的是每个文件/目录的实际存储大小-count显示的是目录下的文件数和总大小。实验里如果让你“统计HDFS上某目录的文件数量”用-count输出格式是目录数 文件数 总大小 路径。2.5 删除和回收站rm、rmr、expunge删除操作在实验里通常就是清理环境但HDFS的删除有回收站机制不搞明白会以为文件没删掉。# 删除文件会进回收站如果启用了 hdfs dfs -rm /user/student/data.txt # 递归删除目录会进回收站 hdfs dfs -rm -r /user/student/output/ # 跳过回收站直接删除 hdfs dfs -rm -r -skipTrash /user/student/output/ # 清空回收站 hdfs dfs -expunge-rm删文件-rm -r删目录-rmr是旧版命令现在等价于-rm -r但有些老教程还在用。回收站默认是开启的删除的文件会移到/user/username/.Trash/下保留一段时间默认6小时。如果你删完发现磁盘空间没释放别慌等回收站过期或者手动-expunge。-skipTrash在实验里清理大目录时很有用避免回收站占空间。3. HDFS读写流程命令背后发生了什么3.1 写流程从put到DataNode管道你敲下hdfs dfs -put local.txt /user/student/客户端做的事情远不止“复制文件”。完整流程分七步客户端调用DistributedFileSystem的create方法向NameNode发起RPC请求要求在HDFS命名空间里创建文件。NameNode检查权限、文件是否存在然后在EditLog里记录创建操作返回一个FSDataOutputStream。客户端开始写数据数据先写入本地缓冲区达到一个块大小默认128MB后向NameNode请求分配DataNode。NameNode返回一组DataNode列表默认3副本按网络距离排序。客户端向第一个DataNode写数据第一个DataNode再向第二个写第二个向第三个写形成管道。数据包在管道中逐级传输每级确认后向上游反馈ACK。所有块写完客户端关闭流NameNode提交元数据。实验里你感觉不到这些但如果你写大文件时观察DataNode日志能看到Receiving block和PacketResponder的输出。理解这个流程后面调优dfs.replication、dfs.client-write-packet-size才有依据。3.2 读流程从get到短路读取读流程相对简单但有个“短路读取”的优化值得知道客户端调用open方法向NameNode请求文件块位置。NameNode返回每个块的所有副本所在DataNode按距离排序。客户端选择最近的DataNode建立连接读取数据。如果DataNode故障客户端自动切换下一个副本。读完一个块继续读下一个块直到文件结束。短路读取是指当客户端和DataNode在同一台机器时绕过网络直接读本地磁盘文件。实验环境通常是单节点伪分布式短路读取默认可能没开但你可以通过dfs.client.read.shortcircuit开启观察读取性能变化。3.3 用代码验证读写Java API最小示例实验如果要求编程实践通常会给一个Java API的模板。这里给一个最小可运行的写读示例帮你理解Shell命令对应的API调用。import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.*; import java.io.*; public class HdfsDemo { public static void main(String[] args) throws Exception { // 加载配置自动读取core-site.xml和hdfs-site.xml Configuration conf new Configuration(); // 如果实验环境没有配置文件手动指定NameNode地址 conf.set(fs.defaultFS, hdfs://localhost:9000); FileSystem fs FileSystem.get(conf); // 写文件对应 hdfs dfs -put Path dst new Path(/user/student/api_test.txt); FSDataOutputStream out fs.create(dst, true); // true表示覆盖 out.write(hello hdfs api\n.getBytes()); out.close(); // 读文件对应 hdfs dfs -cat FSDataInputStream in fs.open(dst); BufferedReader reader new BufferedReader(new InputStreamReader(in)); String line; while ((line reader.readLine()) ! null) { System.out.println(line); } reader.close(); fs.close(); } }这段代码里fs.create对应写流程的create RPCout.write触发数据包管道传输fs.open对应读流程的open RPC。参数true表示如果文件存在就覆盖等价于-f。实验里如果报Connection refused检查fs.defaultFS的端口伪分布式通常是9000或8020以你的core-site.xml为准。4. 避坑指南实验二最容易翻车的五个点4.1 路径写错相对路径和绝对路径混用现象hdfs dfs -put data.txt /user/student/报No such file or directory但data.txt明明在当前目录。原因HDFS命令里的源路径如果是相对路径它默认相对于HDFS的当前工作目录不是本地当前目录。hdfs dfs -put的源是本地路径但如果你写hdfs dfs -ls data.txt它找的是HDFS上的/user/username/data.txt。解决上传时源路径写本地绝对路径或者用./data.txt明确本地。查看HDFS文件时路径要么写全/user/student/data.txt要么先hdfs dfs -cd切换HDFS工作目录注意-cd只在部分版本支持更稳妥的是每次写全路径。4.2 权限拒绝Permission denied的三种情况现象hdfs dfs -put报Permission denied: userstudent, accessWRITE, inode/user/student:hdfs:supergroup:drwxr-xr-x。原因HDFS上/user/student目录的属主是hdfs你当前用户是student没有写权限。实验环境里通常用hdfs用户操作或者管理员提前建好了你的家目录。如果你自己用hdfs dfs -mkdir建目录属主就是你不会报这个错。解决用hdfs dfs -ls -d /user/student看属主和权限。如果是hdfs属主用sudo -u hdfs hdfs dfs -chown student:student /user/student改属主或者直接用hdfs用户操作。实验里如果没权限改就在自己有权限的目录下做比如/tmp/student。4.3 副本数设置setrep不生效现象hdfs dfs -setrep 2 /user/student/data.txt执行成功但hdfs dfs -ls看到的副本数还是3。原因-setrep只是向NameNode提交了副本数变更请求NameNode会异步调整不是立即生效。而且如果DataNode数量少于副本数它只能设到实际DataNode数量。伪分布式只有一个DataNode你设2或3实际都只有1个副本。解决用hdfs fsck /user/student/data.txt -files -blocks查看实际块和副本状态。实验报告里如果要求“设置副本数为2”先确认你的集群有几个DataNode单节点设了也没意义但命令要会敲。4.4 回收站导致磁盘不释放现象hdfs dfs -rm -r /user/student/bigdata删了一个大目录但hdfs dfs -df -h显示空间没怎么变。原因回收站默认开启删除的文件移到了.Trash目录还占着空间。解决hdfs dfs -ls /user/student/.Trash/Current/能看到被删的文件。手动hdfs dfs -expunge清空回收站或者删除时加-skipTrash。实验环境磁盘小建议清理大目录时直接-skipTrash。4.5 安全模式NameNode is in safe mode现象任何写操作都报NameNode is in safe mode。原因NameNode启动时或磁盘空间不足时会进入安全模式只读不写。实验环境如果是刚启动集群等几十秒自动退出。如果是磁盘满了需要清理空间。解决hdfs dfsadmin -safemode get查看状态。如果是启动中等如果是磁盘满清理本地磁盘或HDFS空间。强制退出用hdfs dfsadmin -safemode leave但生产环境慎用实验里可以。5. 进阶技巧用fsck和distcp把实验做扎实5.1 用fsck检查文件健康状态实验报告通常只要求“上传、下载、查看”但如果你想真正理解HDFS的可靠性fsck是必会的。它检查文件的块完整性、副本数、是否损坏。# 检查整个文件系统的健康状态 hdfs fsck / # 检查指定文件显示块和副本详情 hdfs fsck /user/student/data.txt -files -blocks -locations # 检查并删除损坏的块实验环境慎用 hdfs fsck /user/student/data.txt -delete-files显示文件信息-blocks显示块信息-locations显示每个副本在哪个DataNode上。输出里如果看到MISSING或CORRUPT说明块有问题。实验里你可以故意删掉一个DataNode上的块文件再跑fsck看它怎么报加深理解。5.2 用distcp做集群间复制如果实验环境有两个HDFS集群或者你想模拟distcp是跨集群复制的标准工具。它底层是MapReduce任务能并行复制比-get再-put快得多。# 从本地集群复制到远程集群 hadoop distcp hdfs://cluster1:9000/user/student/data.txt hdfs://cluster2:9000/user/student/ # 复制整个目录-m指定并行度 hadoop distcp -m 10 /user/student/input/ /user/student/output/-m控制同时运行的Map任务数默认是20。实验环境如果只有单节点distcp也能跑但并行度设1就行。注意distcp的目标路径如果已存在会报错加-overwrite覆盖。5.3 一个我常做的验证习惯做完实验二我习惯用一条组合命令验证整个链路本地生成数据 → 上传 → 查看块信息 → 下载合并 → 对比本地和HDFS内容是否一致。# 生成测试数据 seq 1 100000 /tmp/test_data.txt # 上传到HDFS hdfs dfs -put /tmp/test_data.txt /user/student/ # 查看块信息 hdfs fsck /user/student/test_data.txt -files -blocks # 下载并合并 hdfs dfs -getmerge /user/student/test_data.txt /tmp/downloaded.txt # 对比 diff /tmp/test_data.txt /tmp/downloaded.txt echo 一致 || echo 不一致这个流程走一遍你对HDFS的读写、块管理、数据一致性就有了体感。实验二的意义不在于命令背得多熟而在于你以后遇到File already exists、Permission denied、Safe mode时能条件反射地知道去哪查、怎么改。我做了这么多年最深的教训就是HDFS的坑大多不在命令本身而在你对它“分布式”这三个字的理解深度。希望帮到你。本文还有配套的精品资源点击获取