宝塔邮局磁盘满了怎么清理?linux磁盘清理教程

我们使用宝塔邮局,有时候磁盘满了,无法使用,特别是smtp无法发送邮件

这时候需要清理服务器的磁盘才能正常使用那么怎么清理服务器磁盘呢?本教程来介绍这个清理问题。

1、连上服务器的ssh

2、清理日志文件

a 清理正在使用日志(此命令不是删除,是清理,删除会导致服务器崩溃,可以直接执行本命令)

bash 复制代码
sudo truncate -s 0 /var/log/syslog

b 删除以前自动日志的自动备份文件

bash 复制代码
sudo find /var/log -name "*.gz" -o -name "*.bz2" -o -name "*.[0-9]" -exec rm -f {} \;

3、宝塔邮局邮件清理

本脚本只清理邮件,不删除账户

bash 复制代码
# 创建脚本文件
cat > /root/mail_cleaner.sh << 'EOF'
#!/bin/bash
echo "=== 邮件文件夹清理工具(交互版)==="

# 记录开始时间
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

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

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

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

# 清理范围选择
echo ""
echo "请选择清理范围:"
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)"
;;
*)
echo "错误:无效的清理范围选择!"
exit 1
;;
esac

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

# 确认操作(直接回车默认为y)
echo ""
echo "========================================"
echo "即将执行以下操作:"
echo "- 清理域名: ${SELECTED_DOMAINS[*]}"
echo "- 清理范围: $SCOPE_NAME"
echo "========================================"
echo -n "确认开始清理吗?(Y/n,直接回车默认确认): "
read confirm

# 处理确认选择(直接回车、y、Y 都确认为继续)
if [[ "$confirm" =~ ^[Nn]$ ]]; then
echo "操作已取消"
exit 0
else
echo "确认执行清理操作..."
fi

# 清理函数(带进度显示)
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"

# 显示进度
echo "[$current_user/$total_users] 处理账号: $user"

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)
echo " 清理: $folder/ ($file_count 个文件)"
rm -rf "$target_dir"/*
user_cleaned=$((user_cleaned + file_count))
fi
done

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

if [ $user_cleaned -gt 0 ]; then
echo " ✓ 此账号清理了 $user_cleaned 个文件"
else
echo " ○ 此账号无需清理"
fi

# 显示剩余账号和进度百分比
remaining=$((total_users - current_user))
progress=$((current_user * 100 / total_users))
echo " 进度: $progress% | 剩余: $remaining 个账号"
echo " ------------------------------------"
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)
sudo bt stop mail

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

for domain in "${SELECTED_DOMAINS[@]}"; do
CURRENT_DOMAIN=$((CURRENT_DOMAIN + 1))
echo ""
echo ">>> 正在处理域名 [$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))
echo ">>> 域名 $domain 处理耗时: $(format_duration $DOMAIN_DURATION)"
echo "========================================"
done

# 重启邮件服务
echo ""
echo "重启邮件服务..."
sudo bt start mail
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 "邮件清理耗时: $(format_duration $MAIL_DURATION)"
echo "总运行时间: $(format_duration $CLEAN_DURATION)"
echo ""

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

if [[ "$clean_logs" =~ ^[Yy]$ ]]; then
echo ""
echo "开始清理系统日志..."
LOG_START_TIME=$(date +%s)

# 清理当前系统日志
echo "正在清理使用中的系统日志..."
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
echo "✓ 安全清理使用中的日志完成"

# 清理压缩的旧日志文件
echo "正在清理备份的早期日志..."
sudo find /var/log -name "*.gz" -o -name "*.bz2" -o -name "*.[0-9]" -exec rm -f {} \; 2>/dev/null || true
echo "✓ 清理备份的早期日志完成"

# 清理宝塔日志
echo "正在清理宝塔面板日志..."
sudo find /www/server/panel/logs -name "*.log" -exec truncate -s 0 {} \; 2>/dev/null || true
echo "✓ 清理宝塔面板日志完成"

LOG_END_TIME=$(date +%s)
LOG_DURATION=$((LOG_END_TIME - LOG_START_TIME))
echo "系统日志清理完成!耗时: $(format_duration $LOG_DURATION)"
else
echo "跳过系统日志清理"
fi

# 显示磁盘使用情况
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 "========================================"
EOF

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

# 执行脚本
/root/mail_cleaner.sh

邮局清理高级版

大部分情况,账号的文件夹下,还有大量的索引文件,邮件都删了,这些索引文件也没啥用了,这个命令可以连着索引一起清理了

bash 复制代码
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

下面是原始代码供参考

bash 复制代码
#!/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"
相关推荐
芝士雪豹只抽瑞克五1 小时前
HAProxy 七层负载均衡器笔记
运维·笔记·负载均衡
Purgatory0011 小时前
CSS 访问服务器
服务器·前端·css
觅特科技-互站1 小时前
告别手动微调Prompt:DevOps用陌讯Skills重构AI运维工作流
运维·prompt·线性回归·kmeans·devops
科技块儿1 小时前
开发者需要为网站或应用集成IP归属地显示功能,如何选择可靠的数据源?
服务器·网络·数据库·tcp/ip·edge·ip
天空属于哈夫克32 小时前
基于 Webhook 的企业微信外部群自动化推送集成
运维·自动化·企业微信
茶乡浪子2 小时前
实战H3C单环RRPP应用配置
运维·服务器·网络
TG_yunshuguoji2 小时前
阿里云代理商:2026 年阿里云国际站上云接入指南
服务器·阿里云·云计算
上海合宙LuatOS2 小时前
LuatOS核心库API——【iperf 】吞吐量测试
linux·运维·服务器·单片机·嵌入式硬件·物联网·硬件工程
乂爻yiyao2 小时前
Minecraft 服务端 JVM 调优指南(低资源 / 非专用服务器专用)
运维·服务器·jvm