HDFS的shell操作

基本语法

  1. hadoop fs 具体命令
  2. hdfs dfs 具体命令

命令大全

  1. [root@hadoop03 bin]# hadoop fs
  2. Usage: hadoop fs [generic options]
  3. [-appendToFile <localsrc> ... <dst>]
  4. [-cat [-ignoreCrc] <src> ...]
  5. [-checksum <src> ...]
  6. [-chgrp [-R] GROUP PATH...]
  7. [-chmod [-R] <MODE[,MODE]... | OCTALMODE> PATH...]
  8. [-chown [-R] [OWNER][:[GROUP]] PATH...]
  9. [-copyFromLocal [-f] [-p] [-l] [-d] [-t <thread count>] <localsrc> ... <dst>]
  10. [-copyToLocal [-f] [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
  11. [-count [-q] [-h] [-v] [-t [<storage type>]] [-u] [-x] [-e] <path> ...]
  12. [-cp [-f] [-p | -p[topax]] [-d] <src> ... <dst>]
  13. [-createSnapshot <snapshotDir> [<snapshotName>]]
  14. [-deleteSnapshot <snapshotDir> <snapshotName>]
  15. [-df [-h] [<path> ...]]
  16. [-du [-s] [-h] [-v] [-x] <path> ...]
  17. [-expunge]
  18. [-find <path> ... <expression> ...]
  19. [-get [-f] [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
  20. [-getfacl [-R] <path>]
  21. [-getfattr [-R] {-n name | -d} [-e en] <path>]
  22. [-getmerge [-nl] [-skip-empty-file] <src> <localdst>]
  23. [-head <file>]
  24. [-help [cmd ...]]
  25. [-ls [-C] [-d] [-h] [-q] [-R] [-t] [-S] [-r] [-u] [-e] [<path> ...]]
  26. [-mkdir [-p] <path> ...]
  27. [-moveFromLocal <localsrc> ... <dst>]
  28. [-moveToLocal <src> <localdst>]
  29. [-mv <src> ... <dst>]
  30. [-put [-f] [-p] [-l] [-d] <localsrc> ... <dst>]
  31. [-renameSnapshot <snapshotDir> <oldName> <newName>]
  32. [-rm [-f] [-r|-R] [-skipTrash] [-safely] <src> ...]
  33. [-rmdir [--ignore-fail-on-non-empty] <dir> ...]
  34. [-setfacl [-R] [{-b|-k} {-m|-x <acl_spec>} <path>]|[--set <acl_spec> <path>]]
  35. [-setfattr {-n name [-v value] | -x name} <path>]
  36. [-setrep [-R] [-w] <rep> <path> ...]
  37. [-stat [format] <path> ...]
  38. [-tail [-f] [-s <sleep interval>] <file>]
  39. [-test -[defsz] <path>]
  40. [-text [-ignoreCrc] <src> ...]
  41. [-touch [-a] [-m] [-t TIMESTAMP ] [-c] <path> ...]
  42. [-touchz <path> ...]
  43. [-truncate [-w] <length> <path> ...]
  44. [-usage [cmd ...]]

命令实操

1、hadoop fs -help rm
    结果:
    [root@hadoop03 hadoop-3.1.3]# hadoop fs -help rm
-rm [-f] [-r|-R] [-skipTrash] [-safely] <src> ... :
  Delete all files that match the specified file pattern. Equivalent to the Unix
  command "rm <src>"

  -f          If the file does not exist, do not display a diagnostic message or 
              modify the exit status to reflect an error.                        
  -[rR]       Recursively deletes directories.                                   
  -skipTrash  option bypasses trash, if enabled, and immediately deletes <src>.  
  -safely     option requires safety confirmation, if enabled, requires          
              confirmation before deleting large directory with more than        
              <hadoop.shell.delete.limit.num.files> files. Delay is expected when
              walking over large directory recursively to count the number of    
              files to be deleted before the confirmation. 

2、上传(从本地上传到HDFS)
    2.1 moveFromLocal (剪切)
    hadoop fs -mkdir /wkmac
    vim wkmac.txt(随便写几个字)
    hadoop fs -moveFromLocal ./wkmac.txt /wkmac
    2.2 copyFromLocal (拷贝)
    vim zlsmac.txt
    hadoop fs -copyFromLocal ./zlsmac.txt /wkmac
    2.3 put 等同于 copyFromLocal
    vim ztmac.txt
    hadoop fs -put ./ztmac.txt /wkmac
    OR hdfs dfs -put ./ztmac/txt /wkmac
    2.4 appendToFile  追加一个文件到已经存在的文件末尾
3、下载(从HDFS下载到本地)
    3.1、copyToLocal
    hadoop fs -copyToLocal /wkmac/wkmac.txt ./

    3.2、get 等同于copyToLocal
    hadoop fs -get /input ./
4、显示目录信息
    hadoop fs -ls /wkmac
5、查看文件内容
    hadoop fs -cat /wkmac/wkmac.txt
6、修改文件权限
    hadoop fs  -chmod 777 /wkmac/wkmac.txt
    hadoop fs  -chown  labour:labour   /wkmac/wkmac.txt
7、创建路径
    hadoop fs -mkdir /test
8、拷贝(HDFS目录之间的拷贝)
    hadoop fs -cp /wkmac/wkmac.txt /test
9、移动
    hadoop fs -mv  /wkmac/wkmac.txt /test
10、显示一个文件末尾1kb的数据
    hadoop fs -tail /test/wkmac.txt
11、删除
    hadoop fs -rm /wkmac
    hadoop fs -rm -rf /wkmac     (递归删除)
12、统计文件夹大小
    hadoop fs -du -s -h /wkmac
        输出:
            42  126  /wkmac (42 文件大小 126 表示文件大小*副本数)
    hadoop fs -du  -h /wkmac
        输出:
            21  63  /wkmac/wkmac.txt
            11  33  /wkmac/zlsmac.txt
            10  30  /wkmac/ztmac.txt
13、设置HDFS副本数量
    hadoop fs -setrep 4 /wkmac
    给文件夹设置副本数时,文件夹下所有的文件都会被设置
        Replication 4 set: /wkmac/wkmac.txt
        Replication 4 set: /wkmac/zlsmac.txt
        Replication 4 set: /wkmac/ztmac.txt

idea中操作HDFS

导入依赖包

<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-common -->
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>3.1.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>3.1.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-hdfs</artifactId>
            <version>3.1.3</version>
        </dependency>

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-mapreduce-client-core</artifactId>
            <version>3.1.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-mapreduce-client-common</artifactId>
            <version>3.1.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-mapreduce-client-jobclient</artifactId>
            <version>3.1.3</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-yarn-api -->
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-yarn-api</artifactId>
            <version>3.1.3</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-yarn-common -->
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-yarn-common</artifactId>
            <version>3.1.3</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-yarn-client -->
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-yarn-client</artifactId>
            <version>3.1.3</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-yarn-server-common -->
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-yarn-server-common</artifactId>
            <version>3.1.3</version>
        </dependency>

编写操作代码

使用客户端操作HDFS时,是有一个用户身份的。默认情况下,HDFS客户端API会采用Windows/MacOS的默认用户去访问HDFS,会报权限异常错误,所以在访问HDFS时,需要配置用户


    /**
     * 测试创建文件
     */
    public void testMkdirs() throws URISyntaxException, IOException, InterruptedException{
        Configuration configuration = new Configuration();

        FileSystem fs = FileSystem.get(new URI("hdfs://hadoop03:8020"), configuration,"root");

        // 2 创建目录
        fs.mkdirs(new Path("/ideatest/cjml/"));

        // 3 关闭资源
        fs.close();

    }
    /**
     * 测试上传文件
     */
    public static void testCopyFromLocalFile() throws IOException, URISyntaxException, InterruptedException {
        Configuration configuration = new Configuration();
        configuration.set("dfs.replication", "2");
        FileSystem fs = FileSystem.get(new URI("hdfs://hadoop03:8020"), configuration, "root");

        // 2 上传文件
        fs.copyFromLocalFile(new Path("/Users/wukai/Downloads/iShot2021-12-08 23.47.13.png"), new Path("/ideatest/cjml/"));

        // 3 关闭资源
        fs.close();

    }
    /**
     *测试文件下载
     */
    public static void testCopyToLocalFile() throws URISyntaxException, IOException, InterruptedException {
        Configuration configuration = new Configuration();
        FileSystem fs = FileSystem.get(new URI("hdfs://hadoop03:8020"), configuration, "root");

        // 2 执行下载操作
        // boolean delSrc 指是否将原文件删除
        // Path src 指要下载的文件路径
        // Path dst 指将文件下载到的路径
        // boolean useRawLocalFileSystem 是否开启文件校验
        fs.copyToLocalFile(false, new Path("/ideatest/cjml/iShot2021-12-08 23.47.13.png"), new Path("/Users/wukai/Downloads/iShot2021-12-08 23.47.13.png"), true);

        // 3 关闭资源
        fs.close();

    }
/**
     *测试文件改名
     */
    public static void testRename() throws IOException, URISyntaxException, InterruptedException {
        Configuration configuration = new Configuration();
        FileSystem fs = FileSystem.get(new URI("hdfs://hadoop03:8020"), configuration, "root");
        fs.rename(new Path("/ideatest/cjml/iShot2021-12-08 23.47.13.png"), new Path("/ideatest/cjml/beauty.png"));
        fs.close();
    }
    /**
     *测试删除文件
     */
    public static void testDelete() throws IOException, URISyntaxException, InterruptedException {
        Configuration configuration = new Configuration();
        FileSystem fs = FileSystem.get(new URI("hdfs://hadoop03:8020"), configuration, "root");
        fs.delete(new Path("/ideatest/cjml/beauty.png"),true);
        fs.close();
    }
    /**
     *获取文件详情(查看文件名称、权限、长度、块信息)
     */
    public static void testListFiles() throws IOException, URISyntaxException, InterruptedException {
        Configuration configuration = new Configuration();
        FileSystem fs = FileSystem.get(new URI("hdfs://hadoop03:8020"), configuration, "root");
        // 2 获取文件详情
        RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/"), true);

        while (listFiles.hasNext()) {
            LocatedFileStatus fileStatus = listFiles.next();

            System.out.println("========" + fileStatus.getPath() + "=========");
            System.out.println(fileStatus.getPermission());
            System.out.println(fileStatus.getOwner());
            System.out.println(fileStatus.getGroup());
            System.out.println(fileStatus.getLen());
            System.out.println(fileStatus.getModificationTime());
            System.out.println(fileStatus.getReplication());
            System.out.println(fileStatus.getBlockSize());
            System.out.println(fileStatus.getPath().getName());

            // 获取块信息
            BlockLocation[] blockLocations = fileStatus.getBlockLocations();
            System.out.println(Arrays.toString(blockLocations));
        }
        // 3 关闭资源
        fs.close();

    }

HDFS写数据流程

HDFS使用 - 图1

1、客户端通过Distributed FileSystem模块向NameNode请求上传文件,NameNode检查目标文件是否已存在,父目录是否存在
2、NameNode返回是否可以上传
3、客户端请求第一个 Block上传到哪几个DataNode服务器上
4、NameNode返回3个DataNode节点,分别为dn1、dn2、dn3
5、客户端通过FSDataOutputStream模块请求dn1上传数据,dn1收到请求会继续调用dn2,然后dn2调用dn3,将这个通信管道建立完成
6、dn1、dn2、dn3逐级应答客户端
7、客户端开始往dn1上传第一个Block(先从磁盘读取数据放到一个本地内存缓存),以Packet为单位,dn1收到一个Packet就会传给dn2,dn2传给dn3;dn1每传一个packet会放入一个应答队列等待应答
8、当一个Block传输完成之后,客户端再次请求NameNode上传第二个Block的服务器。(重复执行3-7步)

在HDFS写数据的过程中,NameNode会选择距离待上传数据最近距离的DataNode接收数据

HDFS读数据流程

HDFS使用 - 图2

1、客户端通过DistributedFileSystem向NameNode请求下载文件,NameNode通过查询元数据,找到文件块所在的DataNode地址
2、挑选一台DataNode(就近原则,然后随机)服务器,请求读取数据
3、DataNode开始传输数据给客户端(从磁盘里面读取数据输入流,以Packet为单位来做校验)
4、客户端以Packet为单位接收,先在本地缓存,然后写入目标文件