HDFS 实验操作指南:命令行与 Python API 交互

实验目标

  1. 掌握HDFS常用的Shell命令,能够通过命令行完成文件系统的基本操作(如创建目录、上传/下载文件、查看文件、删除等)。

  2. 理解HDFS的目录结构和文件存储的基本原理。

  3. 学习如何使用Python语言连接到HDFS,并以编程方式进行文件操作。

  4. 掌握在Windows PyCharm中配置WSL作为远程解释器,以连接到Docker中Hadoop环境的实践技巧。

实验环境准备

  1. Windows 11/10: 已安装并启用WSL2。

  2. WSL2: 已安装任一Linux发行版(如Ubuntu)。

  3. Docker Desktop: 已在Windows上安装,并已配置为使用WSL2后端。

  4. Hadoop Docker环境: 您的GitHub开源Hadoop项目已通过docker-compose up -d或类似命令成功启动。请确保Hadoop集群处于健康运行状态。

  5. PyCharm: Professional版(社区版不支持远程解释器)。

  6. 网络端口: 确保Hadoop NameNode的WebHDFS端口(默认为9870)已经从Docker容器映射到了您的主机。通常在docker-compose.yml文件中会有类似ports: - "9870:9870"的配置。


第一部分:HDFS 命令行接口 (CLI) 操作

这部分操作需要进入到Hadoop NameNode的Docker容器内部来执行。HDFS的命令行工具可以让我们像操作本地Linux文件系统一样操作分布式文件系统。

步骤1:进入Hadoop NameNode容器

首先,我们需要获取一个通往Hadoop集群的“入口”,也就是NameNode容器的bash shell。

  1. 打开Windows的PowerShell或CMD终端。

  2. 列出当前正在运行的Docker容器,找到NameNode容器的名称或ID。

    Bash

    docker ps

    您会看到类似下面的输出,请记下NameNode容器的名称(例如 hadoop-namenode-1)。

    CONTAINER ID   IMAGE                               COMMAND                  CREATED         STATUS         PORTS                                           NAMES
    a1b2c3d4e5f6   bde2020/hadoop-namenode:2.0.0-hadoop3.2.1-java8   "/entrypoint.sh /run…"   2 hours ago     Up 2 hours     0.0.0.0:9000->9000/tcp, 0.0.0.0:9870->9870/tcp   namenode
    ...
  3. 使用docker exec命令进入该容器的交互式bash环境。

    Bash

    docker exec -it namenode /bin/bash
    • docker exec: 在一个正在运行的容器中执行命令。

    • -it: -i (interactive) 保持标准输入打开,-t (tty) 分配一个伪终端。合起来就是我们熟悉的交互式Shell。

    • hadoop-namenode-1: 您的NameNode容器名。

    • /bin/bash: 要在容器内执行的命令,即启动bash shell。

成功后,您的命令提示符会变为类似 root@a1b2c3d4e5f6:/# 的形式,表示您已在容器内部。

步骤2:HDFS常用命令实践

所有HDFS的命令都以hdfs dfs开头,后面跟上具体的指令,与Linux命令非常相似。

  1. 检查HDFS状态

    这是一个很好的起点,可以确认HDFS集群是否健康。

    Bash

    hdfs dfsadmin -report
    • 命令含义:

      • hdfs dfsadmin: Hadoop分布式文件系统的管理命令。

      • -report: 生成一个关于集群当前状态的报告,会显示总容量、已用空间、可用空间以及存活/死亡的DataNode数量等信息。

  2. 创建目录 (mkdir)

    我们将在HDFS的根目录下创建一个用于本次实验的专属目录。

    Bash

    hdfs dfs -mkdir -p /user/lab_exp
    • 命令含义:

      • -mkdir: "make directory"的缩写,用于创建目录。

      • -p: "parent"的缩写,如果父目录(这里是/user)不存在,会自动创建它。这能避免因父目录不存在而导致的错误。

      • /user/lab_exp: 我们要在HDFS中创建的目录的绝对路径。

  3. 列出文件和目录 (ls)

    查看我们刚刚创建的目录是否存在。

    Bash

    hdfs dfs -ls /user
    命令含义:
    • -ls: "list"的缩写,用于列出指定路径下的文件和目录信息,类似于ls -l

    • 预期输出: 您应该能看到刚刚创建的lab_exp目录。

  4. 上传文件到HDFS (put/copyFromLocal)

    我们将先在容器的本地文件系统创建一个示例文本文件,然后上传到HDFS。

    Bash

    # 在容器的/tmp目录下创建一个本地文件
    echo "Hello HDFS from Docker container!" > /tmp/hello.txt
    ​
    # 将本地文件上传到HDFS的指定目录
    hdfs dfs -put /tmp/hello.txt /user/lab_exp/
    命令含义:
    • /user/lab_exp/: 目标路径(在HDFS上)。

    • /tmp/hello.txt: 源文件路径(在容器的本地文件系统里)。

    • -put: 将文件或目录从本地文件系统复制到HDFS。

    • echo ... > ...: Linux命令,创建一个包含指定文本的文件。

  5. 查看HDFS中的文件内容 (cat)

    不下载文件,直接在终端查看HDFS上文件的内容。

    Bash

    hdfs dfs -cat /user/lab_exp/hello.txt
    命令含义:
    • -cat: "concatenate"的缩写,将指定路径的文件内容输出到标准输出(也就是您的终端)。

    • 预期输出: Hello HDFS from Docker container!

  6. 从HDFS下载文件 (get/copyToLocal)

    将HDFS上的文件下载回容器的本地文件系统。

    Bash

    # -f 选项表示如果本地已存在同名文件,则覆盖它
    hdfs dfs -get -f /user/lab_exp/hello.txt /tmp/hello_from_hdfs.txt
    
    # 验证一下文件是否已下载到容器本地h
    ls -l /tmp
    cat /tmp/hello_from_hdfs.txt
    命令含义:
    • -f: "force"的缩写,强制覆盖本地同名文件。

    • -get: 将文件或目录从HDFS复制到本地文件系统。

  7. 删除HDFS上的文件和目录 (rm)

    实验结束,清理我们创建的文件和目录。

    Bash

    # 删除文件
    hdfs dfs -rm /user/lab_exp/hello.txt
    
    # 删除空目录
    hdfs dfs -rmdir /user/lab_exp
    命令含义:
    • -rmdir: "remove directory"的缩写,只能用于删除空目录。

    • -rm: "remove"的缩写,用于删除HDFS上的文件。如果要删除非空目录,需要使用 -rm -r

  8. 退出容器

    完成命令行操作后,输入以下命令返回到您的Windows终端。

    Bash

    exit

第二部分:使用 Python 操作 HDFS

这部分是本次实验的核心,我们将配置PyCharm,并编写Python脚本来完成与第一部分类似的文件操作。

步骤1:安装Python HDFS库

我们需要一个库来帮助Python与HDFS的WebHDFS API进行通信。hdfs是一个非常简单易用的选择。

  1. 在PyCharm底部的Terminal中,使用pip安装hdfs库。

    Bash

    pip install hdfs
步骤2:修改docker-compose.yml

这是最正确、最稳定的解决方案。我们需要通过环境变量来“覆盖”Hadoop的配置,告诉DataNode在向NameNode注册时,上报一个外部可以访问的地址。

  1. 找到docker-compose.yml文件

  2. 定位到datanode服务,为它添加或修改environment部分,明确告诉它在向NameNode注册时,使用localhost作为自己的主机名。

    YAML

    services:
      namenode:
        environment:
          - CLUSTER_NAME=test
          - HDFS_CONF_dfs_client_use_datanode_hostname=true  
        ... # 其他配置保持不变
    
      datanode:
      ... # 其他配置保持不变
        ports:
          - "9864:9864"
        volumes:
          - hadoop_datanode:/hadoop/dfs/data
        environment:
          - SERVICE_PRECONDITION=namenode:9870
          - HDFS_CONF_dfs_datanode_hostname=localhost
          - HDFS_CONF_dfs_client_use_datanode_hostname=true
        ...

更新: 一个更现代和可能更兼容的配置是,直接声明一个所有节点都能访问的域名。对于您的情况,最简单的是让datanode直接使用IP地址进行通信,而不是主机名。上面的CORE_CONF_环境变量是一种常见的方式,它会修改core-site.xml的配置。您需要根据您使用的Docker镜像的文档来确认修改配置的确切环境变量名称。但以上配置的意图是强制HDFS在节点间通信和客户端重定向时使用IP地址而非主机名

  1. 重启Hadoop集群: 在docker-compose.yml文件所在的目录下,打开终端,执行以下命令来让配置生效:

    Bash

    docker-compose down
    docker-compose up -d

    重启后,当NameNode再重定向您的Python客户端时,它就会提供一个基于IP的、您的Windows主机可以理解的地址,问题就解决了。

步骤3:编写Python代码操作HDFS

现在,在您的PyCharm项目中创建一个新的Python文件(例如 hdfs_experiment.py),并输入以下代码。

Python

# 导入hdfs库中的InsecureClient
from hdfs import InsecureClient

# --- 1. 连接到HDFS ---
# NameNode的WebHDFS端口默认是9870。由于Docker端口已映射,
# 并且我们的代码运行在WSL中,可以直接通过localhost访问。
# 'root' 是很多开源Hadoop Docker镜像的默认超级用户。
try:
    client = InsecureClient('http://localhost:9870', user='root')
    print("成功连接到HDFS!")
except Exception as e:
    print(f"连接HDFS失败: {e}")
    exit()

# 定义我们要在HDFS上操作的目录和文件路径
hdfs_base_dir = '/user/python_lab'
hdfs_file_path = f'{hdfs_base_dir}/greetings.txt'
local_download_path = './downloaded_from_hdfs.txt' # 下载到PyCharm项目目录下

try:
    # --- 2. 创建目录 ---
    # 使用 client.makedirs() 创建目录,它类似于 mkdir -p,即使目录已存在也不会报错。
    client.makedirs(hdfs_base_dir)
    print(f"HDFS目录 '{hdfs_base_dir}' 已创建或已存在。")

    # --- 3. 列出目录内容,验证创建 ---
    # client.list() 返回一个包含文件名和目录名的列表
    dir_content = client.list('/user/')
    print(f"/user/ 目录下的内容: {dir_content}")
    if 'python_lab' in dir_content:
        print("目录创建成功!")

    # --- 4. 写入(上传)文件 ---
    # 使用 with...as 语法可以安全地写入数据。
    # data参数需要是字节串(bytes),所以字符串前要加'b'或进行encode()
    file_content = "Hello HDFS from Python! This is a test."
    with client.write(hdfs_file_path, encoding='utf-8', overwrite=True) as writer:
        writer.write(file_content)
    print(f"文件 '{hdfs_file_path}' 已成功写入。")

    # --- 5. 读取(查看)文件内容 ---
    # 使用 with...as 语法安全地读取数据。
    with client.read(hdfs_file_path, encoding='utf-8') as reader:
        content_from_hdfs = reader.read()
    print(f"从HDFS读取到的文件内容:\n---\n{content_from_hdfs}\n---")
    assert file_content == content_from_hdfs

    # --- 6. 下载文件到本地 ---
    # client.download() 返回下载到本地的文件路径
    downloaded_path = client.download(hdfs_file_path, local_download_path, overwrite=True)
    print(f"文件已从HDFS下载到本地: '{downloaded_path}'")
    # 你可以检查一下PyCharm项目左侧的文件浏览器,会看到这个新文件

    # --- 7. 清理实验文件和目录 ---
    # client.delete() 可以删除文件或目录。
    # recursive=True 表示如果删除的是目录,则递归删除其下所有内容。
    deleted = client.delete(hdfs_base_dir, recursive=True)
    if deleted:
        print(f"实验目录 '{hdfs_base_dir}' 及内容已成功删除。")

except Exception as e:
    print(f"操作HDFS时发生错误: {e}")

finally:
    print("\n实验结束。")

步骤4:运行并理解Python代码

  1. 运行脚本: 在PyCharm中运行即可。

  2. 观察输出: 仔细观察PyCharm的运行控制台输出,它会一步步地显示连接、创建、写入、读取、下载和删除的过程。

  3. 代码讲解:

    • from hdfs import InsecureClient: 我们从hdfs库导入InsecureClient类。Insecure意味着我们没有配置Kerberos安全认证,这在实验环境中是常见的。

    • client = InsecureClient('http://localhost:9870', user='root'): 这是最关键的一步。我们创建一个客户端实例来与HDFS通信。

    • http://localhost:9870: 这是HDFS NameNode的WebHDFS服务的地址。因为我们的代码运行在WSL中,localhost可以正确地指向WSL自己,而Docker容器的9870端口已经映射到了WSL上。

    • user='root': 指定以哪个用户的身份来操作HDFS。HDFS有权限系统,root用户通常拥有最高权限。

    • client.makedirs(path): 创建目录,等同于hdfs dfs -mkdir -p

    • client.list(path): 列出目录内容,等同于hdfs dfs -ls

    • client.write(path, ...): 写入数据到HDFS文件,等同于echo "..." | hdfs dfs -put - path 的编程版本。

    • client.read(path, ...): 从HDFS文件中读取数据,等同于hdfs dfs -cat

    • client.download(hdfs_path, local_path): 从HDFS下载文件,等同于hdfs dfs -get

    • client.delete(path, recursive=True): 删除文件或目录,等同于hdfs dfs -rm -r


Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐