Linux 日志自动归档工具(Shell+Python)
Linux 日志自动归档工具(Shell+Python)
为你撰写一篇适配CSDN平台的《Linux日志自动归档工具(Shell+Python双版本实现)》技术文章,内容兼顾实战性和实用性,贴合运维场景,可直接发布:
Linux日志自动归档工具(Shell+Python双版本实现)
在Linux服务器运维中,日志文件会持续增长,不仅占用磁盘空间,还会导致日志查询效率降低。本文将分享Shell脚本和Python程序两种实现方式的日志自动归档工具,实现日志的定时切割、压缩、过期删除全自动化,适用于游戏服务器、Web服务、数据库等各类Linux服务的日志管理。
一、需求分析
日志归档工具需满足以下核心需求:
-
按时间切割:按天/小时切割日志文件(如
app.log→app-20251222.log); -
压缩存储:切割后的日志自动压缩为
.tar.gz格式,节省磁盘空间; -
过期清理:自动删除超过指定天数的归档日志(如保留30天);
-
定时执行:通过Linux
crontab实现定时自动运行; -
日志记录:工具运行过程生成日志,便于故障排查。
二、环境准备
-
服务器系统: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
五、功能扩展(可选)
根据实际运维需求,可对工具进行以下扩展:
-
批量日志处理:在Shell/Python脚本中添加日志文件列表,实现多日志自动归档;
-
磁盘空间告警:当归档目录磁盘使用率超过80%时,通过邮件/钉钉发送告警;
-
日志备份到远端:将归档日志同步到NFS/OSS/S3等远端存储,实现异地备份;
-
按日志大小切割:除了按时间切割,还可根据日志文件大小(如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日志自动归档工具,通过Shell和Python两种方式满足不同运维场景:
-
Shell版本:轻量、高效、无依赖,适合简单的单日志归档场景;
-
Python版本:功能丰富、易扩展,适合批量日志处理、复杂告警的场景。
创作不易,若本文对你有帮助,欢迎点赞、收藏、关注!
更多推荐



所有评论(0)