如何提取文件名首个点前内容并合并同类型Zeek日志文件?
合并Security Onion中Zeek压缩日志的解决方案
问题场景
有大量Zeek生成的.gz压缩日志文件,文件名格式示例:
broker.17:22:58-17:45:10.log.gz broker.18:22:58-18:30:20.log.gz weird.17:22:58-17:45:10.log.gz weird.18:22:58-18:30:20.log.gz
日志按日期存于/nsm/zeek/logs/[date]/目录下,每小时一个压缩包,目标是将每种类型(如broker、weird)的日志合并为单个未压缩文件,最终导入Splunk。
原命令错误分析
原尝试提取文件名前缀的命令:
for f in *.gz ; do grep -oP '.*?(?=\.)' 'print {$f}' ; done
报错ERROR: grep: '.*?(?=\.)' no such file or directory,原因是命令逻辑错误:grep参数顺序颠倒,且print {$f}是错误写法,shell中提取字符串前缀用内置参数展开更高效。
正确实现步骤
1. 提取日志类型前缀的正确方法
在bash中,用${文件名%%.*}可直接截取第一个.之前的内容,示例:
f="broker.17:22:58-17:45:10.log.gz" echo ${f%%.*} # 输出 broker
2. 批量合并同类型日志(跨日期目录)
直接递归遍历所有日期目录,合并对应类型的压缩包并解压到目标文件,无需先合并压缩包再解压,一步完成:
完整脚本示例
# 日志根目录 ZEEK_LOG_ROOT="/nsm/zeek/logs" # 合并后的输出目录(需提前创建) OUTPUT_DIR="/home/user/zeek_combined_logs" mkdir -p $OUTPUT_DIR # 收集所有唯一的日志类型前缀 LOG_TYPES=$(find $ZEEK_LOG_ROOT -name "*.gz" | sed -E 's/.*\/([^.]+)\..*/\1/' | sort -u) # 遍历每个日志类型,合并并解压 for type in $LOG_TYPES; do echo "Processing $type logs..." # 找到所有该类型的压缩包,解压后追加到目标文件 find $ZEEK_LOG_ROOT -name "${type}*.gz" -exec gunzip -c {} \; >> "${OUTPUT_DIR}/${type}.log" done echo "All logs merged successfully to $OUTPUT_DIR"
3. 脚本说明
find $ZEEK_LOG_ROOT -name "*.gz":递归查找所有Zeek压缩日志sed -E 's/.*\/([^.]+)\..*/\1/':提取文件名中第一个.前的类型前缀sort -u:去重得到唯一的日志类型列表find ... -exec gunzip -c {} \; >> ...:将每个压缩包内容解压后追加到目标文件,省去中间合并压缩包的步骤
后续导入Splunk
合并后的${OUTPUT_DIR}/${type}.log文件可直接通过Splunk的文件监控、批量导入等方式添加到索引中。
内容的提问来源于stack exchange,提问作者orafreaz
相关产品推荐
相关产品推荐

