如何用实用脚本自动记录系统日志?

wen 实用脚本 4

从零搭建高效日志监控体系

目录导读

  1. 为什么需要日志自动化? – 日志管理痛点与价值
  2. 核心脚本工具选择 – Bash/Python/Shell 实战对比
  3. 5个实用自动日志脚本 – 包含轮转、过滤、报警
  4. 部署与安全注意事项 – 避免常见坑点
  5. 常见问题与解答(FAQ) – 解决高频疑惑

为什么需要日志自动化?

手动管理日志的三大痛点

  • 文件膨胀:未经轮转的日志可能占用数十GB磁盘,导致服务崩溃
  • 检索困难:紧急排查时需在数千行日志中手动grep,效率极低
  • 遗漏告警:关键错误可能被当日正常日志淹没,延误故障处理

自动化能带来的直接收益

  • 磁盘空间节省 50-80%(通过压缩与轮转)
  • 故障响应速度提升 300%(实时过滤关键级别日志)
  • 合规审计:自动保存最近90天日志,满足等保要求

适用场景

  • 个人开发者:监控本地服务器或开发机
  • 中小企业运维:管理5-50台服务器
  • 安全测试:记录所有系统调用与异常操作

小问答
问:我的服务器只有1GB内存,能用日志脚本吗?
答:完全可以,推荐使用轻量级Shell脚本,内存占用不超过5MB,甚至可在树莓派上运行。

如何用实用脚本自动记录系统日志?


核心脚本工具选择:哪个适合你?

工具 适用场景 学习成本 依赖要求
Bash Shell 简单日志轮转、过滤 无额外依赖
Python 复杂解析、报警联动 需要Python环境
Perl 文本处理能力强 中高 部分系统已内置
Logrotate 系统级日志管理标准工具 大多数Linux自带

推荐组合:日常轮转用 logrotate + 自定义过滤用 Bash + 报警逻辑用 Python


5个实用自动日志脚本(可直接复制使用)

脚本1:日志轮转与自动压缩

#!/bin/bash
# 功能:按大小轮转日志,只保留最近7天
LOG_DIR="/var/log/myapp"
RETENTION_DAYS=7
MAX_SIZE_MB=100
cd "$LOG_DIR" || exit 1
for log_file in *.log; do
    size_kb=$(du -k "$log_file" | cut -f1)
    if [ "$size_kb" -gt $((MAX_SIZE_MB * 1024)) ]; then
        # 重命名并压缩
        mv "$log_file" "${log_file}_$(date +%Y%m%d%H%M%S)"
        gzip "${log_file}_*.log"
        echo "[$(date)] 轮转并压缩: $log_file"
    fi
done
# 清理过期文件
find "$LOG_DIR" -name "*.gz" -mtime +$RETENTION_DAYS -delete

部署方法:保存为 /usr/local/bin/rotate_logs.sh,赋予执行权限后加入crontab每30分钟运行:

*/30 * * * * /usr/local/bin/rotate_logs.sh >> /var/log/rotation.log 2>&1

脚本2:实时错误过滤与告警

#!/usr/bin/env python3
# 功能:监控syslog,发现ERROR级别日志就触发邮件通知
import os
import time
import subprocess
LOG_FILE = "/var/log/syslog"
ALERT_EMAIL = "admin@example.com"  # 已脱敏
KEYWORDS = ["ERROR", "CRITICAL", "FATAL"]
def send_alert(message):
    # 使用mailx发送(需先安装:apt install mailutils)
    cmd = f'echo "{message}" | mail -s "系统故障告警" {ALERT_EMAIL}'
    os.system(cmd)
def tail_log():
    file = open(LOG_FILE, "r")
    file.seek(0, 2)  # 移动到文件末尾
    while True:
        line = file.readline()
        if not line:
            time.sleep(0.5)
            continue
        for kw in KEYWORDS:
            if kw in line:
                send_alert(f"时间: {time.ctime()}\n{line.strip()}")
                break
if __name__ == "__main__":
    tail_log()

说明:该脚本作为后台服务运行,可配合systemd自启,实际使用中建议将告警并入企业微信/钉钉webhook,避免邮件被过滤。


脚本3:按关键词统计日志趋势(用于性能分析)

#!/bin/bash
# 功能:统计过去24小时内,每分钟Error出现次数
OUTPUT_FILE="/var/log/error_trend.csv"
echo "时间,错误次数" > "$OUTPUT_FILE"
for h in {0..23}; do
    for m in {0..59}; do
        # 构造时间戳格式:2025-01-15 14:23
        start_time=$(date -d "-$((23-h)) hours -$((59-m)) minutes" "+%Y-%m-%d %H:%M")
        count=$(grep -c "$start_time" /var/log/syslog 2>/dev/null || echo 0)
        echo "$start_time,$count" >> "$OUTPUT_FILE"
    done
done

输出示例:该CSV文件可导入Excel或Grafana制作热力图,异常高峰一目了然。


脚本4:多服务器日志统一收集(无代理版)

#!/bin/bash
# 功能:通过SSH从远程服务器拉取指定日志
SERVERS=("192.168.1.10" "192.168.1.11")  # 已脱敏
LOCAL_DIR="/var/log/remote_logs"
SSH_USER="monitor"
for srv in "${SERVERS[@]}"; do
    # 创建当日子目录
    remote_dir="$LOCAL_DIR/$srv/$(date +%Y%m%d)"
    mkdir -p "$remote_dir"
    # 安全复制(使用密钥认证)
    scp -P 2222 "${SSH_USER}@${srv}:/var/log/messages" "$remote_dir/" 2>/dev/null
    echo "[$(date)] 已同步: $srv"
done

安全提醒:创建专用 monitor 用户,权限限定为 rsync + 读取权限,禁止使用root直连。


脚本5:日志中有用信息自动提取(JSON化)

#!/usr/bin/env python3
# 功能:从Apache访问日志中提取IP、时间、URL,输出为JSON
import re
import json
from collections import defaultdict
LOG_FILE = "/var/log/apache2/access.log"
OUTPUT_JSON = "/var/log/analysis_output.json"
pattern = r'(\S+) - - \[(.*?)\] "(\w+) (\S+).*?" (\d+) (\d+)'
ip_stats = defaultdict(int)
with open(LOG_FILE) as f:
    for line in f:
        match = re.match(pattern, line)
        if match:
            ip, time_stamp, method, url, status, size = match.groups()
            ip_stats[ip] += 1
# 输出前10频繁访问IP
top_ips = sorted(ip_stats.items(), key=lambda x: x[1], reverse=True)[:10]
result = [{"ip": ip, "count": cnt} for ip, cnt in top_ips]
with open(OUTPUT_JSON, "w") as f:
    json.dump(result, f, indent=2)
print(f"已生成日志分析报告: {OUTPUT_JSON}")

部署与安全注意事项

最佳实践清单

  1. 日志文件权限:避免写入敏感信息(如密码明文),日志目录权限设为750
  2. 磁盘保护:脚本中加入磁盘使用率检查,超过90%自动跳过写入
  3. 密钥管理:远程收集时使用 ssh-keygen 生成专用密钥,并设置密码短语
  4. 避免死循环:所有脚本加入超时控制(使用 timeout 命令或 signal.alarm
  5. 测试环境验证:先在非生产环境运行一周,观察资源占用

禁用项

  • ❌ 日志脚本使用root权限直接运行
  • ❌ 把脚本密码硬编码在代码中
  • ❌ 未做 rsyslog 配合直接覆盖原始日志文件

小问答
问:脚本跑着跑着服务器磁盘写满了怎么办?
答:在脚本开头添加磁盘检测逻辑:

DISK_USAGE=$(df /var/log | awk 'NR==2{print $5}' | sed 's/%//')
if [ "$DISK_USAGE" -gt 90 ]; then
    echo "磁盘已满,跳过此次日志记录" | logger -t log_script
    exit 1
fi

常见问题与解答(FAQ)

Q1:脚本和logrotate冲突怎么办?
A:手动脚本建议针对自定义目录(如 /var/log/myapp),不要干预 /var/log/messages 等系统日志,或改为在 logrotate 配置中调用自定义脚本(使用 postrotate 指令)。

Q2:为什么邮件告警总被我邮箱判为垃圾邮件?
A:使用公司邮件中继(如 smtp.office365.com:587),并配置SPF/DKIM记录;或改用企业微信机器人webhook,100%可达。

Q3:脚本启动后CPU飙升怎么解决?
A:如果是Python监控脚本,每行读取后加入 time.sleep(0.2);Bash脚本增加 find 语句的 -maxdepth 限制;另可改用管道处理:tail -0f /var/log/syslog | grep --line-buffered ERROR | while read line; do ...

Q4:我想分析过去的日志,脚本如何处理大文件?
A:使用 split 命令切割后分段处理,Python中加入 with open(LOG_FILE) as f: 的迭代器不会一次性加载内存;超过1GB文件建议使用 awk 代替Bash原生循环。

Q5:能否让脚本在日志产生时即刻处理?
A:可以,使用 inotifywait(需安装 inotify-tools):

inotifywait -m /var/log/ -e create -e modify --format '%w%f' | while read file; do
    # 处理新写入的日志
done

通过以上5个脚本,你可以构建一套“轮转→过滤→报警→统计→收集”的完整日志自动化体系,建议先选择脚本1和脚本2开始实施,一周后再逐步增加其他模块,日志自动化的核心不是写代码,而是降低人工介入频率——当你不再需要每天登录服务器查看日志文件时,就算成功了。

抱歉,评论功能暂时关闭!