设计思路
- 实时读取日志:使用
tail -f
命令实时读取 prod.log
文件的新增内容。
- 日志解析:对每一行日志进行解析,提取进程ID和日志级别。
- 错误日志计数:维护一个进程ID与错误日志计数的映射关系,每出现一条错误日志,对应进程ID的计数加1。
- 定时检查:每隔1分钟检查一次每个进程的错误日志计数,若超过100条,则发送邮件通知管理员。
- 性能优化:使用数组存储进程ID和计数,避免频繁文件I/O操作,减少资源占用。
脚本代码
#!/bin/bash
# 初始化进程错误日志计数数组
declare -A error_count
# 存储进程ID的数组
pids=()
# 上一次检查时间
last_check_time=$(date +%s)
# 实时读取日志
tail -f prod.log | while read line; do
# 提取时间戳、进程ID、日志级别
timestamp=$(echo $line | awk '{print $1}')
pid=$(echo $line | awk '{print $2}')
log_level=$(echo $line | awk '{print $4}')
# 检查是否为错误日志
if [ "$log_level" = "ERROR" ]; then
if [ -z "${error_count[$pid]}" ]; then
error_count[$pid]=1
pids+=($pid)
else
error_count[$pid]=$((error_count[$pid]+1))
fi
fi
# 每隔1分钟检查一次
current_time=$(date +%s)
if [ $((current_time - last_check_time)) -ge 60 ]; then
for pid in "${pids[@]}"; do
if [ ${error_count[$pid]} -gt 100 ]; then
echo "进程 $pid 在1分钟内产生超过100条错误日志" | sendmail -v 管理员邮箱地址
fi
# 重置计数
error_count[$pid]=0
done
last_check_time=$current_time
fi
done
注意事项
- 替换邮箱地址:脚本中的
管理员邮箱地址
需要替换为实际的管理员邮箱。
- 权限问题:确保脚本运行的用户有执行
sendmail
命令的权限,并且 prod.log
文件可读取。
- 稳定性:在高负载环境下,
tail -f
和 sendmail
命令本身的性能和稳定性需要关注,必要时可以考虑使用更高效的日志读取和邮件发送方式。