获取HDFS集群所有目录的扩展属性信息

b106cd284ab0aa6d14ee87c253add9a3.png

9cf08b329c227282d764ba8434509dd4.png

b10cefea83abbda8d79082c05cd51c05.png

0fda968af45b283c2ce516ec6bd473d6.png

6938e800d301abe66cfd6b3b8d9fa7d5.png

官网参考链接

Extended Attributes in HDFS(简称xattrs)

https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/ExtendedAttributes.html

本次编写目的是如何获取集群所有目录的扩展属性信息,所以概念相关的请参考官网,这里不做过多赘述。

e7db89ae2addb5b7390854656c6bfa1b.png

HDFS的扩展属性信息简要解释

9dc5cc3012e923e624015776c5739038.png

这个概念其实就是额外的属性信息,通俗的理解就是HDFS目录或者文件在生成的时候会带有基础权限、用户、用户组等一些基本信息,那么我还想添加一些我认为需要备注的信息如:user.张三 values为"这个目录是张三创建的",那么通过一般的方式是做不到的,那么此时就需要HDFS的扩展属性信息技术。

截图可能更为直观一些吧

2f7f46b6c44b9412e3e5a279e395ca63.png

详细解释请参考官网链接。

命令示例

#获取目录的所有扩展属性
hadoop fs -getfattr -d /test/xattr/abc


#获取指定user空间的扩展属性信息(除了user还有trusted/security/system/raw)
hadoop fs -getfattr -n user /test/xattr/abc


#对目录设置扩展属性信息
hadoop fs -setfattr -n user.作者张三 -v 这个目录是张三创建的哦 /test/xattr/

接下来的步骤就是要实现如何获取集群的目录扩展属性信息了。

8476c87dfcdcd565e20e18cea126375d.png

1、获取HDFS元数据信息

cc6f65247532a33d22d2d6a793fefe28.png

1、提取HDFS元数据信息

hdfs dfsadmin -fetchImage /tmp/fsimage/fsimage

2、以逗号分隔转换成可查看文件

hdfs oiv -i /tmp/fsimage/fsimage* -o /tmp/fsimage/hdfsfsimage.txt -p Delimited -delimiter ,

3、过滤出HDFS目录

cat /tmp/fsimage/hdfsfsimage.txt|awk -F "," '$10 ~ "^d" {print $1}' > /tmp/fsimage/hdfsdir.txt

6fd23f8bb79633715ddcb4508d15c253.png

2、 API方式获取HDFS目录扩展属性信息

API方式获取HDFS目录的Extended Attributes

7a311064395dcd5e7c747eb6f8ace7e1.png

代码示例

package xattrstool.htsc;


import org.apache.commons.cli.*;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.security.AnnotatedSecurityInfo;
import org.apache.hadoop.security.SecurityUtil;
import org.apache.hadoop.security.UserGroupInformation;


import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;


public class xattrstool {
    private static String HDFSDIRPATH;
    private static String KRB5FILE;
    private static String PRINCIPAL;
    private static String KEYPATH;
    private static String CONFPATH;


    public static void main(String[] args) throws IOException, InterruptedException {
        //解析传入参数
        Options options = new Options();
        options.addOption("hdfsdir", true, "存储HDFS目录文件(*)");
        options.addOption("krb5File", true, "krb5.conf配置文件绝对路径(*)");
        options.addOption("keytab", true, "keytab文件绝对路径(*)");
        options.addOption("principal", true, "keytab对应的主体名称(*)");
        options.addOption("confPath", true, "hdfs-site.xml与core-site.xml配置文件所在目录(*)");
        CommandLineParser parser = new DefaultParser();
        HelpFormatter formatter = new HelpFormatter();
        CommandLine commandLine = null;
        try {
            commandLine = parser.parse(options, args);
            HDFSDIRPATH = commandLine.getOptionValue("hdfsdir");
            KRB5FILE = commandLine.getOptionValue("krb5File");
            KEYPATH = commandLine.getOptionValue("keytab");
            PRINCIPAL = commandLine.getOptionValue("principal");
            CONFPATH = commandLine.getOptionValue("confPath");
        } catch (ParseException e) {
            formatter.printHelp(" ", options);
            System.exit(1);
        }


        if (args.length != 10) {
            formatter.printHelp(" ", options);
            System.exit(1);
        }


        Configuration conf = new Configuration();


        //kerberos验证步骤
        FileSystem fs = KerberosAuth(conf, KRB5FILE, KEYPATH, PRINCIPAL, CONFPATH);


        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        Date datestart = new Date();
        String start = simpleDateFormat.format(datestart);  //data -> String
        System.out.println("开始时间:" + start);
        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(HDFSDIRPATH), "UTF-8"));
        String line = null;
        Path path;
        Scanner sc = new Scanner(new FileReader(HDFSDIRPATH));
        while ((line = br.readLine()) != null) {  //按行读取字符串
            path = new Path(line);
            //判断目录是否有扩展信息
            if (fs.exists(path)) {
                Map<String, byte[]> xAttrs = fs.getXAttrs(path);
                if (!xAttrs.isEmpty()) {
                    Set<String> keySet = xAttrs.keySet();
                    for (String key : keySet) {
                        System.out.println("path=" + line + ",key=" + key + ",value=" + new String(xAttrs.get(key)));
                    }
                }
            }
        }
        fs.close();
        Date dateend = new Date();
        String end = simpleDateFormat.format(dateend);
        System.out.println("结束时间:" + end);
        System.out.println("统计花费时间:" + (dateend.getTime() - datestart.getTime()) / 1000 + "秒");
    }




    public static FileSystem KerberosAuth(Configuration conf, String krb5File, String keyPath, String user, String conf_path) {
        FileSystem fileSystem = null;
        String hdfs_path = conf_path + "hdfs-site.xml";
        String core_path = conf_path + "core-site.xml";
        SecurityUtil.setSecurityInfoProviders(new AnnotatedSecurityInfo());
        System.setProperty("java.security.krb5.conf", krb5File);
        System.setProperty("dfs.client.socket-timeout", "100");
        conf.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem");
        conf.set("fs.file.impl", "org.apache.hadoop.fs.LocalFileSystem");
        conf.addResource(new Path(hdfs_path));
        conf.addResource(new Path(core_path));
        conf.set("hadoop.security.authentication", "kerberos"); //配置认证方式
        conf.set("dfs.client.use.datanode.hostname", "true");
        conf.set("dfs.client.socket-timeout", "100");
        UserGroupInformation.setConfiguration(conf);
        try {
            UserGroupInformation.loginUserFromKeytab(user, keyPath);
            System.out.println("Kerberos认证成功,当前用户为:" + UserGroupInformation.getCurrentUser());
            fileSystem = FileSystem.get(conf);
        } catch (IOException e) {
            System.out.println("Kerberos 认证失败");
            e.printStackTrace();
        }
        return fileSystem;
    }
}

MAVEN依赖

<dependencies>
    <dependency>
        <groupId>commons-cli</groupId>
        <artifactId>commons-cli</artifactId>
        <version>1.4</version>
    </dependency>
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-client</artifactId>
        <version>3.0.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-common</artifactId>
        <version>3.0.0</version>
    </dependency>
</dependencies>

将代码进行编译打包上传到服务器中。

7f0b1feb4ed3dfb049f246fdf4904ec0.png

3、编写shell脚本

b096e33d778fc6c1ac92b717d52b8d2f.png

在此之前,需要准备好管理员票据keytab文件、拥有hdfs-site.xml与core-site.xml配置文件的目录,镜像文件存储目录

shell代码示例

#!/bin/bash


if [ $# != 7 ];then
        echo 'usage:'
        echo '  $1:执行jar的绝对路径'
        echo '  $2:krb5.conf绝对路径'
        echo '  $3:keytab文件路径'
        echo '  $4:keytab对应的主体名称'
        echo '  $5:hdfs-site.xml与core-site.xml配置文件所在目录'
        echo '  $6:存储HDFS目录信息的文件绝对路径'
        echo '  $7:镜像存储路径'
        exit 1
fi


execjar=$1
krb5File=$2
keytab=$3
principal=$4
confPath=$5
hdfsdirfile=$6
fsimagepath=$7




if [[ ! -d ${fsimagepath} ]]; then
 mkdir ${fsimagepath}
else
        rm -rf ${fsimagepath}/fsimage*
fi


#提取HDFS元数据信息
hdfs dfsadmin -fetchImage ${fsimagepath}/fsimage


#以逗号分隔转换成可查看文件
hdfs oiv -i ${fsimagepath}/fsimage* -o ${fsimagepath}/hdfsfsimage.txt -p Delimited -delimiter ,


#过滤出目录文件
cat ${fsimagepath}/hdfsfsimage.txt|awk -F "," '$10 ~ "^d" {print $1}' > ${hdfsdirfile}


java -cp ${execjar} xattrstool.htsc.xattrstool -krb5File ${krb5File} -keytab ${keytab} -principal ${principal} -confPath ${confPath} -hdfsdir ${hdfsdirfile}

执行脚本命令

sh getXattrs.sh \
/root/abc/xattrstool_jar/xattrstool.jar \
/etc/krb5.conf \
/root/hdfs.keytab \
hdfs/cm111@WMM.COM  \
/etc/hadoop/conf/ \
/tmp/fsimage/hdfsdir.txt \
/tmp/fsimage


#传参解释
$1:执行jar的绝对路径即上传压缩包解压后的路径
$2:krb5.conf配置文件的绝对路径"
$3:keytab文件的绝对路径(注意要有管理员权限一般为hdfs.keytab)"
$4:keytab对应的主体名称"
$5:hdfs-site.xml与core-site.xml配置文件所在绝对路径目录,注意路径末尾不能缺失/"
$6:存储HDFS目录信息文件的绝对路径"
$7:镜像存储的路径目录"

执行效果如下

52965a06150751b0b05f311f30eef0ed.png

744a6a3f9c6a698671738f1a5363a121.png

点个在看你最好看

de563b1f24842ab128caf840ad572600.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,您可以使用Hadoop的Java API来实现这个功能。具体实现步骤如下: 1. 首先,需要引入hadoop-client依赖,可以在pom.xml文件中添加以下代码: ```xml <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client</artifactId> <version>3.3.1</version> </dependency> ``` 2. 接着,可以使用以下代码来实现打印hdfs集群下一目录中的文件信息: ```java import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.FileStatus; import java.io.IOException; public class HdfsFileList { public static void main(String[] args) throws IOException { // 创建Configuration对象 Configuration conf = new Configuration(); // 设置HDFS文件系统的URI conf.set("fs.defaultFS", "hdfs://<hdfs_host>:<hdfs_port>"); // 创建FileSystem对象 FileSystem fs = FileSystem.get(conf); // 设置要遍历的目录 Path path = new Path("/path/to/dir"); // 判断目录是否存在 if (fs.exists(path)) { // 获取目录下的所有文件信息 FileStatus[] fileStatusArray = fs.listStatus(path); // 遍历文件信息并打印 for (FileStatus fileStatus : fileStatusArray) { String filePath = fileStatus.getPath().toString(); System.out.println(filePath); } } else { System.out.println("目录不存在!"); } // 关闭FileSystem对象 fs.close(); } } ``` 其中,`<hdfs_host>`和`<hdfs_port>`需要替换为实际的HDFS集群的IP地址和端口号,`/path/to/dir`需要替换为实际的要遍历的目录路径。代码中,使用`FileSystem.listStatus()`方法获取目录下的所有文件信息,然后遍历文件信息并打印出来。 希望这个代码可以帮助到您!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值