日志轮转方案和脚本
**日志轮转方案 **
1. 日志轮转概述
按月份分割和打包日志文件,并保留当前月份的日志。脚本会根据日志文件的内容格式(访问日志或错误日志)进行处理,创建相应的目录,将分割后的日志文件保存到按月份命名的目录中,最后将每个月的目录打包为 .tar.gz 文件,并清空原始日志文件,只保留当前月份的日志。
日志全量只留存一年,现服务器堆积一年前所有的日志已清空,本脚本没有添加按年删除的功能,需手动删除,也就是说在使用脚本之前需要处理一下今年之前的日志,或者在补充一下脚本灵活性,说实话我感觉这个脚本有点der,还不如直接上工具,有想法可以一起沟通,自己琢磨太费劲了,欢迎各位运维大佬
2. 配置和准备工作
· 日志目录: LOG_DIR 变量指定了日志文件所在的目录。
· 月份数组: MONTHS 变量包含了所有的月份数字,用于过滤日志内容。
· 月份名称: MONTH_NAMES 变量包含了月份的英文缩写,用于格式化日志内容。
· 日志文件路径: LOGFILE 变量指定了记录脚本运行日志的文件路径。
3. 脚本执行步骤
创建日志文件: 脚本首先创建一个日志文件,用于记录处理过程中的所有输出信息。
处理日志文件:
① 访问日志: 根据文件名中的 access 关键字,脚本将日志文件按照月份分割,并将每个月的日志保存到对应的目录中。
② 错误日志: 根据文件名中的 error 关键字,脚本将日志文件按照月份分割,并将每个月的日志保存到对应的目录中。
打包目录: 脚本将每个月的目录打包为 .tar.gz 文件,并删除原始目录。
清空****日志文件: 脚本清空原始日志文件切割内容,但保留当前月份的日志。
4. 定时任务设置
在每个月的第一天凌晨 2 点执行该脚本,按照以下步骤设置定时任务:
(1) 编辑 cron 配置文件:
crontab -e
(2) 添加定时任务**:******
0 2 1 * * /scripts/split_logs_by_month.sh
(3) 检查 cron 服务状态**😗*****
sudo systemctl status cron
crontab -l
5、**脚本测试 **
#在个人主机测试的,准备了两个日志文件
(1) 执行
/scripts/split_logs_by_month.sh
(2) 结果
#将日志按照月份切割后,按月份保存到目录,再生成压缩包,删除目录,原日志文件只剩余当月的日志
6、注意事项
· 确保日志目录存在: 在脚本执行前,确保 LOG_DIR 指定的目录存在。
· **权限: **确保脚本具有足够的权限来读取日志文件、创建目录、写入日志和执行其他操作。
#!/bin/bash
#auth:Dragon_qu
#version:v1.0
# 配置变量
LOG_DIR="/var/log/nginx" # 日志目录
MONTHS=("01" "02" "03" "04" "05" "06" "07" "08" "09" "10" "11" "12") # 月份数组
MONTH_NAMES=("Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec") # 月份英文缩写
YEAR=$(date +%Y) # 当前年份
CURRENT_MONTH=$(date +%m) # 当前月份数字
LOGFILE="/scripts/split_logs_by_month_$(date +%Y%m%d).log" # 日志文件路径
# 定义输出日志的函数
log() {
echo "$(date +'%Y-%m-%d %H:%M:%S') $1" >> "$LOGFILE"
}
# 检查日志目录是否存在
if [ ! -d "$LOG_DIR" ]; then
log "日志目录不存在:$LOG_DIR"
exit 1
fi
# 定义函数来处理访问日志文件
process_access_log_file() {
local log_file="$1"
local log_filename=$(basename "$log_file")
log "处理访问日志文件: $log_filename"
for i in ${!MONTHS[@]}; do
month_num=${MONTHS[$i]}
month_name=${MONTH_NAMES[$i]}
# 跳过当前月份的日志
if [ "$month_num" == "$CURRENT_MONTH" ]; then
continue
fi
# 检查日志文件是否包含对应月份的内容
if grep -qE "\/$month_name" "$log_file"; then
# 创建目标目录
year_month="${YEAR}-${month_num}"
month_dir="${LOG_DIR}/${year_month}"
mkdir -p "$month_dir"
# 使用 grep 过滤出对应月份的日志行,并重定向到新文件
grep -E "\/$month_name" "$log_file" >> "${month_dir}/${log_filename}"
log "日志已重定向到: ${month_dir}/${log_filename}"
fi
done
log "[$log_filename] 日志已处理完毕"
}
# 定义函数来处理错误日志文件
process_error_log_file() {
local log_file="$1"
local log_filename=$(basename "$log_file")
log "处理错误日志文件: $log_filename"
for month_num in "${MONTHS[@]}"; do
# 跳过当前月份的日志
if [ "$month_num" == "$CURRENT_MONTH" ]; then
continue
fi
log "检查月份: ${YEAR}/${month_num}/"
# 检查错误日志格式是否存在
if grep -qE "${YEAR}/${month_num}/" "$log_file"; then
log "找到匹配: ${YEAR}/${month_num}/ 在文件: $log_file"
# 创建目标目录
year_month="${YEAR}-${month_num}"
month_dir="${LOG_DIR}/${year_month}"
mkdir -p "$month_dir"
# 使用 grep 过滤出对应月份的日志行,并重定向到新文件
grep -E "${YEAR}/${month_num}/" "$log_file" >> "${month_dir}/${log_filename}"
log "日志已重定向到: ${month_dir}/${log_filename}"
else
log "未找到匹配: ${YEAR}/${month_num}/ 在文件: $log_file"
fi
done
log "[$log_filename] 日志已处理完毕"
}
# 遍历日志目录中的每个 .log 文件,处理包含 "access" 或 "error" 的文件
for log_file in "$LOG_DIR"/*.log; do
if [[ -f "$log_file" ]]; then
if [[ "$log_file" == *access* ]]; then
process_access_log_file "$log_file"
elif [[ "$log_file" == *error* ]]; then
process_error_log_file "$log_file"
else
log "未处理的日志文件: $log_file"
fi
else
log "未找到日志文件: $log_file"
fi
done
# 将每个月的目录打包成 .tar.gz 文件
for i in ${!MONTHS[@]}; do
month_num=${MONTHS[$i]}
year_month="${YEAR}-${month_num}"
month_dir="${LOG_DIR}/${year_month}"
if [ -d "$month_dir" ]; then
tar -czf "${LOG_DIR}/${year_month}.tar.gz" -C "$LOG_DIR" "$year_month"
log "目录 ${month_dir} 已打包为 ${LOG_DIR}/${year_month}.tar.gz"
# 删除原始目录
rm -rf "$month_dir"
log "已删除原始目录: ${month_dir}"
fi
done
# 清空原始日志文件,保留当前月份的日志
for log_file in "$LOG_DIR"/*.log; do
if [[ -f "$log_file" ]]; then
# 备份当前月份的日志到临时文件
grep -E "\/$(date +%b)" "$log_file" > "${log_file}.tmp"
# 用临时文件替换原始日志文件
mv "${log_file}.tmp" "$log_file"
log "已清空日志文件,但保留当前月份的日志: $log_file"
fi
done
log "所有日志文件已按月份分割并输出到相应目录,并已打包且清空,保留当前月份的日志。"