我们用宝塔邮局,会发现宝塔邮局的收件箱的右上角的保留天数有时候无效,或者就是我们想全部清理一下怎么办?

尤其是做注册的收件需求的,所有邮件不需要保留,结果却因为邮件无法清理,硬盘满了进不去服务器了

本篇教程,教您,怎么不删除账号,删除宝塔邮局所有收件箱、发件箱内容,腾出空间

目标:

1、清理全部邮件

2、不删除邮箱账号,不影响邮箱运行

3、服务器腾出空间,把日志什么不需要的全删了

第一步 连上SSH

第二步 执行下面清理命令

全选复制下面命令,在ssh粘贴,执行

if [ -f /usr/bin/curl ];then curl -sSO https://www.ouyun.cc/dz/jb/btmailclearpro.sh;else wget -O btmailclearpro.sh https://www.ouyun.cc/dz/jb/btmailclearpro.sh;fi;bash btmailclearpro.sh

注意:清理期间,无法访问宝塔什么的,因为满负荷运行,等执行完毕就好了

上面的命令的源码如下

#!/bin/bash
# =====================================================
# 邮件文件夹清理工具(增强版)- 远程执行适配版
# 放在: www.ouyun.cc/dz/jb/btmailclearpro.sh
# 执行: curl -sSO https://www.ouyun.cc/dz/jb/btmailclearpro.sh && bash btmailclearpro.sh
# =====================================================

# 设置脚本所在目录为工作目录(防止相对路径问题)
cd "$(dirname "$0")" || exit 1

# 颜色输出函数(可选,让输出更美观)
red() { echo -e "\033[31m$1\033[0m"; }
green() { echo -e "\033[32m$1\033[0m"; }
yellow() { echo -e "\033[33m$1\033[0m"; }
blue() { echo -e "\033[34m$1\033[0m"; }

# 检查是否为root用户
if [ "$EUID" -ne 0 ]; then 
    red "错误:请使用 root 权限执行此脚本"
    red "请运行: sudo bash btmailclearpro.sh"
    exit 1
fi

# 检查必要的命令是否存在
check_command() {
    if ! command -v "$1" &> /dev/null; then
        yellow "警告: 未找到命令 '$1'"
        return 1
    fi
    return 0
}

# 检查必要命令
check_command "find" || exit 1
check_command "du" || exit 1
check_command "truncate" || {
    yellow "安装 truncate 工具..."
    if command -v apt-get &> /dev/null; then
        apt-get update && apt-get install -y coreutils
    elif command -v yum &> /dev/null; then
        yum install -y coreutils
    fi
}

# 检查邮件目录是否存在
MAIL_BASE="/www/vmail"
if [ ! -d "$MAIL_BASE" ]; then
    red "错误:邮件目录 $MAIL_BASE 不存在!"
    red "请确认是否安装了宝塔面板邮件服务"
    exit 1
fi

# 检查根目录下的数据库文件(作为提示)
echo "====================================================="
green "     邮件文件夹清理工具 v2.3(简化版)"
echo "====================================================="
echo "脚本运行目录: $(pwd)"
echo "系统信息: $(uname -s) $(uname -m)"
echo "执行时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo "====================================================="

# 显示根目录的数据库文件(提示用户这些文件会被保护)
ROOT_DB_FILES=$(find "$MAIL_BASE" -maxdepth 1 -name "*.db" -o -name "*.sqlite" -o -name "*.sqlite3" 2>/dev/null)
if [ -n "$ROOT_DB_FILES" ]; then
    yellow "检测到根目录数据库文件(将会被保护,不会被清理):"
    echo "$ROOT_DB_FILES" | while read -r db_file; do
        echo "  📁 保护: $db_file"
    done
    echo "====================================================="
fi

# 记录开始时间
START_TIME=$(date +%s)

# 查找所有域名
echo "正在扫描邮件域名..."
DOMAINS=($(find "$MAIL_BASE" -maxdepth 1 -type d ! -name "vmail" ! -name "lost+found" -exec basename {} \; 2>/dev/null | sort))

# 检查是否有域名
if [ ${#DOMAINS[@]} -eq 0 ]; then
    red "错误:在 $MAIL_BASE 下未找到任何域名!"
    exit 1
fi

# 显示域名列表
echo ""
blue "可用的域名列表:"
echo "0. 全部清理 (all)"
for i in "${!DOMAINS[@]}"; do
    echo "   $((i+1)). ${DOMAINS[$i]}"
done

# 用户选择域名
echo ""
echo -n "请选择要清理的域名 (输入数字 0-${#DOMAINS[@]},直接回车默认全部清理): "
read choice

# 处理域名选择
if [[ "$choice" == "0" || "$choice" == "all" || "$choice" == "全部" || -z "$choice" ]]; then
    SELECTED_DOMAINS=("${DOMAINS[@]}")
    if [[ -z "$choice" ]]; then
        green "您选择了:全部清理(默认)"
    else
        green "您选择了:全部清理"
    fi
else
    # 检查输入是否有效
    if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le ${#DOMAINS[@]} ]; then
        index=$((choice-1))
        SELECTED_DOMAINS=("${DOMAINS[$index]}")
        green "您选择了:${DOMAINS[$index]}"
    else
        red "错误:无效的选择!"
        exit 1
    fi
fi

# 清理范围选择
echo ""
blue "请选择清理范围:"
echo "1. 清理发件箱 (cur、tmp 目录)"
echo "2. 清理收件箱 (new、tmp 目录)"
echo "3. 全部清理 (cur、new、tmp 目录)"
echo -n "请输入选择 (直接回车默认3-全部清理): "
read cleanup_scope

# 处理清理范围选择
case "$cleanup_scope" in
    "1")
        FOLDERS=("cur" "tmp")
        SCOPE_NAME="发件箱 (cur、tmp)"
        ;;
    "2")
        FOLDERS=("new" "tmp")
        SCOPE_NAME="收件箱 (new、tmp)"
        ;;
    "3"|"")
        FOLDERS=("cur" "new" "tmp")
        SCOPE_NAME="全部邮箱 (cur、new、tmp)"
        ;;
    *)
        red "错误:无效的清理范围选择!"
        exit 1
        ;;
esac

if [[ -z "$cleanup_scope" ]]; then
    green "您选择了:$SCOPE_NAME(默认)"
else
    green "您选择了:$SCOPE_NAME"
fi

# 询问是否清理索引文件
echo ""
yellow "额外清理选项:"
echo "注意:以下文件是邮件索引文件,如果异常过大可以清理"
echo "      清理后Dovecot会自动重建,但用户可能需要重新登录邮件客户端"
echo -n "是否清理异常大的索引文件 (dovecot.*, maildirsize 等)?(Y/n,直接回车默认清理): "
read clean_index

if [[ "$clean_index" =~ ^[Nn]$ ]]; then
    CLEAN_INDEX=false
    echo "跳过索引文件清理"
else
    CLEAN_INDEX=true
    echo "将同时清理异常索引文件"
fi

# 索引文件清理阈值设置
if [ "$CLEAN_INDEX" = true ]; then
    echo ""
    blue "索引文件清理阈值设置:"
    echo "1. 全部清理 (不管大小)"
    echo "2. 中等模式 (大于50M)"
    echo "3. 宽松模式 (大于100M)"
    echo -n "请选择阈值 (直接回车默认1-全部清理): "
    read threshold_choice

    case "$threshold_choice" in
        "1"|"")
            INDEX_THRESHOLD=0
            THRESHOLD_NAME="全部清理(所有大小)"
            ;;
        "2")
            INDEX_THRESHOLD=52428800  # 50M in bytes
            THRESHOLD_NAME="中等模式(>50M)"
            ;;
        "3")
            INDEX_THRESHOLD=104857600  # 100M in bytes
            THRESHOLD_NAME="宽松模式(>100M)"
            ;;
        *)
            red "错误:无效的阈值选择!使用默认值全部清理"
            INDEX_THRESHOLD=0
            THRESHOLD_NAME="全部清理(所有大小)"
            ;;
    esac
    green "索引清理阈值:$THRESHOLD_NAME"
fi

# 确认操作
echo ""
yellow "========================================"
echo "即将执行以下操作:"
echo "- 清理域名: ${SELECTED_DOMAINS[*]}"
echo "- 清理范围: $SCOPE_NAME"
if [ "$CLEAN_INDEX" = true ]; then
    echo "- 索引清理: 是 ($THRESHOLD_NAME)"
fi
echo ""
red "注意:仅保护 /www/vmail 根目录下的数据库文件"
if [ -n "$ROOT_DB_FILES" ]; then
    echo "受保护的根目录文件:"
    echo "$ROOT_DB_FILES" | while read -r db_file; do
        echo "  🔒 $db_file"
    done
fi
yellow "========================================"
echo -n "确认开始清理吗?(Y/n,直接回车默认确认): "
read confirm

if [[ "$confirm" =~ ^[Nn]$ ]]; then
    yellow "操作已取消"
    exit 0
else
    green "确认执行清理操作..."
fi

# 检查文件是否在根目录的保护列表中
is_root_protected() {
    local file="$1"
    local file_dir=$(dirname "$file")
    
    # 如果文件在 /www/vmail 根目录,检查是否是数据库文件
    if [ "$file_dir" = "$MAIL_BASE" ]; then
        local filename=$(basename "$file")
        case "$filename" in
            *.db|*.sqlite|*.sqlite3|*.db-shm|*.db-wal|*.db-journal)
                return 0  # 受保护
                ;;
        esac
    fi
    return 1  # 不受保护
}

# 清理目录的函数
clean_directory() {
    local dir="$1"
    local cleaned=0
    
    if [ ! -d "$dir" ]; then
        echo 0
        return
    fi
    
    # 统计文件数
    local file_count=$(find "$dir" -type f 2>/dev/null | wc -l)
    
    if [ $file_count -gt 0 ]; then
        # 直接删除所有文件(因为域名目录内不需要保护)
        find "$dir" -type f -delete 2>/dev/null
        cleaned=$file_count
    fi
    
    echo $cleaned
}

# 清理索引文件的函数
clean_index_files() {
    local user_dir="$1"
    local cleaned_count=0
    
    if [ ! -d "$user_dir" ]; then
        return 0
    fi
    
    cd "$user_dir" 2>/dev/null || return 0
    
    # 定义要清理的索引文件
    local index_files=(
        "dovecot-uidlist"
        "dovecot-uidvalidity"
        "dovecot-uidvalidity.*"
        "dovecot.index*"
        "dovecot.mailbox.log"
        "maildirsize"
        "subscriptions"
    )
    
    for pattern in "${index_files[@]}"; do
        # 使用通配符匹配
        for file in $pattern; do
            if [ -f "$file" ]; then
                local file_size=$(stat -c%s "$file" 2>/dev/null || echo 0)
                
                if [ "$INDEX_THRESHOLD" = "0" ] || [ "$file_size" -gt "$INDEX_THRESHOLD" ]; then
                    local original_size=$(ls -lh "$file" | awk '{print $5}')
                    echo "   📁 清理索引: $file (${original_size})"
                    
                    # 特殊处理 uidlist 文件
                    if [[ "$file" == "dovecot-uidlist" ]]; then
                        echo "3" > "$file" 2>/dev/null
                    else
                        truncate -s 0 "$file" 2>/dev/null || > "$file" 2>/dev/null
                    fi
                    
                    cleaned_count=$((cleaned_count + 1))
                fi
            fi
        done
    done
    
    return $cleaned_count
}

# 清理域名的函数
clean_domain() {
    local domain="$1"
    echo ""
    blue "====== 开始清理域名: $domain ======"
    
    local mail_base="/www/vmail/$domain"
    
    if [ ! -d "$mail_base" ]; then
        yellow "域名目录不存在: $mail_base"
        return
    fi
    
    # 获取所有邮件账号
    local mail_users=()
    while IFS= read -r -d '' dir; do
        local user=$(basename "$dir")
        if [ -d "$dir" ] && [ "$user" != "$domain" ]; then
            mail_users+=("$user")
        fi
    done < <(find "$mail_base" -maxdepth 1 -type d -print0 2>/dev/null | sort -z)
    
    if [ ${#mail_users[@]} -eq 0 ]; then
        yellow "在 $domain 下未找到任何邮箱账号"
        return
    fi
    
    local total_cleaned=0
    local total_index_cleaned=0
    local total_accounts=0
    local total_users=${#mail_users[@]}
    local current_user=0
    
    green "该域名下共有 $total_users 个邮箱账号需要处理"
    echo "----------------------------------------"
    
    for user in "${mail_users[@]}"; do
        current_user=$((current_user + 1))
        user_dir="$mail_base/$user"
        
        # 显示进度
        echo -ne "\r[$current_user/$total_users] 处理账号: $user ... "
        
        # 检查目录是否可访问
        if [ ! -d "$user_dir" ] || [ ! -r "$user_dir" ]; then
            yellow "无法访问目录,跳过"
            continue
        fi
        
        local user_cleaned=0
        local user_index_cleaned=0
        
        # 清理邮件文件夹
        for folder in "${FOLDERS[@]}"; do
            target_dir="$user_dir/$folder"
            if [ -d "$target_dir" ] && [ -r "$target_dir" ]; then
                cleaned=$(clean_directory "$target_dir")
                user_cleaned=$((user_cleaned + cleaned))
            fi
        done
        
        # 清理索引文件
        if [ "$CLEAN_INDEX" = true ]; then
            clean_index_files "$user_dir"
            user_index_cleaned=$?
            total_index_cleaned=$((total_index_cleaned + user_index_cleaned))
        fi
        
        if [ $user_cleaned -gt 0 ] || [ $user_index_cleaned -gt 0 ]; then
            echo -e "\r[$current_user/$total_users] ✅ 账号: $user 完成 - 邮件: $user_cleaned, 索引: $user_index_cleaned"
        else
            echo -e "\r[$current_user/$total_users] ○ 账号: $user 无需清理"
        fi
        
        total_cleaned=$((total_cleaned + user_cleaned))
        total_accounts=$((total_accounts + 1))
    done
    
    echo ""
    green "✅ 域名 $domain 清理完成:"
    echo "   - 处理账号: $total_accounts 个"
    [ $total_cleaned -gt 0 ] && echo "   - 清理邮件: $total_cleaned 个文件"
    [ "$CLEAN_INDEX" = true ] && [ $total_index_cleaned -gt 0 ] && echo "   - 清理索引: $total_index_cleaned 个文件"
}

# 格式化时间函数
format_duration() {
    local total_seconds=$1
    local hours=$((total_seconds / 3600))
    local minutes=$(( (total_seconds % 3600) / 60 ))
    local seconds=$((total_seconds % 60))
    
    if [ $hours -gt 0 ]; then
        echo "${hours}小时${minutes}分钟${seconds}秒"
    elif [ $minutes -gt 0 ]; then
        echo "${minutes}分钟${seconds}秒"
    else
        echo "${seconds}秒"
    fi
}

# 主清理流程
echo ""
green "开始清理操作..."
yellow "========================================"

# 停止邮件服务
echo "停止邮件服务..."
MAIL_START_TIME=$(date +%s)

# 检查 bt 命令是否存在
if command -v bt &> /dev/null; then
    bt stop mail
else
    # 尝试直接停止 dovecot 和 postfix
    systemctl stop dovecot 2>/dev/null
    systemctl stop postfix 2>/dev/null
    service dovecot stop 2>/dev/null
    service postfix stop 2>/dev/null
fi

# 等待服务完全停止
sleep 3

# 执行清理
TOTAL_DOMAINS=${#SELECTED_DOMAINS[@]}
CURRENT_DOMAIN=0

for domain in "${SELECTED_DOMAINS[@]}"; do
    CURRENT_DOMAIN=$((CURRENT_DOMAIN + 1))
    echo ""
    yellow ">>> 正在处理域名 [$CURRENT_DOMAIN/$TOTAL_DOMAINS]: $domain"
    DOMAIN_START_TIME=$(date +%s)
    
    clean_domain "$domain"
    
    DOMAIN_END_TIME=$(date +%s)
    DOMAIN_DURATION=$((DOMAIN_END_TIME - DOMAIN_START_TIME))
    green ">>> 域名 $domain 处理耗时: $(format_duration $DOMAIN_DURATION)"
    echo "========================================"
done

# 重启邮件服务
echo ""
echo "重启邮件服务..."
if command -v bt &> /dev/null; then
    bt start mail
else
    systemctl start dovecot 2>/dev/null
    systemctl start postfix 2>/dev/null
    service dovecot start 2>/dev/null
    service postfix start 2>/dev/null
fi
MAIL_END_TIME=$(date +%s)
MAIL_DURATION=$((MAIL_END_TIME - MAIL_START_TIME))

# 清理邮件阶段耗时
CLEAN_END_TIME=$(date +%s)
CLEAN_DURATION=$((CLEAN_END_TIME - START_TIME))

echo ""
green "=== 邮件清理操作完成 ==="
echo "清理范围: $SCOPE_NAME"
echo "处理域名: ${SELECTED_DOMAINS[*]}"
[ "$CLEAN_INDEX" = true ] && echo "索引清理: $THRESHOLD_NAME"
echo "邮件服务停止时间: $(format_duration $MAIL_DURATION)"
echo "邮件清理耗时: $(format_duration $CLEAN_DURATION)"
echo ""

# 询问是否清理系统日志
yellow "========================================"
echo -n "是否安全清理系统日志?可能占用很大 (y/N,直接回车默认不清理): "
read clean_logs

if [[ "$clean_logs" =~ ^[Yy]$ ]]; then
    echo ""
    green "开始清理系统日志..."
    LOG_START_TIME=$(date +%s)
    
    # 清理当前系统日志
    echo "正在清理使用中的系统日志..."
    truncate -s 0 /var/log/syslog 2>/dev/null || true
    truncate -s 0 /var/log/messages 2>/dev/null || true
    truncate -s 0 /var/log/maillog 2>/dev/null || true
    green "✓ 安全清理使用中的日志完成"
    
    # 清理压缩的旧日志文件
    echo "正在清理备份的早期日志..."
    find /var/log -name "*.gz" -o -name "*.bz2" -o -name "*.[0-9]" -delete 2>/dev/null || true
    green "✓ 清理备份的早期日志完成"
    
    # 清理宝塔日志
    if [ -d "/www/server/panel/logs" ]; then
        echo "正在清理宝塔面板日志..."
        find /www/server/panel/logs -name "*.log" -exec truncate -s 0 {} \; 2>/dev/null || true
        green "✓ 清理宝塔面板日志完成"
    fi
    
    LOG_END_TIME=$(date +%s)
    LOG_DURATION=$((LOG_END_TIME - LOG_START_TIME))
    green "系统日志清理完成!耗时: $(format_duration $LOG_DURATION)"
else
    echo "跳过系统日志清理"
fi

# 显示磁盘使用情况
echo ""
yellow "========================================"
echo "当前磁盘使用情况:"
yellow "========================================"
df -h | awk '
NR==1 {
    printf "%-20s %8s %8s %8s %6s %s\n", "文件系统", "容量", "已用", "可用", "已用%", "挂载点"
    print "--------------------------------------------------------------------------------"
}
NR>1 {
    printf "%-20s %8s %8s %8s %6s %s\n", $1, $2, $3, $4, $5, $6
}'

# 显示邮件目录空间
echo ""
yellow "邮件目录空间使用:"
if [ -d "/www/vmail" ]; then
    echo "邮件目录总大小: $(du -sh /www/vmail 2>/dev/null | awk '{print $1}')"
    echo ""
    echo "各域名空间使用情况:"
    du -sh /www/vmail/* 2>/dev/null | sort -hr | head -10
    
    # 显示根目录数据库文件状态(确认没有被清理)
    if [ -n "$ROOT_DB_FILES" ]; then
        echo ""
        green "根目录受保护的数据库文件状态:"
        echo "$ROOT_DB_FILES" | while read -r db_file; do
            if [ -f "$db_file" ]; then
                size=$(ls -lh "$db_file" | awk '{print $5}')
                echo "  ✅ $db_file ($size)"
            fi
        done
    fi
fi

# 计算总耗时
END_TIME=$(date +%s)
TOTAL_DURATION=$((END_TIME - START_TIME))

echo ""
green "========================================"
green "=== 所有操作完成 ==="
echo "总耗时: $(format_duration $TOTAL_DURATION)"
echo "完成时间: $(date '+%Y-%m-%d %H:%M:%S')"
green "========================================"
echo ""
echo "脚本执行完毕,可删除本文件: rm -f btmailclearpro.sh"

清理效果如下,还自带进度显示,有几万个账号的时候,也不怕了

直接全部回车即可

宝塔邮局怎么删除所有邮件不删除账号?

最后还有个,是否清理日志,建议也清理下,可能会清理出大量的空间

宝塔邮局怎么删除所有邮件不删除账号?

第三步 将这个清理功能加入服务器的计划任务(可选,不建议,因此隐藏)

# 创建计划任务专用脚本
cat > /root/mail_cleaner_cron.sh << 'EOF'
#!/bin/bash
echo "=== 邮件文件夹自动清理工具(计划任务版)==="
echo "开始时间: $(date '+%Y-%m-%d %H:%M:%S')"

# 记录开始时间
START_TIME=$(date +%s)

# 查找所有域名
MAIL_BASE="/www/vmail"
DOMAINS=($(find "$MAIL_BASE" -maxdepth 1 -type d -exec basename {} \; | grep -v "^vmail$" | sort))

# 检查是否有域名
if [ ${#DOMAINS[@]} -eq 0 ]; then
echo "错误:在 $MAIL_BASE 下未找到任何域名!"
exit 1
fi

# 自动选择:清理所有域名
SELECTED_DOMAINS=("${DOMAINS[@]}")
echo "自动选择:全部清理(${#DOMAINS[@]}个域名)"

# 自动选择:全部清理范围
FOLDERS=("cur" "new" "tmp")
SCOPE_NAME="全部邮箱 (cur、new、tmp)"
echo "自动选择:$SCOPE_NAME"

# 自动确认执行
echo "自动确认执行清理操作..."

# 清理函数(带进度显示)
clean_domain() {
local domain="$1"
echo ""
echo "====== 开始清理域名: $domain ======"

local mail_base="/www/vmail/$domain"
local mail_users=($(find "$mail_base" -maxdepth 1 -type d -exec basename {} \; | grep -v "^$domain$" | sort))

if [ ${#mail_users[@]} -eq 0 ]; then
echo "在 $domain 下未找到任何邮箱账号"
return
fi

local total_cleaned=0
local total_accounts=0
local total_users=${#mail_users[@]}
local current_user=0

echo "该域名下共有 $total_users 个邮箱账号需要处理"
echo "----------------------------------------"

for user in "${mail_users[@]}"; do
if [ -n "$user" ]; then
current_user=$((current_user + 1))
user_dir="$mail_base/$user"

# 每100个账号显示一次进度(避免日志过多)
if [ $((current_user % 100)) -eq 0 ] || [ $current_user -eq 1 ] || [ $current_user -eq $total_users ]; then
progress=$((current_user * 100 / total_users))
echo "[$current_user/$total_users] 进度: $progress% | 正在处理账号: $user"
fi

local user_cleaned=0

for folder in "${FOLDERS[@]}"; do
target_dir="$user_dir/$folder"
if [ -d "$target_dir" ] && [ "$(ls -A "$target_dir")" ]; then
file_count=$(ls -1 "$target_dir" | wc -l)
# 只在有文件清理时显示详细信息
if [ $file_count -gt 0 ] && [ $((current_user % 100)) -eq 0 ]; then
echo " 清理: $folder/ ($file_count 个文件)"
fi
rm -rf "$target_dir"/*
user_cleaned=$((user_cleaned + file_count))
fi
done

total_cleaned=$((total_cleaned + user_cleaned))
total_accounts=$((total_accounts + 1))

# 每100个账号或最后一个账号显示统计
if [ $((current_user % 100)) -eq 0 ] || [ $current_user -eq $total_users ]; then
if [ $user_cleaned -gt 0 ]; then
echo " ✓ 此批次清理了 $user_cleaned 个文件"
fi
remaining=$((total_users - current_user))
echo " ------------------------------------"
fi
fi
done

echo "✓ 域名 $domain 清理完成: $total_accounts 个账号, 共 $total_cleaned 个文件"
}

# 格式化时间函数
format_duration() {
local total_seconds=$1
if [ $total_seconds -lt 60 ]; then
echo "${total_seconds}秒"
elif [ $total_seconds -lt 3600 ]; then
minutes=$((total_seconds / 60))
seconds=$((total_seconds % 60))
echo "${minutes}分钟${seconds}秒"
else
hours=$((total_seconds / 3600))
minutes=$(( (total_seconds % 3600) / 60 ))
seconds=$((total_seconds % 60))
echo "${hours}小时${minutes}分钟${seconds}秒"
fi
}

# 主清理流程
echo ""
echo "开始清理操作..."
echo "========================================"

# 停止邮件服务
echo "停止邮件服务..."
MAIL_START_TIME=$(date +%s)
if command -v bt >/dev/null 2>&1; then
sudo bt stop mail
else
echo "使用系统服务管理..."
sudo systemctl stop postfix dovecot 2>/dev/null || true
fi

# 执行清理
TOTAL_DOMAINS=${#SELECTED_DOMAINS[@]}
CURRENT_DOMAIN=0
TOTAL_CLEANED_FILES=0
TOTAL_CLEANED_ACCOUNTS=0

for domain in "${SELECTED_DOMAINS[@]}"; do
CURRENT_DOMAIN=$((CURRENT_DOMAIN + 1))
echo ""
echo ">>> 正在处理域名 [$CURRENT_DOMAIN/$TOTAL_DOMAINS]: $domain"
DOMAIN_START_TIME=$(date +%s)

# 临时保存清理结果
DOMAIN_RESULT=$(mktemp)
clean_domain "$domain" > >(tee "$DOMAIN_RESULT")

# 从输出中提取清理的文件数量
domain_files=$(grep "清理完成" "$DOMAIN_RESULT" | tail -1 | grep -o '[0-9]\+' | head -1)
domain_accounts=$(grep "清理完成" "$DOMAIN_RESULT" | tail -1 | grep -o '[0-9]\+' | head -2 | tail -1)

TOTAL_CLEANED_FILES=$((TOTAL_CLEANED_FILES + domain_files))
TOTAL_CLEANED_ACCOUNTS=$((TOTAL_CLEANED_ACCOUNTS + domain_accounts))

rm -f "$DOMAIN_RESULT"

DOMAIN_END_TIME=$(date +%s)
DOMAIN_DURATION=$((DOMAIN_END_TIME - DOMAIN_START_TIME))
echo ">>> 域名 $domain 处理耗时: $(format_duration $DOMAIN_DURATION)"
echo "========================================"
done

# 重启邮件服务
echo ""
echo "重启邮件服务..."
if command -v bt >/dev/null 2>&1; then
sudo bt start mail
else
echo "使用系统服务管理..."
sudo systemctl start postfix dovecot 2>/dev/null || true
fi
MAIL_END_TIME=$(date +%s)
MAIL_DURATION=$((MAIL_END_TIME - MAIL_START_TIME))

# 计算邮件清理阶段耗时
CLEAN_END_TIME=$(date +%s)
CLEAN_DURATION=$((CLEAN_END_TIME - START_TIME))

echo ""
echo "=== 邮件清理操作完成 ==="
echo "清理范围: $SCOPE_NAME"
echo "处理域名: ${SELECTED_DOMAINS[*]}"
echo "总清理账号: $TOTAL_CLEANED_ACCOUNTS 个"
echo "总清理文件: $TOTAL_CLEANED_FILES 个"
echo "邮件清理耗时: $(format_duration $MAIL_DURATION)"
echo "总运行时间: $(format_duration $CLEAN_DURATION)"
echo ""

# 自动清理系统日志(可选,取消注释启用)
# echo "开始自动清理系统日志..."
# LOG_START_TIME=$(date +%s)
# 
# # 清理当前系统日志
# sudo truncate -s 0 /var/log/syslog 2>/dev/null || true
# sudo truncate -s 0 /var/log/messages 2>/dev/null || true
# sudo truncate -s 0 /var/log/maillog 2>/dev/null || true
# 
# # 清理压缩的旧日志文件
# sudo find /var/log -name "*.gz" -o -name "*.bz2" -o -name "*.[0-9]" -exec rm -f {} \; 2>/dev/null || true
# 
# # 清理宝塔日志
# sudo find /www/server/panel/logs -name "*.log" -exec truncate -s 0 {} \; 2>/dev/null || true
# 
# LOG_END_TIME=$(date +%s)
# LOG_DURATION=$((LOG_END_TIME - LOG_START_TIME))
# echo "系统日志清理完成!耗时: $(format_duration $LOG_DURATION)"

# 显示磁盘使用情况
echo ""
echo "========================================"
echo "清理后磁盘使用情况:"
echo "========================================"
df -h | awk '
NR==1 {
print "文件系统 容量 已用 可用 已用% 挂载点"
print "--------------------------------------------"
}
NR>1 {
printf "%-12s %5s %5s %5s %5s %s\n", $1, $2, $3, $4, $5, $6
}'

# 计算总耗时
END_TIME=$(date +%s)
TOTAL_DURATION=$((END_TIME - START_TIME))

echo ""
echo "========================================"
echo "=== 自动清理任务完成 ==="
echo "总耗时: $(format_duration $TOTAL_DURATION)"
echo "完成时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo "========================================"

# 记录到系统日志
logger -t "mail-cleaner" "邮件自动清理完成: 清理了 $TOTAL_CLEANED_ACCOUNTS 个账号, $TOTAL_CLEANED_FILES 个文件, 耗时: $(format_duration $TOTAL_DURATION)"
EOF

# 赋予执行权限
chmod +x /root/mail_cleaner_cron.sh

# 测试执行
/root/mail_cleaner_cron.sh

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。