ビッグデータ入門 (3) HDFS シェルと Java API

1. HDFS シェル

ほとんどの HDFS シェル コマンドは Unix シェルに似ていますが、主な違いは、HDFS シェル コマンドはリモート Hadoop サーバー上のファイルに対して動作するのに対し、Unix シェル コマンドはローカル ファイルに対して動作することです。

完全な HDFS シェル コマンドについては、公式 Web サイト「FileSystemShell および HDFS コマンド ガイド 」を参照するか、hadoop fs --help コマンドを使用して表示します。以下に、一般的に使用されるいくつかのコマンドを示します。

注文 説明する
ハドゥープFS FS は、ローカル、HDFS などの任意のファイル システムをポイントできる汎用ファイル システムに関連しているため、ローカル FS、HFTP FS、S3 FS などのさまざまなファイル システムを扱うときに使用できます (最も広く使用されており、任意のファイル システムを操作できます)。
Hadoop DFS 特に hdfs 分散ファイル システムに対して非推奨になりました
hdfs dfs hadoop dfs と同じですが、hadoop dfs を使用する場合は内部で hdfs dfs コマンドに変換されます。
  • mkdir はディレクトリを作成します。

使用方法: hadoop fs -mkdir [-p] <パス>...

説明: -p パラメータは、親ディレクトリが存在しない場合でも、ディレクトリを再帰的に作成します。ディレクトリ レベルに従ってディレクトリが自動的に作成されます。

  • put と copeFromLocal を使用してファイルをアップロードします。

put の使用方法: hadoop fs -put <localsrc> ... <dst>

説明: 単一または複数のソース パス/ファイルをローカル ファイル システムからターゲット ファイル システムにコピーし、標準入力からの入力の読み取りとターゲット ファイル システムへの書き込みもサポートします。

copyFromLocal: put と同じ。唯一の違いは、-put はより緩和されており、ローカルまたは HDFS から HDFS にファイルをコピーできるのに対し、-copyFromLocal はローカル ファイルのみを HDFS にコピーできることです。

  • ls はファイルをリストします。

使用方法: hadoop fs -ls <args>

注: HDFS でパラメータを指定しない「-ls」コマンドには戻り値がなく、デフォルトで HDFS の「ホーム」ディレクトリの内容が返されます。HDFS には、カレント ディレクトリの概念も cd コマンドもありません。

lsr コマンド:この機能は、サブディレクトリ内のファイルとディレクトリ情報を再帰的にリストします。これは非推奨となっており、hadoop fs -ls -R <args> で置き換えることができます。

  • cat:指定されたパスにあるファイルの内容を標準出力に出力します。

  • get およびcopeToLocal ファイルのダウンロード:ファイルをローカル ファイル システムにコピーします。hadoop fs -get [-f] [-p] [-ignoreCrc] [-crc] <src> ... <localdst>

-p: アクセスと変更の時刻、所有権と権限を保持します。(権限がファイルシステム間で伝播できると仮定します)

-f: ターゲットがすでに存在する場合はターゲットを上書きします

-ignorecrc: ダウンロードされたファイルの CRC チェックをスキップします。

-crc: ダウンロードされたファイルの CRC チェックサムを書き込みます

詳細情報: HADOOP の CRC データ チェック ファイル

copeToLocal: get と同じ。唯一の違いは、copeToLocal がターゲット パスをローカル ファイルのみに制限していることです。

  • rm: 指定したパス下のファイルを削除しますhadoop fs -rm [-f] [-r|-R] [-skipTrash] [-safely] URI [URI...]

HDFS にはガベージ コレクション ビン (ゴミ箱) メカニズムがあり、デフォルトでは無効になっていますが、fs.trash.interval (core-site.xml) でゼロより大きい値 (分単位) を設定することで有効にできます。ゴミ箱が有効になっている場合、HDFS は削除されたファイルをゴミ箱ディレクトリ (/user/username/.Trash/) に移動します。ファイルをごみ箱に入れずに直接削除したい場合は、-skipTrash コマンドを使用できます。

ここで設定する回復サイクルは 1 日 (60*24) です。

HDFS ゴミ箱の具体的な実装は、実際には、NameNode でバックグラウンド スレッド Emptier (org.apache.Hadoop.fs.TrashPolicyDefault.Emptier、fs.trash.classname を通じて TrashPolicy クラスを変更できます) を開くことです。このスレッドは、ライフ サイクルを超えたごみ箱内のファイルとディレクトリを定期的に自動的に削除します。あるいは、ユーザーがごみ箱内のファイルを手動で削除することもできます。ごみ箱内のファイルを削除する操作は、他のファイル ディレクトリを削除するのと同じです。唯一の違いは、HDFS がファイル ディレクトリがごみ箱であるかどうかを検出することです。ごみ箱である場合、HDFS はファイルをごみ箱に入れません。

rmr コマンド:この機能は、ファイル ディレクトリ内のすべてのファイルを再帰的に削除することです。これは非推奨になっており、hadoop fs -rm [-R | -r] <URI> で置き換えることができます。

  • expunge コマンド: hadoop fs -expunge [-immediate]

hadoop fs -expunge を初めて実行するとき、HDFS は新しいチェックポイントを作成し、ゴミ箱に保存されている最近削除されたファイルをチェックポイントに移動します。次回の hadoop fs -expunge の実​​行時 (コア サイトで fs.trash.checkpoint.interval プロパティを構成している場合に注意してください)。(注:詳細については、「ファイルの削除と削除の取り消し」を参照してください)

-immediate オプションが渡された場合、fs.trash.interval 設定は無視され、現在のユーザーのすべてのゴミ箱ファイルが直ちに削除されます。

  • du: hadoop fs [汎用オプション] -du [-s] [-h] [-v] [-x] <path> ... ディレクトリ内のすべてのファイルのサイズを表示します

注: 最初の列は、このディレクトリ内のファイルの合計サイズを示し、2 番目の列は、クラスター上のこのディレクトリ内のすべてのファイルの合計ストレージ サイズ (ファイル サイズ * コピー係数に等しい) を示し、3 番目の列は、クエリしているディレクトリです。

  • setrep: hadoop fs -setrep [-R] [-w] <numReplicas> <path> ファイルのレプリカ係数を変更するために使用されます。path がディレクトリの場合、コマンドは path をルートとするディレクトリ ツリーの下にあるすべてのファイルのコピー係数を再帰的に変更します。

-w パラメーターはコマンドが完了するまで待機しますが、これには長い時間がかかる場合があります。-R パラメータは下位互換性のためのものですが、効果はありません。

  • mv: hadoop fs -mv URI [URI ...] <dest> ファイルをソースから宛先に移動します。このコマンドでは複数のソースも許可されます。その場合、宛先はディレクトリである必要があります。ファイルシステム間でのファイルの移動は許可されていません。

ここでは、dir2 ディレクトリ全体が dir1 に移動されています。

  • cp: hadoop fs -cp [-f] [-p | -p[topax]] URI [URI ...] <dest> コピー元からコピー先にファイルをコピーします。このコマンドでは複数のソースも許可されます。その場合、宛先はディレクトリである必要があります。

  • head: hadoop fs -head URI は、ファイルの最初の 1KB を標準出力に出力します。
  • tail: hadoop fs -tail [-f] URI ファイルの末尾の 1KB の内容を標準出力に表示します。Unix と同様に、-f パラメータを使用すると、コンテンツの最後の 1KB を継続的に出力できます。

  • stat:ファイル/ディレクトリの統計を指定された形式で出力します。この形式では、8 進数 (%a) および記号 (%a)、バイト単位のファイル サイズ (%b)、タイプ (%F)、所有者のグループ名 (%g)、名前 (%n)、ブロック サイズ (%o)、コピー (%r)、所有者のユーザー名 (%u)、アクセス日 (%x、%x)、および変更日 (%y、%y) のアクセス許可を受け入れます。%x と %y は UTC 日付を「yyyy-MM-dd HH:mm:ss」として示し、%x と %y は 1970 年 1 月 1 日の UTC 時間のミリ秒を示します。形式が指定されていない場合は、デフォルトで %y が使用されます。
hadoop fs -stat "type:%F perm:%a %u:%g size:%b mtime:%y atime:%x name:%n" /user/hadoop/dir1/testHDFS.txt

  • テスト: hadoop fs -test -[defswrz] URI 
  1. -d: パスがディレクトリの場合は 0 を返します。
  2. -e: パスが存在する場合は 0 を返します。
  3. -f: パスがファイルの場合は 0 を返します。
  4. -s: パスが空でない場合は 0 を返します。
  5. -w: パスが存在し、書き込み権限が付与されている場合は 0 を返します。
  6. -r: パスが存在し、読み取り権限がある場合は 0 を返します。
  7. -z: ファイル長が 0 の場合は 0 を返します。

bash で $? を使用して、最後の呼び出しの戻り値を取得します。

  • text: hadoop fs -text <src> はソース ファイルを取得し、そのファイルをテキスト形式で出力します。許可される形式は zip と TextRecordInputStream です。

  • touchz: hadoop fs -touchz URI [URI ...] 0 バイトの空のファイルを作成します

  • セーフ モード コマンド: HDFS の NameNode は、起動時に自動的にセーフ モードに入ります。セーフモードは、ファイル システムへの変更が許可されない NameNode の状態です。セーフ モードの目的は、システム起動時に各データノード上のデータ ブロックの正当性を確認し、ポリシーに従って必要に応じてデータ ブロックをコピーまたは削除することであり、データ ブロックのコピー数が最小コピー数を満たした場合、セーフ モードは自動的に終了します。HDFS がセーフ モードに入ると、Hive と HBase が異常に起動することに注意してください。拡張: HDFS セキュリティ モードについての理解       セキュリティ モードの操作コマンドは次のとおりです。
# 进入安全模式
hadoop dfsadmin -safemode enter

# 退出安全模式
hadoop dfsadmin -safemode leave

# 查看集群是否处于安全模式
hadoop dfsadmin -safemode get

 

二、HDFS Java API

2.1 IDEA (Windows) が仮想マシン Hadoop クラスターに接続する

Windows 上の仮想マシン上の Hadoop クラスターに接続するには、次のような事前準備が必要です。

  1. まず、 Windows でディレクトリを見つけて、「ビッグデータ入門 (1) Hadoop 擬似分散インストール」の最初のセクションでダウンロードした hadoop-3.0.0.tar.gz を解凍します。
  2. 次に、winutils ミラーからhadoop.dllwinutils.exe をダウンロードし、hadoop-3.0.0.tar.gz 解凍されたディレクトリの bin ディレクトリにコピーします。
  3. 最後に、環境変数 HADOOP_HOME を構成します。その値は、ディレクトリを解凍した hadoop-3.0.0.tar.gz であり、$HADOOP_HOME\bin をシステム変数のパスに追加します。

2.2 IDEA プロジェクトのテスト

新しい Spring プロジェクトを作成します。pom ファイルの依存関係は次のとおりです。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>hadoopdemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>hadoopdemo</name>
    <description>Demo project for Hadoop</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--引入hadoop-client Jar包  -->
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>3.1.1</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>log4j-over-slf4j</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-api</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- 引入hadoop-common Jar包 -->
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>3.1.1</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>log4j-over-slf4j</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-api</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- 引入hadoop-hdfs Jar包 -->
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-hdfs</artifactId>
            <version>3.1.1</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

次に、HDFS の構成クラスがあります。

package com.example.hadoopdemo.config;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.springframework.context.annotation.Bean;

import java.net.URI;

@org.springframework.context.annotation.Configuration
public class HDFSConfig {
    private static String HDFS_URI = "hdfs://hadoop0:9000/";

    @Bean
    public FileSystem getFileSystem() throws Exception {
        Configuration configuration = new Configuration();
        FileSystem fs = FileSystem.get(new URI(HDFS_URI), configuration, "root");
        return fs;
    }
}

上記の情報を構成すると、HDFS を使用できるようになります。Hadoop のファイル操作クラスは基本的に「org.apache.hadoop.fs」パッケージに含まれており、これらの API でサポートされる操作には、ファイルを開く、ファイルの読み書き、ファイルの削除などがあります。サンプルコードは次のとおりです。

package com.example.hadoopdemo.utils;

import org.apache.hadoop.fs.*;
import org.apache.hadoop.hdfs.DistributedFileSystem;
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
import org.apache.hadoop.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.OutputStream;

@Component
public class HDFSUtils {
    @Autowired
    private FileSystem hdfs;

    // 判断文件、目录是否存在
    public boolean isExists(String pathString) throws IOException {
        Path path = new Path(pathString);
        return hdfs.exists(path);
    }

    // 上传文件
    public void upload(String src, String dst) throws IOException {
        Path scrPath = new Path(src);
        Path dstPath = new Path(dst);
        hdfs.copyFromLocalFile(scrPath, dstPath);
    }

    // 下载文件
    public void download(String src, String dst) throws IOException {
        Path scrPath = new Path(src);
        Path dstPath = new Path(dst);
        hdfs.copyToLocalFile(scrPath, dstPath);
    }

    // 创建文件并写入数据
    public void createFile(String dst, String context) throws IOException {
        Path dstPath = new Path(dst);
        FSDataOutputStream outputStream = hdfs.create(dstPath);
        outputStream.write(context.getBytes());
        outputStream.close();
    }

    // 创建目录
    public boolean createDir(String dir) throws IOException {
        return hdfs.mkdirs(new Path(dir));
    }

    // 文件重命名
    public boolean renameFile(String src, String dst) throws IOException {
        return hdfs.rename(new Path(src), new Path(dst));
    }

    // 删除文件或目录,recursive标志用来确定是否要递归删除
    public boolean delete(String src, boolean recursive) throws IOException {
        return hdfs.delete(new Path(src), recursive);
    }

    // 读取文件, 输出到outputStream
    public void readFile(String src, OutputStream outputStream) throws IOException {
        FSDataInputStream inputStream = hdfs.open(new Path(src));
        IOUtils.copyBytes(inputStream, outputStream, 1024, false);
        IOUtils.closeStream(inputStream);
    }

    // 查看指定目录下的文件信息
    public void list(String src) throws IOException {
        FileStatus[] fileStatusList = hdfs.listStatus(new Path(src));
        for (FileStatus fileStatus : fileStatusList) {
            // 文件路径
            System.out.println(fileStatus.getPath());
            // 文件的修改时间
            System.out.println(fileStatus.getModificationTime());
        }
    }

    // 获取DataNode信息
    public void getNodeMessage() throws IOException {
        DistributedFileSystem distributedFileSystem = (DistributedFileSystem) hdfs;
        DatanodeInfo[] datanodeInfos = distributedFileSystem.getDataNodeStats();
        for (int i = 0; i < datanodeInfos.length; i++) {
            System.out.println("DataNode_" + i + "_Name: " + datanodeInfos[i].getHostName());
        }
    }
}

テストコードは次のとおりです。

package com.example.hadoopdemo;

import com.example.hadoopdemo.utils.HDFSUtils;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class HDFSTest {
    @Autowired
    private HDFSUtils hdfsUtils;

    @Test
    public void test() throws Exception {
        System.out.println("hdfs目录是否存在:" + hdfsUtils.isExists("/hdfs"));
        System.out.println("创建hdfs目录:" + hdfsUtils.createDir("/hdfs"));
        hdfsUtils.upload("C:\\Users\\Minghui.Ni\\Desktop\\test.txt", "/hdfs");
        System.out.println("test.txt文件是否上传成功:" + hdfsUtils.isExists("/hdfs/test.txt"));
        System.out.println("test.txt重命名为hdfsTest.txt:" + hdfsUtils.renameFile("/hdfs/test.txt", "/hdfs/hdfsTest.txt"));
        hdfsUtils.readFile("/hdfs/hdfsTest.txt", System.out);
        System.out.println("\n");
        hdfsUtils.createFile("/hdfs/test2.txt", "Hello HDFS\n");
        hdfsUtils.readFile("/hdfs/test2.txt", System.out);
        hdfsUtils.list("/hdfs");
        hdfsUtils.getNodeMessage();
        hdfsUtils.delete("/hdfs", true);
        System.out.println("hdfs目录是否删除成功:" + !hdfsUtils.isExists("/hdfs"));
    }
}

実行中のスクリーンショットは次のとおりです。

 

3. その他

Spring for Apache Hadoop - リファレンスドキュメント

 

おすすめ

転載: blog.csdn.net/qq_37771475/article/details/116596779