如何编写Shell脚本监控日志?

话题来源: Forge服务端日志分析实战

说到日志监控,我不得不感叹Shell脚本真是个好东西!记得刚开始管理服务器时,每天手动翻日志简直让人抓狂。后来学会用Shell脚本自动化监控,工作效率直接翻倍。今天就来聊聊如何编写实用的日志监控脚本,这些可都是我在实战中总结出来的经验。

基础监控脚本入门

先来个最简单的例子吧。有时候我们只需要知道日志里是否出现了错误信息,这时候一个基础的grep命令就能搞定。不过直接使用grep有个问题——它不会持续监控新产生的日志。所以我会用tail命令配合grep,这样就能实时捕捉到新出现的错误了。

#!/bin/bash
# 实时监控错误日志
tail -f /var/log/app/latest.log | grep --line-buffered -E "(ERROR|Exception|Crash)"

看到那个–line-buffered参数了吗?这可是个实用的小技巧,能确保日志行被立即输出,不会因为缓冲而延迟显示。说实话,我当初就是没加这个参数,调试时白白浪费了好多时间!

进阶监控策略设计

基础监控虽然简单,但在生产环境中往往不够用。我们需要更智能的监控方案,比如定时统计错误数量、设置阈值告警等等。下面这个脚本是我在实际项目中使用的,效果相当不错。

#!/bin/bash
LOG_FILE="/var/log/app/latest.log"
ALERT_THRESHOLD=10

while true; do
    ERROR_COUNT=$(grep -c "ERROR" $LOG_FILE)
    WARNING_COUNT=$(grep -c "WARN" $LOG_FILE)
    
    if [ $ERROR_COUNT -gt $ALERT_THRESHOLD ]; then
        echo "[$(date)] 警报:发现 $ERROR_COUNT 个错误!" | mail -s "系统异常警报" admin@example.com
    fi
    
    echo "[$(date)] 统计:错误 $ERROR_COUNT 个,警告 $WARNING_COUNT 个"
    sleep 300
done

这个脚本每5分钟检查一次日志,当错误数量超过阈值时就会发送邮件告警。不过要注意,这种简单的计数方式在某些场景下可能不够准确,比如日志轮转时计数会重置。这时候就需要更复杂的逻辑来处理了。

实战中的坑与解决方案

写监控脚本最怕什么?我觉得是误报!记得有次脚本疯狂告警,结果发现是因为日志格式变了,grep匹配到了不该匹配的内容。从那以后,我都会在脚本里加入更精确的匹配模式。

#!/bin/bash
# 更精确的错误匹配
ERROR_PATTERN="^[.*]s+ERRORs+"
WARN_PATTERN="^[.*]s+WARNs+"

monitor_logs() {
    tail -f $1 | while read line; do
        if [[ $line =~ $ERROR_PATTERN ]]; then
            echo "[紧急] $line" >> /var/log/monitor/alert.log
            send_alert "$line"
        elif [[ $line =~ $WARN_PATTERN ]]; then
            echo "[警告] $line" >> /var/log/monitor/warn.log
        fi
    done
}

另外,日志文件大小也是个需要注意的问题。有次监控脚本突然失效,查了半天才发现是日志文件太大,tail命令跟不上了。现在我都会定期清理旧日志,或者使用logrotate来管理日志文件。

说实话,写日志监控脚本就像是在和系统玩捉迷藏。你永远不知道下一个问题会出现在哪里,但正是这种不确定性让这个工作充满挑战和乐趣。希望这些经验能帮你少走些弯路!

评论