提交 e8861898 authored 作者: 陈泽健's avatar 陈泽健

feat(scripts): 添加自动化清理和MySQL日志备份脚本

- 实现了自动清理已删除大文件的脚本(auto_clean_deleted_ubains_v3.sh)
- 添加了MySQL日志文件定时备份与压缩功能(backup_mysql_logs.sh)
- 包含日志轮转机制,支持5MB轮转和指定天数保留
- 实现了文件权限保存和恢复功能
- 添加了容器重启和特定应用启动逻辑
- 集成了错误处理和日志记录机制
上级 2fc1edbe
#!/bin/bash
#===============================================================================
# 脚本名称:auto_clean_deleted_ubains_v3.sh
# 功能描述:已删除大文件自动清理与容器重启脚本
# 版本:V3.1
# 创建日期:2026-01-27
# 更新日期:2026-03-30
#
# 监测对象:
# 1. 进程占用的已删除大文件(>1GB)
# 2. 匹配关键字: ubains-INFO-AND-ERROR
# 3. 自动清理并重启关联容器
# 4. 日志文件自动轮转(5MB轮转、保留7天)
#
# 清理策略:
# 1. 扫描所有进程的fd目录,查找deleted标记文件
# 2. 文件大小超过1GB时执行自动处理
# 3. 强制杀死占用进程
# 4. 重启docker容器ujava2
# 5. 若进程属于特定应用,启动该应用
#
# 使用方法:
# chmod +x auto_clean_deleted_ubains_v3.sh
# ./auto_clean_deleted_ubains_v3.sh
#
# 定时任务示例:
# 0 4 * * * /opt/scripts/auto_clean_deleted_ubains_v3.sh
#===============================================================================
# ================= 配置区域 =================
TARGET_KEY="ubains-INFO-AND-ERROR"
MIN_SIZE=$((1024*1024*1024)) # 1GB (单位:字节)
LOG_FILE="/data/logs/auto_clean_deleted_ubains.log"
MAX_LOG_SIZE=$((5*1024*1024)) # 5MB 日志大小限制
LOG_RETENTION_DAYS=7 # 日志保留天数
CONTAINER_NAME="ujava2" # 容器名称
APP_PATH="/data/services/api/java-meeting/java-meeting-extapi" # 特定应用路径
APP_START_SCRIPT="${APP_PATH}/run.sh" # 特定应用启动脚本
# ===========================================
# 日志函数
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}
# 日志轮转
rotate_logs() {
if [ -f "$LOG_FILE" ]; then
FILE_SIZE=$(stat -c%s "$LOG_FILE")
if [ "$FILE_SIZE" -ge "$MAX_LOG_SIZE" ]; then
mv "$LOG_FILE" "$LOG_FILE.$(date '+%Y%m%d%H%M%S')"
touch "$LOG_FILE"
log "日志文件超过 5MB,已自动轮转。"
fi
fi
find "$(dirname "$0")" -name "auto_clean_deleted_ubains.log.*" -mtime +$LOG_RETENTION_DAYS -exec rm -f {} \;
}
rotate_logs
log "==============================================="
log "开始扫描:检测 deleted 大文件并自动清理 (内核直读版)"
log "匹配关键字: $TARGET_KEY"
log "大于尺寸: 1GB"
log "==============================================="
FOUND=0
NEED_RESTART=0
NEED_APP_START=0 # 新增:标记是否需要启动特定应用
# 遍历所有进程的 fd 目录,寻找匹配关键字且标记为 deleted 的文件
for fd_path in /proc/[0-9]*/fd/*; do
# 检查是否为符号链接且指向包含关键字的已删除文件
if [ -L "$fd_path" ]; then
target_file=$(readlink "$fd_path" 2>/dev/null)
if [[ "$target_file" == *"(deleted)"* ]] && [[ "$target_file" == *"$TARGET_KEY"* ]]; then
FOUND=1
# 提取 PID 和 FD
pid=$(echo "$fd_path" | cut -d'/' -f3)
fd=$(echo "$fd_path" | cut -d'/' -f5)
# 获取进程名
proc_name="unknown"
[ -f "/proc/$pid/comm" ] && proc_name=$(cat "/proc/$pid/comm")
# 获取文件大小 (字节) - 使用 stat -L 获取链接指向的实际文件状态
size_bytes=$(stat -L -c %s "$fd_path" 2>/dev/null || echo 0)
size_mb=$((size_bytes / 1024 / 1024))
log "-----------------------------------------------"
log "发现匹配文件:"
log "进程: $proc_name"
log "PID: $pid"
log "FD: $fd"
log "文件: $target_file"
log "大小: $size_mb MB"
if [ "$size_bytes" -ge "$MIN_SIZE" ]; then
log "⚠ 文件超过1GB,执行自动处理。"
log "➡ 杀死进程 PID: $pid"
kill -9 "$pid" 2>/dev/null
sleep 1
NEED_RESTART=1
# 获取进程的当前工作目录,判断是否为特定应用
proc_cwd=$(readlink /proc/$pid/cwd 2>/dev/null)
if [ "$proc_cwd" == "$APP_PATH" ]; then
log "检测到被杀死的进程属于特定应用:$APP_PATH,将在容器重启后尝试启动。"
NEED_APP_START=1
fi
else
log "⏩ 文件不足 1GB,跳过。"
fi
fi
fi
done
if [ "$FOUND" -eq 0 ]; then
log "未发现匹配的 deleted 文件。"
fi
if [ "$NEED_RESTART" -eq 1 ]; then
log "➡ 检测到大文件进程已处理,统一重启 docker 容器:$CONTAINER_NAME"
# 检查 docker 命令是否存在
if command -v docker >/dev/null 2>&1; then
docker restart "$CONTAINER_NAME" >> "$LOG_FILE" 2>&1
log "✔ Docker 容器重启完成。"
else
log "❌ 错误: 未找到 docker 命令,请手动重启容器。"
fi
# 如果需要启动特定应用,则执行启动脚本
if [ "$NEED_APP_START" -eq 1 ]; then
log "➡ 启动特定应用脚本:$APP_START_SCRIPT"
if [ -f "$APP_START_SCRIPT" ]; then
bash "$APP_START_SCRIPT" >> "$LOG_FILE" 2>&1
log "✔ 特定应用启动脚本执行完成。"
else
log "❌ 错误: 未找到特定应用启动脚本:$APP_START_SCRIPT。"
fi
fi
else
log "无需重启 docker 容器。"
fi
log "🎉 执行结束。"
log "==============================================="
#!/bin/bash
#===============================================================================
# 脚本名称:backup_mysql_logs.sh
# 功能描述:MySQL日志文件定时备份与压缩脚本
# 版本:V1.2
# 创建日期:2026-01-27
# 更新日期:2026-03-30
# 基于文档:_PRD_新统一平台_MySQL日志备份需求文档.md
#
# 备份对象:
# 1. MySQL容器日志文件(.log, .slow等)
# 2. 自动压缩备份文件
# 3. 保留原始文件权限
# 4. 自动清理过期备份
# 5. 日志文件自动轮转(5MB轮转、保留30天)
#
# 日志文件类型:
# *.log, *.slow, error.log, slow.log, mysqld.log
#
# 使用方法:
# chmod +x backup_mysql_logs.sh
# ./backup_mysql_logs.sh
#
# 定时任务示例:
# 0 2 * * * /data/services/scripts/backup_mysql_logs.sh
#===============================================================================
# ==================== 配置区 ====================
MYSQL_LOG_DIR="/data/middleware/mysql/log" # MySQL日志目录
BACKUP_DIR="/data/bakup/mysql/logs/backup" # 备份目录
LOG_FILE="/data/logs/backup_mysql_logs.log" # 日志文件路径
MAX_LOG_SIZE=$((5*1024*1024)) # 5MB 日志大小限制
LOG_RETENTION_DAYS=30 # 日志保留天数
RETENTION_DAYS=30 # 备份保留天数
DATE=$(date +"%Y%m%d") # 当前日期格式 YYYYMMDD
TODAY_DIR="$BACKUP_DIR/$DATE" # 今天的备份目录
# ==================== 日志函数 ====================
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
# ==================== 日志轮转函数 ====================
rotate_logs() {
if [ -f "$LOG_FILE" ]; then
FILE_SIZE=$(stat -c%s "$LOG_FILE" 2>/dev/null || echo 0)
if [ "$FILE_SIZE" -ge "$MAX_LOG_SIZE" ]; then
mv "$LOG_FILE" "$LOG_FILE.$(date '+%Y%m%d%H%M%S')"
touch "$LOG_FILE"
log "日志文件超过 5MB,已自动轮转。"
fi
fi
# 清理超过保留天数的旧日志文件
find "$(dirname "$LOG_FILE")" -name "backup_mysql_logs.log.*" -mtime +$LOG_RETENTION_DAYS -exec rm -f {} \; 2>/dev/null
}
# ==================== 权限保存和恢复函数 ====================
save_permissions() {
local file="$1"
# 获取文件权限和属主信息
local perms owner group
perms=$(stat -c %a "$file" 2>/dev/null)
owner=$(stat -c %U "$file" 2>/dev/null)
group=$(stat -c %G "$file" 2>/dev/null)
# 存储到临时文件
echo "$perms $owner $group" > "$file.permissions.tmp"
}
restore_permissions() {
local file="$1"
local perm_file="$file.permissions.tmp"
if [ -f "$perm_file" ]; then
local perms owner group
read -r perms owner group < "$perm_file"
# 恢复权限和属主(增加空值检查)
if [ -n "$owner" ] && [ -n "$group" ]; then
chown "$owner:$group" "$file" 2>/dev/null
fi
if [ -n "$perms" ]; then
chmod "$perms" "$file" 2>/dev/null
fi
# 删除临时权限文件
rm -f "$perm_file"
fi
}
# ==================== 主要功能 ====================
# 创建日志目录并确保存在
mkdir -p "$(dirname "$LOG_FILE")"
touch "$LOG_FILE"
# 执行日志轮转
rotate_logs
log "===== 开始备份MySQL日志 (日期: $DATE) ====="
# 创建备份目录
mkdir -p "$TODAY_DIR"
# 检查MySQL日志目录是否存在
if [ ! -d "$MYSQL_LOG_DIR" ]; then
log "❌ MySQL日志目录不存在: $MYSQL_LOG_DIR"
exit 1
fi
# 进入日志目录
cd "$MYSQL_LOG_DIR" || {
log "❌ 无法进入目录: $MYSQL_LOG_DIR"
exit 1
}
# 查找所有日志文件(包括 .log 和 .slow 文件)
LOG_FILES=$(find "$MYSQL_LOG_DIR" -maxdepth 1 \( -name "*.log" -o -name "*.slow" -o -name "error.log" -o -name "slow.log" -o -name "mysqld.log" \) -type f)
if [ -z "$LOG_FILES" ]; then
log "⚠️ 在 $MYSQL_LOG_DIR 中未找到日志文件"
exit 0
fi
# 备份并压缩每个日志文件
SUCCESS_COUNT=0
for log_file in $LOG_FILES; do
filename=$(basename "$log_file")
source_path="$MYSQL_LOG_DIR/$filename"
# 跳过已经备份过的文件(如果同名备份已存在)
if [ -f "$TODAY_DIR/${filename}.gz" ]; then
log "⚠️ 备份文件已存在,跳过: $filename"
continue
fi
log "开始备份日志文件: $filename"
# 保存原始权限信息
save_permissions "$source_path"
# 复制文件到备份目录并压缩
if gzip -c "$source_path" > "$TODAY_DIR/${filename}_${DATE}.gz"; then
log "✅ 日志备份并压缩成功: $filename -> ${filename}_${DATE}.gz"
((SUCCESS_COUNT++))
else
log "❌ 日志备份失败: $filename"
# 如果备份失败,仍需要恢复权限信息
restore_permissions "$source_path"
fi
# 恢复原始文件权限
restore_permissions "$source_path"
done
log "本次共成功备份 $SUCCESS_COUNT 个日志文件"
# ==================== 清理超过30天的旧备份 ====================
log "开始清理超过 $RETENTION_DAYS 天的旧备份..."
find "$BACKUP_DIR" -maxdepth 1 -type d -name "????????" -mtime +$RETENTION_DAYS -exec rm -rf {} + 2>/dev/null
# 清理权限临时文件(以防万一)
find "$MYSQL_LOG_DIR" -name "*.permissions.tmp" -type f -delete 2>/dev/null
log "===== 日志备份任务结束 ====="
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论