Shell脚本未按预期从error.log提取指定时段关键日志求助
问题分析与修复
你的脚本没生效的核心原因是直接用字符串比较日期时间容易因为格式细节(比如空格数量)或locale排序规则出错,导致日志行的日期和你生成的d1/d2无法正确匹配。
修复后的脚本
#!/bin/ksh # 计算时间戳:50分钟前和当前时间的epoch秒数 d1_ts=$(date --date="-50 min" +%s) d2_ts=$(date +%s) # 读取日志文件,逐行处理(IFS=和-r避免丢失空格/反斜杠) while IFS= read -r line; do # 提取日志行的日期时间部分(前3个字段:Apr 7 13:05:57) line_date=$(echo "$line" | cut -d' ' -f1-3) # 将提取的日期转换为epoch时间戳 line_ts=$(date --date="$line_date" +%s) # 用数值比较判断日志是否在过去50分钟内 if (( line_ts > d1_ts && line_ts <= d2_ts )); then # 匹配包含critical/Critical的行并写入目标文件 [[ "$line" =~ [Cc]ritical ]] && echo "$line" >> /mnt/dinesh/ksh-scripts/draft/text.txt fi done < /var/log/error.log
为什么原来的脚本失效?
- 日期格式的空格差异:你用
date "+%b %_d %H:%M"生成的日期,当日期是个位数时会是Apr 7(两个空格),但日志里的日期是Apr 7(一个空格)。字符串比较时,这种空格数量的差异会导致$line > $d1的判断不符合预期(比如在某些locale下,空格的排序优先级高于数字,会让Apr 7...被认为比Apr 7...小)。 - 字符串比较的不可靠性:直接用字符串比较时间,会受到字符顺序、locale排序规则的影响,远不如数值型的时间戳比较准确。
额外优化建议
如果日志量很大,建议用awk一次性处理,效率更高(需要GNU awk支持):
#!/usr/bin/awk -f BEGIN { # 计算时间戳:当前时间减去50分钟 d1_ts = systime() - 50*60 d2_ts = systime() } { # 提取前3个字段并转换为awk可识别的日期格式 line_date = $1 " " $2 " " $3 line_ts = mktime(gensub(/([A-Za-z]+) ([0-9]+) ([0-9]+):([0-9]+):([0-9]+)/, "\\3 \\1 \\2 \\4 \\5 0", 1, line_date)) if (line_ts > d1_ts && line_ts <= d2_ts && tolower($0) ~ /critical/) { print > "/mnt/dinesh/ksh-scripts/draft/text.txt" } }
内容的提问来源于stack exchange,提问作者Dineshkumar Ravisekar
相关产品推荐
相关产品推荐

