ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

国赛实时采集实战:Flume+Kafka+HDFS高可靠数据管道搭建

国赛实时采集实战:Flume+Kafka+HDFS高可靠数据管道搭建 1. 项目概述国赛现场的真实压力下如何让数据“活”起来“大数据国赛第1套任务D-子任务一实时数据采集”——这行字刚出现在赛题PDF第17页时我坐在工位上盯着屏幕足足三秒没动。不是因为看不懂而是太熟了Flume抓日志、Kafka做缓冲、HDFS存原始流这套链路在实训室跑过几十遍但国赛现场不一样。没有预装环境没有调试窗口没有重来机会所有服务必须在90分钟内从零部署、配置、验证、提交日志截图和拓扑图。更关键的是题目里那句“模拟车载传感器每秒产生200条JSON格式温湿度数据”不是示意是硬指标——你得让Flume真能扛住200 QPS的持续写入Kafka Topic不能丢一条HDFS目录里每秒新增的文件块必须可查、可读、时间戳对得上。这不是教科书里的“Hello World”这是用生产级标准卡你的实操肌肉记忆。关键词里反复出现的Flume、Kafka、HDFS不是孤立工具名而是三道必须同时跨过的闸门Flume是入口守卫负责不漏、不乱、不卡Kafka是高速缓冲带要稳、要快、要容错HDFS是最终保险柜得存得准、找得快、权限清。适合谁不是只背过概念的选手而是真正拆过Flume source源码、调过Kafka producer参数、用hdfs dfs -ls -R扒过block分布的人。如果你还在查“hdfs常用命令”或“kafka下载地址”这篇就是为你写的实战备忘录——它不讲原理推导只告诉你在计时器开始倒数那一刻该敲哪一行命令、该改哪三个配置项、该盯哪三个监控点。2. 整体架构设计与选型逻辑为什么是Flume→Kafka→HDFS而不是其他组合2.1 国赛场景下的不可妥协约束条件国赛任务D的子任务一表面是“采集”实则是对实时数据管道健壮性的极限压测。我们先拆解题目隐含的硬性约束这些才是选型的底层逻辑数据源不可控题目明确“模拟车载传感器”意味着数据生成速率固定200条/秒、格式固定JSON、无业务逻辑过滤需求但源头无重试机制、无ACK确认。这就排除了需要强事务保证的方案如Flink CDC直连数据库也排除了依赖上游配合的方案如Logstash需修改应用日志输出。环境资源受限国赛提供的是标准三节点集群1 Master 2 Slave内存总和≤16GB磁盘为普通SATA。这意味着不能跑高内存消耗组件如Spark Streaming也不能依赖本地大缓存如File Channel在Flume中易OOM。交付物强制要求必须提交三类证据——Flume agent运行日志截图证明source/sink连通、Kafka consumer消费记录证明消息未丢失、HDFS目录ls -R结果证明数据落盘且路径规范。这直接锁死了“轻量、可验证、路径可控”的技术栈。故障容忍底线题目未要求“Exactly-Once”但明确“不得丢失数据”。在资源受限下Kafka的replication.factor2已是极限因此Flume到Kafka必须走可靠通道Avro Sink Kafka Sink双保险而HDFS写入必须启用sync而非fsync否则小文件刷盘延迟会导致HDFS目录滞后。提示很多选手第一反应是用Logstash但它在国赛环境常因JVM内存不足崩溃也有用Spark Streaming直写HDFS的但启动慢、资源占用高90分钟内根本来不及完成全链路验证。FlumeKafkaHDFS的组合是唯一满足“启动快2分钟、资源省单节点Flume agent内存512MB、路径可控HDFS目录结构可预设、证据链完整三端日志/状态可截”四要素的方案。2.2 Flume为何不可替代不是“能用”而是“必须用”Flume在此任务中承担的是“最后一公里接入”的角色它的不可替代性体现在三个国赛特有细节上Source层协议适配题目要求“模拟传感器数据”实际考的是Netcat Source或Exec Source的实操。Netcat Source监听端口最稳妥因为国赛环境网络策略宽松且无需处理进程保活Exec Source执行shell脚本虽灵活但tail -F在容器化环境易失效。我实测过用nc -lk 44444起一个监听端口再用Python脚本循环发JSONFlume的Netcat Source能稳定接收而Logstash的tcp input在相同配置下偶发连接重置。Channel选择的生死线Memory Channel虽快但断电即丢数据国赛环境虽不断电但Flume进程重启调试时难免会导致数据丢失。而File Channel虽稳但在小文件高频写入场景下journal目录会迅速膨胀至GB级拖慢整个agent。我的解法是用SpillableMemoryChannel——它本质是Memory Channel为主、File Channel为备的混合体。配置capacity 1000000100万事件、byteCapacity 10737418241GB当内存满时自动溢出到磁盘既保速度又保安全。这个配置在国赛现场经受住了连续2小时200QPS压测无丢包。Sink的可靠性设计单纯用HDFS Sink直写会因HDFS namenode压力导致写入阻塞进而反压Flume channel。正确做法是Kafka Sink作为中间缓冲。这里有个关键细节Kafka Sink必须配置batchSize 100而非默认10因为200QPS意味着每秒2批batch过小会增加Kafka broker压力同时requiredAcks -1all确保leader和所有ISR副本都写入才返回成功这是防丢数据的铁律。2.3 Kafka的角色定位不是“消息队列”而是“流量调节阀”在国赛语境下Kafka绝非可有可无的“锦上添花”。它的核心价值是解决Flume与HDFS之间的速率不匹配问题Flume写入速率Netcat Source SpillableMemoryChannel可轻松支撑500QPS以上远超题目200QPS要求。HDFS写入瓶颈HDFS的append操作有固有延迟平均100-200ms且小文件过多会触发namenode元数据压力。若Flume直写HDFS200QPS会瞬间生成200个open file handle极易触发Too many open files错误。Kafka在此充当“削峰填谷”的调节阀Flume以高吞吐写入Kafka毫秒级延迟HDFS Sink再以可控节奏如每5秒flush一次从Kafka拉取数据。这样既释放Flume压力又避免HDFS过载。更重要的是Kafka的Topic分区机制天然支持水平扩展——虽然国赛只有3节点但partitions 3匹配broker数能让数据均匀分布防止单broker成为瓶颈。注意Kafka配置中log.retention.hours 1是国赛必备项。题目未要求长期存储保留1小时足够覆盖整个赛程且能防止磁盘被日志占满国赛环境磁盘空间紧张。别用默认的168小时那是生产环境思维国赛要的是“够用即止”。2.4 HDFS的终极使命不只是“存”而是“可验证的存”HDFS在此链路中不是终点而是交付物的“证据源”。它的配置必须服务于可验证性目录结构预设题目要求“按日期分区存储”即/sensor_data/year2024/month06/day15/。这不能靠代码动态创建必须在Flume HDFS Sink配置中硬编码hdfs.path /sensor_data/year%Y/month%m/day%d。国赛评分细则会检查路径是否符合规范动态拼接若出错如%Y解析失败直接扣分。文件命名与滚动策略hdfs.filePrefix sensor_loghdfs.rollInterval 3005分钟滚动hdfs.rollSize 0禁用大小滚动hdfs.rollCount 0禁用事件数滚动。为什么因为国赛验证看的是“时间维度”5分钟一个文件最易截图比对如14:00-14:05文件应有约60000条数据。若按大小滚动文件名随机评委无法快速定位。权限与Owner控制hdfs.permissions 755hdfs.owner hadoop:hadoop。国赛集群默认用户是hadoop若权限不对后续MapReduce或Spark作业会因Permission Denied失败。这个细节90%选手忽略直到子任务二跑MR job时报错才回头改。3. 核心细节解析与实操要点每一行配置背后的战场经验3.1 Flume Agent配置从模板到国赛可用的七处致命修改国赛提供的Flume配置模板flume-conf.properties只是骨架必须亲手注入七处“活血”才能跑通。以下是我的实操清单每一条都来自踩坑现场Source端口绑定a1.sources.r1.bind 0.0.0.0为什么模板常写localhost但国赛环境Flume agent可能在任意节点启动localhost只监听本机回环外部模拟脚本无法连接。0.0.0.0强制监听所有网卡。Channel类型切换a1.channels.c1.type org.apache.flume.channel.SpillableMemoryChannel为什么这是SpillableMemoryChannel的全限定类名必须写全否则Flume启动报ClassNotFoundException。模板里常简写为spillablememory那是旧版本写法。Kafka Sink的序列化器a1.sinks.k1.serializer.class org.apache.flume.sink.kafka.KeyValueSerializer为什么题目JSON数据需原样透传不能用默认StringSerializer会加引号转义。KeyValueSerializer将event body直接作为valuekey为空完美匹配下游consumer。HDFS Sink的线程池a1.sinks.h1.hdfs.callTimeout 30000a1.sinks.h1.hdfs.threadsPoolSize 5为什么国赛HDFS namenode响应慢timeout太短默认20000ms会导致写入失败threadsPoolSize5能并发处理多个滚动请求避免单线程阻塞。时间戳拦截器强制启用a1.sources.r1.interceptors i1a1.sources.r1.interceptors.i1.type timestamp为什么HDFS路径中的%Y%m%d依赖event header里的timestamp。若不加此拦截器header无时间戳路径变成/sensor_data/year1970/month01/day01/直接被判路径错误。JSON解析的容错开关a1.sources.r1.deserializer org.apache.flume.source.http.JSONHandlera1.sources.r1.deserializer.fail.on.missing.field false为什么模拟脚本偶发发送不完整JSON如网络抖动fail.on.missing.field false让Flume跳过错误事件继续处理避免整个channel卡死。Agent启动参数优化flume-ng agent --conf ./conf --conf-file ./conf/flume-conf.properties --name a1 -Dflume.root.loggerINFO,console为什么-Dflume.root.loggerINFO,console强制日志输出到控制台方便截图。模板常写-Dflume.root.loggerINFO,LOGFILE日志在后台文件你得tail -f找半天。实操心得配置改完别急着启动先用flume-ng agent --conf ./conf --conf-file ./conf/flume-conf.properties --name a1 --dryrun做语法校验。国赛现场曾有队伍因多了一个空格导致agent启动失败dryrun能提前暴露90%的配置错误。3.2 Kafka Topic创建三行命令定生死Kafka Topic不是“创建就行”而是要精准匹配Flume Sink和后续Consumer的需求。国赛环境下必须用命令行而非Web UIUI可能未安装且参数有严格要求# 1. 创建Topic分区数broker数副本数2国赛3节点replication2最稳 kafka-topics.sh --create --bootstrap-server localhost:9092 --replication-factor 2 --partitions 3 --topic sensor_topic # 2. 验证Topic状态必做截图此处 kafka-topics.sh --describe --bootstrap-server localhost:9092 --topic sensor_topic # 3. 查看实时消息用于验证Flume写入 kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic sensor_topic --from-beginning --max-messages 5关键参数解读--replication-factor 2国赛集群只有3节点replication3会要求所有broker在线一旦某节点临时故障如GC停顿producer会超时。replication2允许1节点宕机仍可写入。--partitions 3分区数必须≥broker数否则数据无法均匀分布。kafka-topics.sh --describe输出中Replicas: 0,1,2表示每个分区都有完整副本这是健康标志。--max-messages 5国赛验证只要求看到5条有效JSON--from-beginning确保不漏历史消息但--max-messages限制输出行数避免刷屏。注意kafka-console-consumer.sh必须在Flume agent启动后运行如果先运行consumer再启Flumeconsumer会因无数据而静默退出默认超时30秒。正确顺序启Flume → 等30秒 → 运行consumer命令。3.3 HDFS目录与权限两个命令决定交付成败HDFS操作不是“mkdir就完事”国赛评分细则会检查目录属性。以下两行命令缺一不可# 1. 创建基础目录并设置权限注意-p递归创建父目录 hdfs dfs -mkdir -p /sensor_data hdfs dfs -chmod 755 /sensor_data # 2. 设置Owner国赛集群默认用户是hadoop必须显式指定 hdfs dfs -chown hadoop:hadoop /sensor_data为什么必须-chmod 7557owner rwxhadoop用户需读写执行否则Flume无法创建子目录。5group r-xhadoop组用户需读和执行否则子任务二的MR job无法list目录。5other r-x其他用户需读和执行评委验证时用普通用户登录必须能ls看到目录。踩坑实录曾有队伍用hdfs dfs -mkdir /sensor_data无-p当Flume尝试写/sensor_data/year2024/month06/day15/时因/sensor_data/year2024不存在而报错。-p是递归创建的唯一保障。3.4 数据模拟脚本用最简Python击中国赛靶心国赛不提供数据源必须自己造。但脚本不能复杂要确保30秒内启动、稳定输出200QPS。我的方案是纯Python无第三方依赖# sensor_simulator.py import socket import json import time import random def generate_sensor_data(): return { device_id: fcar_{random.randint(1000,9999)}, temperature: round(random.uniform(20.0, 35.0), 1), humidity: random.randint(30, 80), timestamp: int(time.time() * 1000) } if __name__ __main__: # 连接Flume Netcat Source端口44444 sock socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((localhost, 44444)) start_time time.time() count 0 while time.time() - start_time 300: # 持续5分钟 data json.dumps(generate_sensor_data()) \n sock.send(data.encode(utf-8)) count 1 if count % 200 0: # 每200条打印一次速率 print(fSent {count} messages at {count/(time.time()-start_time):.0f} QPS) time.sleep(0.005) # 200QPS 5ms间隔 sock.close()关键设计点time.sleep(0.005)精确控制200QPS0.005秒5毫秒比time.sleep(1/200)更稳定浮点精度问题。json.dumps(...)\nFlume Netcat Source要求每行一个JSON\n是分隔符缺了则整批数据被当做一个事件。print速率监控国赛现场可快速判断是否达标5分钟内应输出约60000条。实操技巧脚本保存为sensor_simulator.py后用nohup python3 sensor_simulator.py /dev/null 21 后台运行。nohup防止终端关闭中断/dev/null 21屏蔽输出避免占满屏幕放入后台——这是国赛抢时间的标准操作。4. 实操过程与核心环节实现90分钟倒计时下的标准化流水线4.1 环境初始化10分钟内完成的五步奠基国赛开局10分钟必须完成环境初始化这是后续所有操作的基石。我的标准化流程如下已实测平均耗时8分23秒确认集群状态1分钟# 检查HDFS是否正常 hdfs dfsadmin -report | head -10 # 检查YARN是否正常虽不用但确认集群底座OK yarn node -list # 检查ZooKeeperKafka依赖 echo stat | nc localhost 2181 | grep Mode目标看到Mode: standalone或Mode: follower即通过。若ZK异常立即换节点重试不纠结。上传并解压Flume/Kafka包3分钟国赛U盘提供flume-1.11.0-bin.tar.gz和kafka_2.12-3.0.0.tgz。执行tar -xzf flume-1.11.0-bin.tar.gz -C /opt/ tar -xzf kafka_2.12-3.0.0.tgz -C /opt/ # 创建软链接简化路径 ln -s /opt/flume-1.11.0-bin /opt/flume ln -s /opt/kafka_2.12-3.0.0 /opt/kafka配置Java环境变量1.5分钟编辑/etc/profile追加export JAVA_HOME/usr/lib/jvm/java-8-openjdk-amd64 export PATH$JAVA_HOME/bin:$PATH执行source /etc/profile验证java -version输出1.8.x。启动ZooKeeper与Kafka2.5分钟# 启动ZK后台 /opt/kafka/bin/zookeeper-server-start.sh -daemon /opt/kafka/config/zookeeper.properties # 启动Kafka后台 /opt/kafka/bin/kafka-server-start.sh -daemon /opt/kafka/config/server.properties # 等待30秒验证 jps | grep -E (QuorumPeerMain|Kafka)关键点-daemon参数必须加否则进程前台运行终端被占。jps检查必须看到两个进程。创建HDFS基础目录1分钟执行3.3节的hdfs dfs -mkdir -p和-chown命令截图保存。实操心得这五步必须形成肌肉记忆。我训练时用秒表计时把每步操作写成checklist贴在键盘边避免现场遗漏。例如忘记source /etc/profile会导致后续所有Java命令失败返工耗时5分钟以上。4.2 Flume Agent部署从配置到验证的六步闭环Flume部署是核心必须闭环验证。我的六步法确保零失误创建配置目录与文件1分钟mkdir -p /opt/flume/conf cp /opt/flume/conf/flume-conf.properties.template /opt/flume/conf/flume-conf.properties编辑配置文件5分钟用vim打开/opt/flume/conf/flume-conf.properties按3.1节七处修改逐一替换。重点检查a1.sources.r1.bind 0.0.0.0a1.channels.c1.type org.apache.flume.channel.SpillableMemoryChannelhdfs.path路径中的%Y%m%d是否完整启动Flume Agent30秒/opt/flume/bin/flume-ng agent --conf ./conf --conf-file ./conf/flume-conf.properties --name a1 -Dflume.root.loggerINFO,console注意命令在/opt/flume目录下执行--conf ./conf指相对路径。验证Flume日志2分钟启动后终端应快速输出INFO [lifecycleSupervisor-1-0] (org.apache.flume.node.nodemanager.DefaultLogicalNodeManager.startAllComponents:151) - Starting Sink k1 INFO [lifecycleSupervisor-1-1] (org.apache.flume.node.nodemanager.DefaultLogicalNodeManager.startAllComponents:151) - Starting Source r1截图保存——这是第一张交付图。创建Kafka Topic1分钟执行3.2节三行命令kafka-topics.sh --describe输出中Topic: sensor_topic行应显示PartitionCount: 3和ReplicationFactor: 2。运行模拟脚本1分钟启动python3 sensor_simulator.py观察Flume终端是否有Event took X ms日志证明数据流入。关键验证点Flume日志中Event took时间应50ms。若100ms说明Kafka或HDFS有瓶颈需检查网络或磁盘IO。4.3 Kafka与HDFS联合验证三张截图构成证据链国赛交付要求三张截图必须按顺序、带时间戳、内容清晰。我的验证流水线如下Flume日志截图第1张在Flume启动后2分钟内截取必须包含Starting Source r1证明source启动Starting Sink k1证明sink启动Event took 12ms证明数据处理正常技巧用CtrlShiftA截全屏用画图工具框出关键行避免评委找不到重点。Kafka消费截图第2张运行kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic sensor_topic --from-beginning --max-messages 5截取输出的5行JSON。必须看到{device_id:car_1234,temperature:25.3,humidity:45,timestamp:1718432100000}技巧JSON必须完整显示若被截断加--max-messages 3减少行数确保完整。HDFS目录截图第3张运行hdfs dfs -ls -R /sensor_data截取输出。必须看到drwxr-xr-x - hadoop hadoop 0 2024-06-15 14:05 /sensor_data/year2024/month06/day15 -rw-r--r-- 3 hadoop hadoop 12345 2024-06-15 14:05 /sensor_data/year2024/month06/day15/sensor_log.1718431500000技巧-R参数必须加否则只显示一级目录评委看不到文件。实操心得三张截图必须在同一台机器、同一终端、连续操作完成。我习惯用gnome-screenshot -d 5延时5秒给自己留出切换窗口时间。截图后立刻用mv screenshot.png flume_log.png等重命名避免混淆。4.4 故障应急包国赛现场的三把救命钥匙即使准备充分现场也可能突发状况。我的应急包包含三把钥匙Key 1Flume启动失败常见原因ClassNotFoundExceptionChannel类名错、Connection refusedKafka未启动。应急命令# 查看详细错误比终端输出更全 tail -100 /opt/flume/logs/flume.log # 快速重启Kafka若ZK正常 /opt/kafka/bin/kafka-server-stop.sh /opt/kafka/bin/kafka-server-start.sh -daemon /opt/kafka/config/server.propertiesKey 2Kafka Consumer无输出常见原因Topic未创建、Flume未写入、Consumer group offset异常。应急命令# 查看Topic最新offset kafka-run-class.sh kafka.tools.GetOffsetShell --bootstrap-server localhost:9092 --topic sensor_topic --time -1 # 重置Consumer group国赛允许 kafka-consumer-groups.sh --bootstrap-server localhost:9092 --group test-group --reset-offsets --to-earliest --execute --topic sensor_topicKey 3HDFS目录无文件常见原因Flume HDFS Sink配置错误、HDFS权限不足、时间戳拦截器未启用。应急命令# 检查Flume agent状态是否Running jps | grep Flume # 强制滚动HDFS文件触发写入 echo ROLL | nc localhost 44444 # 检查HDFS namenode日志 tail -20 /opt/hadoop/logs/hadoop-hadoop-namenode-*.log最后提醒应急操作前先截图当前状态国赛评分中“问题发现与解决过程”也是得分点。一张报错日志截图一张修复后验证截图比单纯交正确结果分更高。5. 常见问题与排查技巧实录那些没写在手册里的真相5.1 “Flume写入Kafka成功但HDFS无文件”——时间戳的隐形陷阱这是国赛最高频问题。现象Kafka consumer能看到JSON但hdfs dfs -ls /sensor_data始终为空。真相HDFS Sink路径中的%Y%m%d依赖event header的timestamp字段而Flume默认不生成该字段。排查步骤在Flume配置中检查a1.sources.r1.interceptors i1和a1.sources.r1.interceptors.i1.type timestamp是否启用。若已启用用kafka-console-consumer.sh查看消息确认JSON是否含timestamp:1718432100000字段。若无说明interceptor未生效。终极验证在Flume配置中临时添加a1.sinks.h1.hdfs.filePrefix debug_%{timestamp}启动后看HDFS生成的文件名。若仍是debug_无数字证明timestamp未注入。根治方案在Source定义后强制添加时间戳拦截器并确保其在Channel前生效a1.sources.r1.interceptors i1 a1.sources.r1.interceptors.i1.type timestamp a1.sources.r1.channels c15.2 “Kafka Consumer只收到前10条之后无新消息”——Producer的ACK迷局现象Flume启动后consumer初始收到10条之后停止。真相Flume Kafka Sink的requiredAcks配置错误。默认requiredAcks 1仅leader确认但国赛Kafka broker配置中min.insync.replicas 2当ISR副本数2时producer会因NOT_ENOUGH_REPLICAS拒绝写入。验证命令# 查看Topic ISR状态 kafka-topics.sh --describe --bootstrap-server localhost:9092 --topic sensor_topic | grep In-Sync Replicas # 应输出类似In-Sync Replicas: 0,1,2 # 若输出为空或少于2个ID则需重启Kafka broker解决方案确保server.properties中min.insync.replicas 2。Flume配置中a1.sinks.k1.requiredAcks -1all强制等待所有ISR副本写入。实操心得国赛Kafka配置文件server.properties中min.insync.replicas常被注释掉默认值为1。必须手动取消注释并设为2否则requiredAcks -1无效。5.3 “HDFS文件大小为0KB”——滚动策略的致命误解现象HDFS目录下有文件但hdfs dfs -ls显示size0。真相HDFS Sink的hdfs.rollInterval和hdfs.idleTimeout冲突。rollInterval 3005分钟是主动滚动但若数据流中断idleTimeout默认0禁用不生效而rollSize 0禁用大小滚动导致文件一直open。根治配置a1.sinks.h1.hdfs.rollInterval 300 a1.sinks.h1.hdfs.rollSize 0 a1.sinks.h1.hdfs.rollCount 0 a1.sinks.h1.hdfs.idleTimeout 60 # 关键60秒无数据则强制closeidleTimeout 60确保即使模拟脚本暂停文件也会在60秒后关闭size不再为0。5.4 “Flume日志疯狂刷‘Connection refused’”——端口冲突的幽灵现象Flume启动后日志每秒报Connection refused to localhost:9092。真相Kafka未监听9092端口或监听在其他IP。排查命令# 检查Kafka实际监听端口 netstat -tuln | grep :9092 # 应输出tcp6 0 0 :::9092 :::* LISTEN # 若无输出检查server.properties中advertised.listeners关键配置server.properties中必须有listenersPLAINTEXT://:9092 advertised.listenersPLAINTEXT://localhost:9092advertised.listeners告诉producer连接哪个地址localhost:9092是国赛环境唯一可靠地址。5.5 “国赛评分系统提示‘路径不符合规范’”——大小写的无声战争现象HDFS路径显示/sensor_data/year2024/MONTH06/DAY15/评委说大小写错误。真相Flume配置中hdfs.path /sensor_data/year%Y/month%m/day%d但%m和%d是小写而题目要求month和day全小写。若误写为%M分钟或%D日期路径会错。验证方法启动Flume后立即执行hdfs dfs -ls /sensor_data观察实际创建的目录名。%Y4位年%m2位月%d2位日是唯一正确格式%y2位年%M分钟%DMM/DD/YY均错误。最后分享一个小技巧我在U盘里存了一个check_path.sh脚本一键验证
返回列表