作为运维,你是不是也经历过这样的崩溃瞬间:
凌晨3点被监控电话吵醒:"/opt分区使用率95%!" 登录服务器一看,全是半年前没人看的日志 手动gzip压缩一个10GB文件,要等5分钟,还不能删源文件 更头疼的是:等保要求日志至少保留180天,删都删不得
今天分享一个渐进式日志压缩解决方案,完美平衡安全合规与运维效率。
一、等保合规 vs 日常效率:找到那个平衡点
等保要求180天 ≠ 所有日志都要明文躺平180天!
我们的策略:
最近2个月:日志明文,方便随时grep排查问题 2个月前:压缩归档,空间直接缩小90% 超过180天:自动清理或迁移冷存储
这样既满足审查要求,又保证日常排查效率,磁盘空间也释放了。
二、脚本演进:从"能用"到"好用"
阶段1:单文件压缩(最原始)
bash 复制
# 痛点:手动操作,无法批量,看不到进度
gzip -1 2025-12-15.log
阶段2:批量并行压缩(质的飞跃)
bash 复制
# 痛点:参数写死,不灵活
find . -name "*.log" -mtime +60 | xargs -P 8 -I {} gzip -1 {}
阶段3:参数化脚本(生产级) 现在我们有了终极版本:
bash 复制
#!/bin/bash
# compress_logs.sh - 智能日志压缩工具
# ==========================================
# 核心配置(可命令行覆盖)
DEFAULT_LOG_DIR="/opt"
DEFAULT_DAYS=60 # 压缩60天前的文件(保留最近2个月)
DEFAULT_LEVEL=1 # 压缩级别1(速度最快)
DEFAULT_JOBS=8 # 并行8个任务
DEFAULT_TYPE="gzip" # 压缩类型
# ==========================================
# 使用示例:
# ./compress_logs.sh --help
# ./compress_logs.sh -d /var/log -k 60 -l 1 -j 16
三、完整脚本:一键搞定日志压缩
bash
复制
#!/bin/bash
# compress_logs.sh - 智能日志压缩工具
# 配色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# 默认配置
DEFAULT_LOG_DIR="/opt"
DEFAULT_DAYS=60 # 压缩60天前的文件(保留最近2个月)
DEFAULT_LEVEL=1 # 压缩级别1(速度最快)
DEFAULT_JOBS=8
DEFAULT_TYPE="gzip"
# 帮助信息
usage() {
cat << EOF
${BLUE}智能日志压缩工具${NC}
用法: $0 [选项]
选项:
-d, --dir PATH 日志目录路径 (默认: /opt)
-k, --days DAYS 保留天数,压缩N天前的文件 (默认: 60,保留2个月)
-l, --level LEVEL 压缩级别 1-9 (默认: 1)
-j, --jobs NUM 并行作业数 (默认: 8)
-t, --type TYPE 压缩类型: gzip 或 zip (默认: gzip)
-h, --help 显示帮助
${GREEN}示例:${NC}
$0 # 压缩/opt下60天前的日志
$0 -d /var/log -k 30 -l 3 # 压缩30天前的,级别3
$0 --dir /data --days 60 --jobs 16 # 16个并行,快速处理
${YELLOW}提示:${NC}
• 建议使用gzip格式,zip仅用于跨平台交换
• 大文件用级别1-3,9级压缩率提升有限但耗时极长
• 等保要求180天,本脚本保留60天明文,压缩后保留180天
EOF
}
# 参数解析
TEMP=$(getopt -o d:k:l:j:t:h --long dir:,days:,level:,jobs:,type:,help -n "$0" -- "$@")
[ $? != 0 ] && usage && exit 1
evalset -- "$TEMP"
LOG_DIR="$DEFAULT_LOG_DIR"
DAYS="$DEFAULT_DAYS"
LEVEL="$DEFAULT_LEVEL"
PARALLEL_JOBS="$DEFAULT_JOBS"
COMPRESS_TYPE="$DEFAULT_TYPE"
whiletrue; do
case"$1"in
-d|--dir) LOG_DIR="$2"; shift 2 ;;
-k|--days) DAYS="$2"; shift 2 ;;
-l|--level) LEVEL="$2"; shift 2 ;;
-j|--jobs) PARALLEL_JOBS="$2"; shift 2 ;;
-t|--type) COMPRESS_TYPE="$2"; shift 2 ;;
-h|--help) usage; exit 0 ;;
--) shift; break ;;
*) echo"未知选项: $1"; usage; exit 1 ;;
esac
done
# 校验参数
[[ "$COMPRESS_TYPE" != "gzip" && "$COMPRESS_TYPE" != "zip" ]] && \
{ echo -e "${RED}错误: 压缩类型必须是 gzip 或 zip${NC}"; exit 1; }
[ ! -d "$LOG_DIR" ] && { echo -e "${RED}错误: 目录不存在${NC}"; exit 1; }
[ "$LEVEL" -lt 1 -o "$LEVEL" -gt 9 ] && { echo -e "${RED}错误: 压缩级别必须是1-9${NC}"; exit 1; }
# 开始工作
cd"$LOG_DIR" || exit 1
echo -e "${BLUE}=== 日志压缩任务开始 ===${NC}"
echo"⏱ 时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo"📂 目录: $LOG_DIR"
echo"⚙️ 配置: 压缩${DAYS}天前的文件,级别${LEVEL},并行${PARALLEL_JOBS}个任务,格式${COMPRESS_TYPE}"
echo"📝 行为: 保留最近${DAYS}天明文,更早的压缩归档(满足180天等保)"
# 查找文件
mapfile -t files < <(find . -maxdepth 1 -name "*.log" -mtime +$((DAYS-1)) 2>/dev/null)
if [ ${#files[@]} -eq 0 ]; then
echo -e "${YELLOW}⚠️ 没有符合条件的文件${NC}"
exit 0
fi
echo -e "\n📊 待压缩文件列表 (${#files[@]}个):"
for f in"${files[@]}"; do
printf"${BLUE}%-50s${NC} %10s\n""$f""$(du -h "$f" 2>/dev/null | cut -f1)"
done
# 并行压缩
echo -e "\n🚀 开始并行压缩..."
time {
if [ "$COMPRESS_TYPE" == "gzip" ]; then
for f in"${files[@]}"; do
gzip -"$LEVEL""$f" &
(( $(jobs | wc -l) >= PARALLEL_JOBS )) && wait
done
else
for f in"${files[@]}"; do
zip -"$LEVEL" -q "${f}.zip""$f" &
(( $(jobs | wc -l) >= PARALLEL_JOBS )) && wait
done
fi
wait
}
# 结果汇总
echo -e "\n${GREEN}=== 压缩结果 ===${NC}"
for f in"${files[@]}"; do
if [ "$COMPRESS_TYPE" == "gzip" ] && [ -f "${f}.gz" ]; then
printf"%-50s ${GREEN}→${NC} %10s\n""$f""$(du -h "${f}.gz" | cut -f1)"
elif [ "$COMPRESS_TYPE" == "zip" ] && [ -f "${f}.zip" ]; then
printf"%-50s ${GREEN}→${NC} %10s\n""$f""$(du -h "${f}.zip" | cut -f1)"
fi
done
echo -e "\n✅ 任务完成时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo -e "${GREEN}磁盘空间已释放,同时满足等保180天要求!${NC}"
四、实战效果:数据说话
压缩一个8.9GB日志文件:
bash 复制
# 执行
./compress_logs.sh -d /opt -k 60 -l 1
# 输出示例
=== 日志压缩任务开始 ===
⏱ 时间: 2025-12-17 15:30:00
📂 目录: /opt
⚙️ 配置: 压缩60天前的文件,级别1,并行8个任务,格式gzip
📝 行为: 保留最近60天明文,更早的压缩归档(满足180天等保)
📊 待压缩文件列表 (1个):
2025-12-15.log 8.9G
🚀 开始并行压缩...
real 0m42.123s ← 42秒完成压缩
=== 压缩结果 ===
2025-12-15.log → 573M
✅ 任务完成时间: 2025-12-17 15:30:42
磁盘空间已释放,同时满足等保180天要求!
五、自动化:让脚本自己跑
bash 复制
# 添加到crontab(每天凌晨2点执行)
0 2 * * * /opt/scripts/compress_logs.sh -d /opt/app/logs -k 60 -j 16 >/tmp/log_compress.log 2>&1
# 查看执行结果
tail -f /tmp/log_compress.log
等保审计时:
bash 复制
# 证明日志完整保存180天
find /opt/app/logs -name "*.log*" -mtime -180 | wc -l
# 输出: 180(正好是180天的日志)
六、运维心得:写给同行的话
还记得之前接到等保整改通知时,团队熬了几个通宵写脚本、做策略。后来发现,最好的方案不是最复杂的,而是最懂业务的:
保留2个月明文: 这是给开发同事留的"后悔药",排查问题不用找运维解压 压缩率vs速度: 大文件用-1就够了,省那5%空间多耗时10分钟不值 并行是神器: 8核CPU不用白不用,1分钟压缩完和10分钟完全两个心态 合规不是负担: 用好了自动化,等保检查反而成了加分项
七、互动话题
你们公司日志保留策略是怎样的?有没有更好的平衡方案?
欢迎在评论区分享你的经验
作者简介:某大厂SRE,专注运维自动化。踩过最大的坑是手动,最大的成就是解放双手。
echo "压缩前: $(ls -lh 2025-12-15.log | awk '{print $5}')" && \
echo "开始时间: $(date '+%H:%M:%S')" && \
time gzip -c 2025-12-15.log > 2025-12-15.log.gz && \
echo "结束时间: $(date '+%H:%M:%S')" && \
echo "压缩后: $(ls -lh 2025-12-15.log.gz | awk '{print $5}')" && \
du -h 2025-12-15.log 2025-12-15.log.gz





usage() {
echo -e "${BLUE}智能日志压缩工具${NC}"
echo"用法: $0 [选项]"
echo""
echo"选项:"
echo" -d, --dir PATH 日志目录路径 (默认: /opt)"
echo" -k, --days DAYS 保留天数,压缩N天前的文件 (默认: 60,保留2个月)"
echo" -l, --level LEVEL 压缩级别 1-9 (默认: 1)"
echo" -j, --jobs NUM 并行作业数 (默认: 8)"
echo" -t, --type TYPE 压缩类型: gzip 或 zip (默认: gzip)"
echo" -h, --help 显示帮助"
echo""
echo -e "${GREEN}示例:${NC}"
echo" $0 # 压缩/opt下60天前的日志"
echo" $0 -d /var/log -k 30 -l 3 # 压缩30天前的,级别3"
echo" $0 --dir /data --days 60 --jobs 16 # 16个并行,快速处理"
echo""
echo -e "${YELLOW}提示:${NC}"
echo" • 建议使用gzip格式,zip仅用于跨平台交换"
echo" • 大文件用级别1-3,9级压缩率提升有限但耗时极长"
echo" • 等保要求180天,本脚本保留60天明文,压缩后保留180天"
}



本文链接:https://www.jingber.cn/post/3948.html 转载需授权!

微信扫一扫,打赏作者吧~