ubuntu 清理脚本

发布于:2025-07-19 ⋅ 阅读:(12) ⋅ 点赞:(0)

ubuntu 清理

#!/bin/bash

# =============================
# 合并版 Ubuntu 系统清理脚本(带进度和空间统计)
# 包含:
# - Conda 缓存清理(兼容旧版)
# - Pip 缓存清理
# - APT 缓存清理
# - 系统临时文件清理
# - 系统日志清理
# - Docker 垃圾清理
# - 旧内核清理
# - 用户缓存清理
# - 交互式菜单选择
# Date: 2025-07-18
# =============================

# ANSI 颜色代码
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m'

# 日志函数
log() {
    echo -e "${GREEN}[INFO] $1${NC}"
}

warn() {
    echo -e "${YELLOW}[WARN] $1${NC}"
}

error() {
    echo -e "${RED}[ERROR] $1${NC}"
}

progress() {
    echo -e "${BLUE}[PROGRESS] $1${NC}"
}

# 确认函数
confirm() {
    read -p "$1 是否继续?(y/n): " -n 1 -r
    echo
    [[ $REPLY =~ ^[Yy]$ ]]
}

# 清屏函数
clear_screen() {
    clear
}

# 获取目录大小(MB)
get_size() {
    if [ -d "$1" ]; then
        du -sm "$1" 2>/dev/null | awk '{print $1}'
    else
        echo 0
    fi
}

# 获取文件大小(MB)
get_file_size() {
    if [ -e "$1" ]; then
        du -sm "$1" 2>/dev/null | awk '{print $1}'
    else
        echo 0
    fi
}

# 格式化数字为千分位
format_number() {
    echo $1 | awk '{ printf "%\047d\n", $1 }'
}

# 主菜单
main_menu() {
    clear_screen
    echo "=========================================="
    echo "     Ubuntu 系统清理工具"
    echo "=========================================="
    echo "1) 清理 Conda 缓存(兼容旧版)"
    echo "2) 清理 pip 缓存"
    echo "3) 清理 APT 缓存"
    echo "4) 清理系统临时文件(/tmp)"
    echo "5) 清理用户缓存(~/.cache)"
    echo "6) 清理系统日志"
    echo "7) 删除无用依赖"
    echo "8) 删除旧内核(谨慎操作)"
    echo "9) 清理 Docker 垃圾(images, containers, volumes, networks)"
    echo "10) 执行所有清理任务"
    echo "q) 退出"
    echo
    read -p "请选择要执行的操作: " choice
    case $choice in
        1) cleanup_conda ;;
        2) cleanup_pip ;;
        3) cleanup_apt ;;
        4) cleanup_tmp ;;
        5) cleanup_user_cache ;;
        6) cleanup_logs ;;
        7) remove_unused_deps ;;
        8) remove_old_kernels ;;
        9) cleanup_docker ;;
        10) run_all ;;
        q|Q) exit 0 ;;
        *) error "无效选项,请重新选择。"; sleep 2 ;;
    esac
}

# 显示清理前预估空间
show_pre_cleanup_stats() {
    local target="$1"
    
    case "$target" in
        "conda")
            if command -v conda &>/dev/null; then
                local conda_pkgs_size=$(get_size ~/anaconda3/pkgs)
                local conda_cache_size=$(get_size ~/anaconda3/conda-meta/package_cache)
                total_size=$((conda_pkgs_size + conda_cache_size))
                echo "预计可清理 Conda 缓存大小: ${total_size}MB"
            else
                warn "未检测到 Conda"
            fi
            ;;
        "pip")
            if command -v pip &>/dev/null; then
                local pip_cache_size=$(get_size ~/.cache/pip)
                echo "预计可清理 pip 缓存大小: ${pip_cache_size}MB"
            else
                warn "未检测到 pip"
            fi
            ;;
        "apt")
            local apt_cache_size=$(get_size /var/cache/apt/archives)
            echo "预计可清理 APT 缓存大小: ${apt_cache_size}MB"
            ;;
        "tmp")
            local tmp_size=$(get_size /tmp)
            echo "预计可清理 /tmp 文件大小: ${tmp_size}MB"
            ;;
        "user_cache")
            local user_cache_size=$(get_size ~/.cache)
            echo "预计可清理用户缓存大小: ${user_cache_size}MB"
            ;;
        "logs")
            local log_size=$(get_size /var/log)
            echo "预计可清理日志文件大小: ${log_size}MB"
            ;;
        "unused_deps")
            echo "预计可清理无用依赖: 50-200MB(视系统情况而定)"
            ;;
        "old_kernels")
            local old_kernels_size=$(dpkg --list | grep -i linux-image | awk '{ print $2 }' | grep -v "$(uname -r)" | grep -v "generic" | wc -l)
            if [ "$old_kernels_size" -gt 0 ]; then
                echo "检测到 $old_kernels_size 个旧内核(每个约 100-300MB)"
            else
                echo "未检测到旧内核"
            fi
            ;;
        "docker")
            if command -v docker &>/dev/null; then
                local docker_size=$(docker system df | grep "Total" | awk '{print $3}' | sed 's/[A-Za-z]//g')
                echo "预计可清理 Docker 垃圾大小: ${docker_size}MB"
            else
                warn "未检测到 Docker"
            fi
            ;;
        "all")
            show_pre_cleanup_stats "conda"
            show_pre_cleanup_stats "pip"
            show_pre_cleanup_stats "apt"
            show_pre_cleanup_stats "tmp"
            show_pre_cleanup_stats "user_cache"
            show_pre_cleanup_stats "logs"
            show_pre_cleanup_stats "docker"
            show_pre_cleanup_stats "old_kernels"
            ;;
    esac
}

# 清理 Conda 缓存(兼容旧版)
cleanup_conda() {
    log "开始清理 Conda 缓存..."
    if command -v conda &> /dev/null; then
        local before_size=$(($(get_size ~/anaconda3/pkgs) + $(get_size ~/anaconda3/conda-meta/package_cache)))
        
        progress "清理 Conda 缓存(tarball、索引缓存、日志等)..."
        conda clean --tarballs --index-cache --logs -y
        
        progress "清理未安装但缓存的包..."
        if [ -d ~/anaconda3/pkgs ]; then
            find ~/anaconda3/pkgs -type f -name "*.tar.bz2" -delete
        else
            warn "未找到 Conda 的 pkgs 目录"
        fi
        
        local after_size=$(($(get_size ~/anaconda3/pkgs) + $(get_size ~/anaconda3/conda-meta/package_cache)))
        local saved=$((before_size - after_size))
        
        log "Conda 缓存清理完成,共释放空间: ${saved}MB"
        log "列出所有 Conda 环境(你可以手动删除不需要的环境):"
        conda env list
    else
        warn "未检测到 Conda,跳过清理"
    fi
}

# 清理 pip 缓存
cleanup_pip() {
    log "开始清理 pip 缓存..."
    if command -v pip &> /dev/null; then
        local before_size=$(get_size ~/.cache/pip)
        
        progress "清理 pip 缓存..."
        if pip cache purge 2>/dev/null; then
            log "pip 缓存清理完成"
        else
            progress "使用传统方式清理 pip 缓存..."
            pip cache remove --all
        fi
        
        local after_size=$(get_size ~/.cache/pip)
        local saved=$((before_size - after_size))
        
        log "pip 缓存清理完成,共释放空间: ${saved}MB"
    else
        warn "未检测到 pip,跳过清理"
    fi
}

# 清理 APT 缓存
cleanup_apt() {
    log "开始清理 APT 缓存..."
    if confirm "确定要清理 APT 缓存吗?这将删除 /var/cache/apt/archives 中的所有 .deb 文件"; then
        local before_size=$(get_size /var/cache/apt/archives)
        
        sudo apt-get clean
        sudo apt-get autoclean
        
        local after_size=$(get_size /var/cache/apt/archives)
        local saved=$((before_size - after_size))
        
        log "APT 缓存清理完成,共释放空间: ${saved}MB"
    fi
}

# 清理系统临时文件
cleanup_tmp() {
    log "开始清理 /tmp 文件..."
    if confirm "确定要删除 /tmp 中超过 7 天的文件吗?"; then
        local before_size=$(get_size /tmp)
        
        sudo find /tmp -mindepth 1 -mtime +7 -exec rm -rf {} +
        
        local after_size=$(get_size /tmp)
        local saved=$((before_size - after_size))
        
        log "/tmp 文件清理完成,共释放空间: ${saved}MB"
    fi
}

# 清理用户缓存
cleanup_user_cache() {
    log "开始清理用户缓存 ~/.cache ..."
    if confirm "确定要删除 ~/.cache 中超过 7 天的文件吗?"; then
        local before_size=$(get_size ~/.cache)
        
        find ~/.cache -type f -mtime +7 -delete
        
        local after_size=$(get_size ~/.cache)
        local saved=$((before_size - after_size))
        
        log "用户缓存清理完成(保留最近 7 天内的),共释放空间: ${saved}MB"
    fi
}

# 清理系统日志
cleanup_logs() {
    log "开始清理系统日志..."
    if confirm "是否清理 /var/log 中的旧日志文件?"; then
        local before_size=$(get_size /var/log)
        
        sudo journalctl --vacuum-time=7d
        sudo find /var/log -type f -name "*.log.*" -delete 2>/dev/null
        sudo rm -f /var/log/*.gz /var/log/*.old /var/log/*.1 /var/log/syslog.1
        
        local after_size=$(get_size /var/log)
        local saved=$((before_size - after_size))
        
        log "系统日志清理完成,共释放空间: ${saved}MB"
    fi
}

# 删除无用依赖
remove_unused_deps() {
    log "开始删除无用依赖..."
    if confirm "确定要删除无用依赖吗?"; then
        local before_size=50  # 估计值
        
        sudo apt-get autoremove --yes
        
        log "无用依赖清理完成,预计释放空间: 50-200MB"
    fi
}

# 删除旧内核
remove_old_kernels() {
    log "开始查找可以删除的旧内核..."

    # 获取当前运行的内核版本
    current_kernel=$(uname -r)

    # 列出所有已安装的内核包
    old_kernels=$(dpkg --list | grep -i linux-image | awk '{ print $2 }' | grep -v "$current_kernel" | grep -v "generic")

    if [ -z "$old_kernels" ]; then
        warn "没有发现可删除的旧内核。"
        return
    fi

    echo "以下内核将被删除:"
    echo "$old_kernels"

    if confirm "是否继续删除这些旧内核?请确保保留至少一个备用内核"; then
        local before_count=$(echo "$old_kernels" | wc -l)
        local estimated_saved=$((before_count * 200))
        
        log "预计将删除 $before_count 个旧内核,共释放空间: ${estimated_saved}MB"
        log "正在进行内核清理,请稍候..."
        
        sudo apt purge $old_kernels
        sudo apt autoremove --purge
        
        log "旧内核清理完成,预计释放空间: ${estimated_saved}MB"
    fi
}

# 清理 Docker 垃圾
cleanup_docker() {
    log "开始清理 Docker 垃圾..."
    if command -v docker &>/dev/null; then
        local docker_size=$(docker system df | grep "Total" | awk '{print $3}' | sed 's/[A-Za-z]//g')
        
        if confirm "是否删除无用的 Docker 镜像、容器、卷和网络?"; then
            log "预计清理 Docker 垃圾大小: ${docker_size}MB"
            log "正在进行 Docker 垃圾清理,请稍候..."
            
            docker system prune -af
            docker volume prune -f
            
            log "Docker 垃圾清理完成"
        fi
    else
        warn "未检测到 Docker,跳过该步骤"
    fi
}

# 执行所有清理任务
run_all() {
    log "开始执行全部清理任务..."
    
    # 显示预估清理空间
    log "📊 预计清理空间概览:"
    show_pre_cleanup_stats "all"
    echo
    
    if confirm "是否继续执行全部清理任务?"; then
        cleanup_conda
        cleanup_pip
        cleanup_apt
        cleanup_tmp
        cleanup_user_cache
        cleanup_logs
        cleanup_docker
        remove_unused_deps
        
        if confirm "是否也要清理旧内核?(谨慎操作)"; then
            remove_old_kernels
        fi
        
        log "所有清理任务已完成。建议重启系统以释放更多空间(特别是删除旧内核后)。"
    fi
}

# 主程序入口
while true; do
    main_menu
done

网站公告

今日签到

点亮在社区的每一天
去签到