Linux 日志自动归档工具(Shell+Python)

为你撰写一篇适配CSDN平台的《Linux日志自动归档工具(Shell+Python双版本实现)》技术文章,内容兼顾实战性和实用性,贴合运维场景,可直接发布:

Linux日志自动归档工具(Shell+Python双版本实现)

在Linux服务器运维中,日志文件会持续增长,不仅占用磁盘空间,还会导致日志查询效率降低。本文将分享Shell脚本Python程序两种实现方式的日志自动归档工具,实现日志的定时切割、压缩、过期删除全自动化,适用于游戏服务器、Web服务、数据库等各类Linux服务的日志管理。

一、需求分析

日志归档工具需满足以下核心需求:

  1. 按时间切割:按天/小时切割日志文件(如app.logapp-20251222.log);

  2. 压缩存储:切割后的日志自动压缩为.tar.gz格式,节省磁盘空间;

  3. 过期清理:自动删除超过指定天数的归档日志(如保留30天);

  4. 定时执行:通过Linuxcrontab实现定时自动运行;

  5. 日志记录:工具运行过程生成日志,便于故障排查。

二、环境准备

  • 服务器系统:CentOS 7/8、Ubuntu 20.04+(其他Linux发行版适配性良好);

  • 依赖工具tar(压缩)、find(文件查找)、Python 3.6+(Python版本需安装);

  • 日志路径:以游戏服务器日志/var/log/game/为例(可根据实际修改)。

三、Shell版本实现(轻量高效)

Shell脚本适合轻量场景,无需额外依赖,执行效率高,核心代码如下:

1. 编写Shell归档脚本log_archive.sh

#!/bin/bash
# 日志自动归档工具(Shell版)
# 配置项
LOG_DIR="/var/log/game"          # 原始日志目录
ARCHIVE_DIR="/var/log/archive"   # 归档日志目录
KEEP_DAYS=30                     # 保留归档日志天数
LOG_FILE="${ARCHIVE_DIR}/archive_tool.log" # 工具运行日志

# 创建目录(若不存在)
mkdir -p ${ARCHIVE_DIR}
touch ${LOG_FILE}

# 日志记录函数
log() {
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" >> ${LOG_FILE}
}

# 步骤1:切割当前日志(以app.log为例,可扩展为批量)
ORIGIN_LOG="${LOG_DIR}/app.log"
if [ -f ${ORIGIN_LOG} ]; then
    # 重命名原始日志为时间戳格式
    ARCHIVE_LOG="${ARCHIVE_DIR}/app-$(date +'%Y%m%d%H%M').log"
    mv ${ORIGIN_LOG} ${ARCHIVE_LOG}
    log "切割日志:${ORIGIN_LOG} → ${ARCHIVE_LOG}"
    
    # 重建空日志文件(避免服务日志输出失败)
    touch ${ORIGIN_LOG}
    # 重启日志输出服务(如游戏服务,根据实际情况修改)
    # systemctl restart game-server
else
    log "原始日志文件不存在:${ORIGIN_LOG}"
    exit 1
fi

# 步骤2:压缩切割后的日志
tar -zcf ${ARCHIVE_LOG}.tar.gz ${ARCHIVE_LOG} && rm -f ${ARCHIVE_LOG}
log "压缩日志:${ARCHIVE_LOG}.tar.gz"

# 步骤3:删除过期归档日志
find ${ARCHIVE_DIR} -name "app-*.tar.gz" -mtime +${KEEP_DAYS} -delete
log "删除${KEEP_DAYS}天前的归档日志完成"

log "日志归档工具执行完成"
echo "========================================" >> ${LOG_FILE}

2. 脚本权限与测试

# 添加执行权限
chmod +x log_archive.sh

# 手动执行测试
./log_archive.sh

# 查看工具运行日志
cat /var/log/archive/archive_tool.log

3. 定时执行(crontab)

通过crontab设置每天凌晨1点执行归档:

# 编辑crontab任务
crontab -e

# 添加以下内容(每天凌晨1点执行)
0 1 * * * /path/to/log_archive.sh > /dev/null 2>&1

四、Python版本实现(功能更丰富)

Python版本适合需要复杂逻辑(如批量日志处理、邮件告警)的场景,核心代码如下:

1. 编写Python归档脚本log_archive.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 日志自动归档工具(Python版)
import os
import sys
import tarfile
import shutil
import logging
from datetime import datetime, timedelta

# 配置项
LOG_DIR = "/var/log/game"          # 原始日志目录
ARCHIVE_DIR = "/var/log/archive"   # 归档日志目录
KEEP_DAYS = 30                     # 保留归档日志天数
LOG_TOOL = os.path.join(ARCHIVE_DIR, "archive_tool_py.log")  # 工具运行日志

# 配置日志记录
logging.basicConfig(
    filename=LOG_TOOL,
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S"
)

def init_dir():
    """初始化目录"""
    if not os.path.exists(ARCHIVE_DIR):
        os.makedirs(ARCHIVE_DIR)
        logging.info(f"创建归档目录:{ARCHIVE_DIR}")

def cut_log(log_file):
    """切割日志文件"""
    if not os.path.isfile(log_file):
        logging.error(f"原始日志文件不存在:{log_file}")
        return None
    # 生成时间戳文件名
    timestamp = datetime.now().strftime("%Y%m%d%H%M")
    log_name = os.path.basename(log_file)
    log_prefix = log_name.split(".")[0]
    archive_log = os.path.join(ARCHIVE_DIR, f"{log_prefix}-{timestamp}.log")
    # 重命名切割
    shutil.move(log_file, archive_log)
    # 重建空日志文件
    with open(log_file, "w", encoding="utf-8") as f:
        f.write("")
    logging.info(f"切割日志:{log_file} → {archive_log}")
    return archive_log

def compress_log(log_file):
    """压缩日志文件"""
    tar_file = f"{log_file}.tar.gz"
    with tarfile.open(tar_file, "w:gz") as tar:
        tar.add(log_file, arcname=os.path.basename(log_file))
    os.remove(log_file)  # 删除原日志文件
    logging.info(f"压缩日志:{tar_file}")
    return tar_file

def clean_expired_log():
    """删除过期归档日志"""
    expire_time = datetime.now() - timedelta(days=KEEP_DAYS)
    expire_timestamp = expire_time.timestamp()
    for file in os.listdir(ARCHIVE_DIR):
        if file.startswith("app-") and file.endswith(".tar.gz"):
            file_path = os.path.join(ARCHIVE_DIR, file)
            file_mtime = os.path.getmtime(file_path)
            if file_mtime < expire_timestamp:
                os.remove(file_path)
                logging.info(f"删除过期日志:{file_path}")
    logging.info(f"删除{KEEP_DAYS}天前的归档日志完成")

def main():
    """主函数"""
    init_dir()
    # 批量处理日志(可添加多个日志文件)
    log_files = [os.path.join(LOG_DIR, "app.log"), os.path.join(LOG_DIR, "error.log")]
    for log_file in log_files:
        archive_log = cut_log(log_file)
        if archive_log:
            compress_log(archive_log)
    clean_expired_log()
    logging.info("日志归档工具执行完成")
    logging.info("="*50)

if __name__ == "__main__":
    main()

2. 脚本测试与定时执行

# 手动执行测试
python3 log_archive.py

# 添加crontab定时任务(每小时执行一次)
crontab -e
# 添加内容
0 * * * * /usr/bin/python3 /path/to/log_archive.py > /dev/null 2>&1

五、功能扩展(可选)

根据实际运维需求,可对工具进行以下扩展:

  1. 批量日志处理:在Shell/Python脚本中添加日志文件列表,实现多日志自动归档;

  2. 磁盘空间告警:当归档目录磁盘使用率超过80%时,通过邮件/钉钉发送告警;

  3. 日志备份到远端:将归档日志同步到NFS/OSS/S3等远端存储,实现异地备份;

  4. 按日志大小切割:除了按时间切割,还可根据日志文件大小(如100MB)触发切割。

扩展示例:Python版钉钉告警

# 需安装requests库:pip3 install requests
import requests

def send_dingding_alert(msg):
    """发送钉钉告警"""
    webhook = "https://oapi.dingtalk.com/robot/send?access_token=你的钉钉机器人token"
    data = {
        "msgtype": "text",
        "text": {"content": f"日志归档工具告警:{msg}"}
    }
    try:
        requests.post(webhook, json=data)
        logging.info("钉钉告警发送成功")
    except Exception as e:
        logging.error(f"钉钉告警发送失败:{str(e)}")

# 在main函数中添加磁盘空间检查
disk_usage = os.popen(f"df -h {ARCHIVE_DIR} | grep -v Filesystem | awk '{{print $5}}'").read().strip()
disk_usage_percent = int(disk_usage.strip("%"))
if disk_usage_percent > 80:
    send_dingding_alert(f"归档目录磁盘使用率超过80%:{disk_usage}")

六、总结

本文实现的Linux日志自动归档工具,通过ShellPython两种方式满足不同运维场景:

  • Shell版本:轻量、高效、无依赖,适合简单的单日志归档场景;

  • Python版本:功能丰富、易扩展,适合批量日志处理、复杂告警的场景。

创作不易,若本文对你有帮助,欢迎点赞、收藏、关注!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐