Shell脚本循环重复执行问题求助:tail -F日志监听异常
解决Hive日志实时监听脚本循环重复执行的问题
我一眼就看出问题出在哪了——你的脚本每次匹配到select日志时,会全量扫描整个hive-server2.log文件,还取最后一行输出,这就导致只要有新的select日志进来,你就会重复处理之前已经处理过的历史记录,自然会出现循环重复执行的情况。
核心优化思路
放弃全量扫描日志文件的方式,改为流式逐行处理:实时跟踪当前日志流中的queryId,只关联当前select语句对应的s3路径,不碰历史日志内容。
修改后的脚本示例
# 初始化变量,用于跟踪当前的queryId和审计类型 current_query_id="" AuditTypeID="" tail -n 0 -F hive-server2.log | while read -r LINE; do # 匹配"Executing command(queryId="行,提取当前queryId if echo "$LINE" | grep -q "Executing command(queryId="; then # 用sed提取queryId(根据你的日志格式调整正则) current_query_id=$(echo "$LINE" | sed 's/.*queryId=\([^: ]*\):.*/\1/') # 判断是否是select语句,设置对应的AuditTypeID if echo "$LINE" | grep -qi "select "; then AuditTypeID=15 else # 非select语句重置审计类型 AuditTypeID="" fi # 匹配包含s3://的行,且当前有有效的select类型queryId elif [ -n "$current_query_id" ] && [ "$AuditTypeID" = "15" ] && echo "$LINE" | grep -q "s3://"; then # 提取s3路径(根据实际日志格式调整正则,这里取s3://到空格前的内容) s3_path=$(echo "$LINE" | grep -o "s3://[^ ]*") # 输出你需要的格式(这里是","+queryId,可按需调整) echo ",$current_query_id" # 处理完后重置变量,避免关联到后续不相关的日志 current_query_id="" AuditTypeID="" fi done
关键优化点说明
- 流式处理:只处理
tail -F实时输出的新增日志行,不再全量读取整个日志文件,彻底避免重复处理历史内容。 - 实时跟踪queryId:当捕获到包含queryId的执行命令行时,先记录当前的queryId,同时判断是否是select语句并设置审计类型。
- 关联对应s3路径:只有当当前存在有效的select类型queryId时,再关联后续出现的s3路径,处理完成后立即重置变量,防止重复匹配。
额外注意事项
- 请根据你的
hive-server2.log实际格式调整正则表达式,比如queryId的提取规则、s3路径的匹配规则,确保能精准捕获需要的内容。 - 使用
read -r来避免转义字符干扰,保留日志行的原始内容。 - 如果日志中select语句的大小写不固定,用
grep -qi来忽略大小写匹配,避免漏判。
内容的提问来源于stack exchange,提问作者Jeyamahesan
相关产品推荐
相关产品推荐

