用纯 Bash 脚本打造轻量级服务器日志实时监控与告警体系

2026-09-30 09:37 技术文章 25 阅读 分享


在服务器运维中,当生产环境发生 500 崩溃或数据库连接失败时,能否第一时间收到告警至关重要。市面上的监控方案往往需要安装 Python、Prometheus 或复杂的 Agent。

本文将分享一套零第三方依赖、完全基于 Linux 原生工具(Bash + Cron + Curl)的极简日志监控脚本。它采用"断点续读"机制,只抓取新增日志中的高危错误,并通过 Telegram 实时推送到手机。

💡 为什么选择 Telegram? 本文以 Telegram Bot 为例,主要是因为其 API 申请极为简单(秒级开通、无需审核)。当然,这套脚本具备极高的通用性,如果你习惯使用企业微信、钉钉、飞书或 Server酱,只需将底部的 curl 推送部分稍作替换即可无缝切换。

一、30 秒快速获取 Telegram 告警通道

在部署脚本前,需要先拿到两个核心凭证:

  1. 申请 Bot Token:

    • 在 Telegram 搜索并打开官方机器人 @BotFather。

    • 发送指令 /newbot,按提示输入昵称和用户名(必须以 bot 结尾),即可获得 BOT_TOKEN。

  2. 获取你的 Chat ID:

    • 搜索并打开 @userinfobot,发送任意消息即可获得一串数字 CHAT_ID。

  3. ⚠️ 极其关键的一步(必须发送消息):

    • Telegram 具有严格的隐私保护:如果用户从未与 Bot 发起过对话,Bot 是无法主动向你推送消息的。

    • 必须在 Telegram 中主动搜索你刚才创建的机器人,点击底部的 "Start" 按钮,或者随便发一句话。否则脚本推送时会报 chat not found 错误。

二、核心核心:log_watcher.sh 脚本源码

在服务器上新建一个目录(例如 /opt/monitor/),将以下代码保存为 log_watcher.sh。

该脚本会自动在同级目录下生成并管理偏移量缓存文件,无需手动创建任何多余文件:

#!/bin/bash

# ================= 配置区域 =================
# 获取当前脚本所在的目录,用于自适应存放偏移量文件
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# 1. 动态匹配当日日志文件路径(以你的项目或 Web 服务器日志命名规则为准)
LOG_FILE="/path/to/your/project/writable/logs/log-$(date +%Y-%m-%d).log"

# 2. 记录上次读取位置的偏移量文件(自动在同级目录下生成)
OFFSET_FILE="$DIR/last_position.txt"

# 3. Telegram Bot 配置
BOT_TOKEN="你的Telegram_Bot_Token"
CHAT_ID="你的Chat_ID"
# ============================================

# 1. 如果当日日志文件不存在,直接静默退出
[ ! -f "$LOG_FILE" ] && exit 0

# 2. 获取当前日志文件的字节大小 (兼容 Linux 的 stat 命令)
current_size=$(stat -c%s "$LOG_FILE" 2>/dev/null)
[ -z "$current_size" ] && exit 0

# 3. 读取上一次记录的偏移量
last_offset=0
[ -f "$OFFSET_FILE" ] && last_offset=$(cat "$OFFSET_FILE")

# 4. 如果发生日志轮转或被清空(文件变小了),重置偏移量
if [ "$current_size" -lt "$last_offset" ]; then
    last_offset=0
fi

# 5. 如果大小没变,说明没有新内容,直接退出
if [ "$current_size" -eq "$last_offset" ]; then
    exit 0
fi

# 6. 从上次断点之后开始读取新增的内容 (tail -c 从 1 开始计数,所以偏移量 + 1)
start_byte=$((last_offset + 1))
new_content=$(tail -c +$start_byte "$LOG_FILE")

# 7. 立即更新偏移量文件,记录当前位置
echo "$current_size" > "$OFFSET_FILE"

# 8. 过滤新增内容中是否包含严重错误关键字 (兼容应用级及 Web 服务器级错误)
errors=$(echo "$new_content" | grep -E -i '\b(CRITICAL|ERROR|FATAL|CRIT|ALERT|EMERG)\b')

# 9. 如果发现了严重错误,通过 Telegram 发送告警
if [ -n "$errors" ]; then
    msg="🚨 【服务器故障告警】 🚨

$errors"

    # 使用 curl 的 --data-urlencode 自动处理中文和特殊字符转义,避开复杂的 JSON 拼写
    curl -s -X POST "https://api.telegram.org/bot$BOT_TOKEN/sendMessage" \
        --data-urlencode "chat_id=$CHAT_ID" \
        --data-urlencode "text=$msg" > /dev/null 2>&1
fi

三、脚本核心设计解析

  1. 断点续读(增量扫描):脚本通过 stat -c%s 获取文件当前大小,并与同级目录记录的 last_position.txt 进行比对。利用 tail -c +$start_byte 只读取新增的字节内容。这彻底避免了传统全量 cat 或 grep 带来的 CPU 性能开销。

  2. 防崩溃日志轮转(Logrotate):第 4 步的边界判断非常精妙:如果系统发生了日志轮转或者日志被清空(导致 current_size 小于上一次记录的 last_offset),脚本会自动将偏移量重置为 0,保证不会因为文件缩反而导致脚本卡死或报错。

  3. 精准高危过滤:通过 grep -E -i 结合单词边界 \b,精准捕捉应用级(CRITICAL、ERROR、FATAL)以及 Web 服务器级(CRIT、ALERT、EMERG)的高危关键字,过滤掉无意义的 Notice 和 Warning 干扰。

  4. 安全传参防转义:推送时巧妙利用了 curl --data-urlencode,由底层自动处理日志中的特殊符号、空格和中文换行,完美避开了手写 JSON 时容易出现的格式崩塌问题。

四、部署与自动化运行

  1. 赋予脚本执行权限:

    chmod +x /path/to/log_watcher.sh
    
  2. 配置 Crontab 定时任务:打开定时任务编辑器:

    crontab -e
    

    加入以下规则,让脚本每分钟自动巡检一次日志:

    */1 * * * * /bin/bash /path/to/log_watcher.sh >/dev/null 2>&1
    

至此,一个轻量、高效、高解耦的服务器日志监控守护体系便搭建完毕。

五、 为什么这个方案值得收藏?

  1. 极其优雅的参数转义:在 Bash 中直接拼接 JSON 发送 HTTP 请求往往会因为双引号、换行符导致崩溃。这里巧妙地使用了 curl 的 --data-urlencode 参数,让系统自动帮你把带有换行和特殊字符的错误日志转义安全,省去了引入 jq 或复杂字符串替换的麻烦。

  2. 完全解耦:监控脚本作为一个独立的“外挂”运行,无论你的网站业务代码怎么迭代、怎么报错崩溃,监控脚本依然能独立、安全地把最后一眼的错误现场捕获并推送给你。

  3. 极低的性能开销:每次运行只比对文件大小、读取增量文本,耗时不到 0.01 秒,对服务器 CPU 和内存几乎零消耗。


更多文章 下一页