Linux磁盘挂载助手:一键管理磁盘分区与挂载

简介

Linux磁盘挂载助手是一款功能强大的跨平台磁盘管理工具,支持Debian、Ubuntu、CentOS、RHEL、Rocky Linux、AlmaLinux、Arch Linux、Manjaro、openSUSE等主流Linux发行版。无论您是Linux新手还是资深管理员,这个脚本都能简化磁盘管理流程,提供安全、直观的操作界面。

主要功能

  • 全自动磁盘检测 - 智能识别系统所有磁盘和分区
  • 多种文件系统支持 - ext4、xfs、ext3、btrfs、NTFS、FAT32
  • 分区表管理 - 支持GPT和MBR分区表
  • 一键挂载/卸载 - 简化挂载流程,自动配置fstab
  • 分区管理 - 创建、格式化、删除分区
  • 安全保护 - 避免误操作系统关键分区
  • 跨平台兼容 - 自动适配不同发行版的包管理器

快速开始

1. 下载并运行脚本

# 方法一:直接运行(推荐一键运行)
bash <(curl -s http://disk.6wd.cn/mount-disk.sh)

# 方法二:下载后运行
curl -s http://disk.6wd.cn/mount-disk.sh -o mount.sh
sudo bash mount.sh

2. 主菜单界面

运行脚本后,您将看到清晰的图形化界面:

#!/bin/bash

# 磁盘挂载助手 - 跨平台版 v6.1
# 支持:Debian/Ubuntu/CentOS/RHEL/Rocky/Alma/Arch/Manjaro/openSUSE
# 支持:GPT/MBR分区表,多种文件系统,自动包管理检测
# 新增:删除分区/分区表功能
# 使用方法: curl -s https://your-domain.com/mount-universal.sh | sudo bash

set -e

# 颜色定义
if command -v tput > /dev/null 2>&1; then
    RED=$(tput setaf 1)
    GREEN=$(tput setaf 2)
    YELLOW=$(tput setaf 3)
    BLUE=$(tput setaf 4)
    PURPLE=$(tput setaf 5)
    CYAN=$(tput setaf 6)
    WHITE=$(tput setaf 7)
    BOLD=$(tput bold)
    RESET=$(tput sgr0)
else
    RED='\033[0;31m'
    GREEN='\033[0;32m'
    YELLOW='\033[1;33m'
    BLUE='\033[0;34m'
    PURPLE='\033[0;35m'
    CYAN='\033[0;36m'
    WHITE='\033[1;37m'
    BOLD='\033[1m'
    RESET='\033[0m'
fi

# 全局变量
FORMAT_RESULT=""
PKG_MANAGER=""
PARTED_AVAILABLE=false
FDISK_AVAILABLE=false
PARTITION_TOOL=""
GPT_SUPPORT=true
MBR_SUPPORT=true
SYS_INFO=""
CONTAINER_ENV=false
RESTART_SCRIPT=false  # 新增:标记是否需要重启脚本

# 系统兼容性检查
check_system_compatibility() {
    echo -e "${CYAN}${BOLD}系统兼容性检查...${RESET}"
    echo ""
  
    # 检查操作系统
    if [ -f /etc/os-release ]; then
        . /etc/os-release
        SYS_INFO="$PRETTY_NAME"
        echo -e "  ${WHITE}系统:${RESET} $PRETTY_NAME"
    elif [ -f /etc/redhat-release ]; then
        SYS_INFO=$(cat /etc/redhat-release)
        echo -e "  ${WHITE}系统:${RESET} $SYS_INFO"
    elif [ -f /etc/arch-release ]; then
        SYS_INFO="Arch Linux"
        echo -e "  ${WHITE}系统:${RESET} Arch Linux"
    else
        SYS_INFO="Unknown Linux"
        echo -e "  ${WHITE}系统:${RESET} 未知Linux发行版"
    fi
  
    # 检查内核
    echo -e "  ${WHITE}内核:${RESET} $(uname -r)"
  
    # 检查架构
    local arch=$(uname -m)
    echo -e "  ${WHITE}架构:${RESET} $arch"
  
    # 检查是否在容器中
    if [ -f /.dockerenv ] || grep -q docker /proc/1/cgroup 2>/dev/null || grep -q kubepods /proc/1/cgroup 2>/dev/null; then
        CONTAINER_ENV=true
        echo -e "  ${WHITE}环境:${RESET} ${YELLOW}容器环境${RESET}"
    else
        echo -e "  ${WHITE}环境:${RESET} 物理机/虚拟机"
    fi
  
    # 检查可用工具
    if command -v parted > /dev/null 2>&1; then
        PARTED_AVAILABLE=true
        PARTITION_TOOL="parted"
        echo -e "  ${WHITE}分区工具:${RESET} ${GREEN}parted${RESET} (支持GPT/MBR)"
    fi
  
    if command -v fdisk > /dev/null 2>&1; then
        FDISK_AVAILABLE=true
        if [ -z "$PARTITION_TOOL" ]; then
            PARTITION_TOOL="fdisk"
        fi
        echo -e "  ${WHITE}分区工具:${RESET} ${GREEN}fdisk${RESET} (主要MBR,新版支持GPT)"
    fi
  
    if [ -z "$PARTITION_TOOL" ]; then
        echo -e "  ${WHITE}分区工具:${RESET} ${RED}未找到${RESET}"
    fi
  
    # 检查包管理器
    detect_package_manager
    echo -e "  ${WHITE}包管理器:${RESET} ${CYAN}$PKG_MANAGER${RESET}"
  
    echo ""
  
    # 检查是否支持GPT
    local kernel_version=$(uname -r | cut -d. -f1-2)
    if [ "$(echo "$kernel_version >= 2.6" | bc 2>/dev/null || echo 0)" -eq 1 ] || [ "$(echo "$kernel_version" | awk -F. '{print $1$2}')" -ge 26 ]; then
        GPT_SUPPORT=true
    else
        GPT_SUPPORT=false
        echo -e "${YELLOW}[!]${RESET} 内核版本较旧,可能不支持GPT分区表"
    fi
  
    # 最低要求检查
    if ! command -v lsblk > /dev/null 2>&1; then
        echo -e "${RED}[✗]${RESET} 缺少必要工具: lsblk"
        exit 1
    fi
  
    if ! command -v blkid > /dev/null 2>&1; then
        echo -e "${RED}[✗]${RESET} 缺少必要工具: blkid"
        exit 1
    fi
  
    echo -e "${GREEN}[✓]${RESET} 系统兼容性检查通过"
    echo ""
}

# 检测包管理器
detect_package_manager() {
    if command -v apt > /dev/null 2>&1; then
        PKG_MANAGER="apt"
    elif command -v apt-get > /dev/null 2>&1; then
        PKG_MANAGER="apt-get"
    elif command -v yum > /dev/null 2>&1; then
        PKG_MANAGER="yum"
    elif command -v dnf > /dev/null 2>&1; then
        PKG_MANAGER="dnf"
    elif command -v pacman > /dev/null 2>&1; then
        PKG_MANAGER="pacman"
    elif command -v zypper > /dev/null 2>&1; then
        PKG_MANAGER="zypper"
    elif command -v emerge > /dev/null 2>&1; then
        PKG_MANAGER="emerge"
    elif command -v apk > /dev/null 2>&1; then
        PKG_MANAGER="apk"
    else
        PKG_MANAGER="unknown"
    fi
}

# 通用安装包函数
install_package() {
    local package=$1
    local description=${2:-$package}
  
    if command -v "$package" > /dev/null 2>&1; then
        return 0
    fi
  
    echo -e "${YELLOW}[!]${RESET} 正在安装 $description..."
  
    case $PKG_MANAGER in
        apt|apt-get)
            $PKG_MANAGER update > /dev/null 2>&1
            $PKG_MANAGER install -y "$package" > /dev/null 2>&1
            ;;
        yum|dnf)
            $PKG_MANAGER install -y "$package" > /dev/null 2>&1
            ;;
        pacman)
            pacman -S --noconfirm "$package" > /dev/null 2>&1
            ;;
        zypper)
            zypper install -y "$package" > /dev/null 2>&1
            ;;
        emerge)
            emerge --quiet "$package" > /dev/null 2>&1
            ;;
        apk)
            apk add --quiet "$package" > /dev/null 2>&1
            ;;
        *)
            echo -e "${RED}[✗]${RESET} 无法自动安装 $package,请手动安装"
            return 1
            ;;
    esac
  
    if [ $? -eq 0 ]; then
        echo -e "${GREEN}[✓]${RESET} $description 安装成功"
        return 0
    else
        echo -e "${RED}[✗]${RESET} $description 安装失败"
        return 1
    fi
}

# 检查root权限
check_root() {
    if [[ $EUID -ne 0 ]]; then
        echo -e "${RED}╔══════════════════════════════════════════╗${RESET}"
        echo -e "${RED}║          权限错误                        ║${RESET}"
        echo -e "${RED}╠══════════════════════════════════════════╣${RESET}"
        echo -e "${RED}║ 此脚本需要root权限运行                  ║${RESET}"
        echo -e "${RED}║                                          ║${RESET}"
        echo -e "${RED}║ 请使用: ${GREEN}sudo bash \$0${RED}                  ║${RESET}"
        echo -e "${RED}╚══════════════════════════════════════════╝${RESET}"
        exit 1
    fi
}

# 显示系统信息
show_system_info() {
    clear
    echo -e "${PURPLE}╔══════════════════════════════════════════════════════════════╗${RESET}"
    echo -e "${PURPLE}║             磁盘挂载助手 - 跨平台版 v6.1                    ║${RESET}"
    echo -e "${PURPLE}║  支持:挂载 / 卸载 / 格式化 / 删除分区 / 删除分区表        ║${RESET}"
    echo -e "${PURPLE}║  兼容:Debian/Ubuntu/CentOS/RHEL/Arch/openSUSE等主流发行版  ║${RESET}"
    echo -e "${PURPLE}╚══════════════════════════════════════════════════════════════╝${RESET}"
    echo ""
  
    echo -e "${CYAN}${BOLD}系统信息:${RESET}"
    echo -e "  ${WHITE}系统:${RESET} $SYS_INFO"
    echo -e "  ${WHITE}内核:${RESET} $(uname -r)"
    echo -e "  ${WHITE}主机:${RESET} $(hostname)"
    echo ""
}

# 获取磁盘状态
get_disk_status() {
    local disk=$1
    local disk_path="/dev/$disk"
  
    local disk_mount=$(lsblk -d -n -o MOUNTPOINT "$disk_path" 2>/dev/null | xargs)
    local partitions=$(lsblk -l -n -o NAME,MOUNTPOINT | grep "^${disk}[0-9]" | awk '{print $2}' | xargs)
  
    if [ -n "$disk_mount" ]; then
        echo "disk_mounted"
    elif [ -z "$partitions" ]; then
        echo "no_mounts"
    else
        local all_mounted=true
        local some_mounted=false
      
        while IFS= read -r line; do
            local part_mount=$(echo "$line" | awk '{print $2}' | xargs)
            if [ -n "$part_mount" ]; then
                some_mounted=true
            else
                all_mounted=false
            fi
        done <<< "$(lsblk -l -n -o NAME,MOUNTPOINT | grep "^${disk}[0-9]")"
      
        if $all_mounted && $some_mounted; then
            echo "all_partitions_mounted"
        elif $some_mounted; then
            echo "some_partitions_mounted"
        else
            echo "no_mounts"
        fi
    fi
}

# 显示磁盘状态颜色
get_disk_status_color() {
    local status=$1
    case $status in
        "disk_mounted")
            echo "${GREEN}磁盘已挂载${RESET}"
            ;;
        "all_partitions_mounted")
            echo "${GREEN}全部分区已挂载${RESET}"
            ;;
        "some_partitions_mounted")
            echo "${YELLOW}部分分区已挂载${RESET}"
            ;;
        "no_mounts")
            echo "${RED}未挂载${RESET}"
            ;;
        *)
            echo "${RED}未知${RESET}"
            ;;
    esac
}

# 显示磁盘信息
show_disk_info() {
    echo -e "${CYAN}${BOLD}系统磁盘状态:${RESET}"
    echo ""
  
    echo -e "${BLUE}┌─────────────────────────────────────────────────────────────┐${RESET}"
    printf "${BLUE}│%-12s │ %-8s │ %-10s │ %-20s│${RESET}\n" "设备" "容量" "类型" "状态"
    echo -e "${BLUE}├─────────────────────────────────────────────────────────────┤${RESET}"
  
    local disks=$(lsblk -d -n -o NAME | grep -vE '^loop|^sr' | sort)
  
    for disk in $disks; do
        local disk_path="/dev/$disk"
        local size=$(lsblk -d -n -o SIZE "$disk_path" | xargs)
        local status=$(get_disk_status "$disk")
        local status_display=$(get_disk_status_color "$status")
      
        printf "│${GREEN}%-12s${RESET}│${CYAN}%9s${RESET}│${WHITE}%11s${RESET}│ %-20s│\n" \
            "$disk_path" "$size" "disk" "$status_display"
      
        local partitions=$(lsblk -l -n -o NAME,SIZE,FSTYPE,MOUNTPOINT | grep "^${disk}[0-9]" | sort)
      
        if [ -n "$partitions" ]; then
            while IFS= read -r part_line; do
                local part_name=$(echo "$part_line" | awk '{print $1}')
                local part_size=$(echo "$part_line" | awk '{print $2}' | xargs)
                local part_fstype=$(echo "$part_line" | awk '{print $3}' | xargs)
                local part_mount=$(echo "$part_line" | awk '{print $4}' | xargs)
                local part_path="/dev/$part_name"
              
                if [ -n "$part_mount" ]; then
                    printf "│  ${YELLOW}└─%-10s${RESET}│${CYAN}%9s${RESET}│${WHITE}%11s${RESET}│ ${GREEN}%-20s${RESET}│\n" \
                        "$part_path" "$part_size" "part" "$part_mount"
                else
                    if [ -n "$part_fstype" ] && [ "$part_fstype" != "swap" ]; then
                        printf "│  ${YELLOW}└─%-10s${RESET}│${CYAN}%9s${RESET}│${WHITE}%11s${RESET}│ ${YELLOW}%-20s${RESET}│\n" \
                            "$part_path" "$part_size" "part" "可挂载"
                    else
                        printf "│  ${YELLOW}└─%-10s${RESET}│${CYAN}%9s${RESET}│${WHITE}%11s${RESET}│ %-20s│\n" \
                            "$part_path" "$part_size" "part" "-"
                    fi
                fi
            done <<< "$partitions"
            echo -e "${BLUE}├─────────────────────────────────────────────────────────────┤${RESET}"
        fi
    done
    echo -e "${BLUE}└─────────────────────────────────────────────────────────────┘${RESET}"
    echo ""
}

# 显示可用的挂载设备列表
show_available_mount_devices() {
    echo -e "${CYAN}${BOLD}可挂载的设备列表:${RESET}"
    echo ""
  
    local index=1
    declare -gA device_map
    device_map=()
  
    while IFS= read -r line; do
        local fields=($line)
        local name="${fields[0]}"
        local type="${fields[1]}"
        local size="${fields[2]}"
        local fstype="${fields[3]}"
        local mountpoint="${fields[4]}"
      
        if [ "$type" = "part" ] && [ "$fstype" != "swap" ] && [ -z "$mountpoint" ] && [ -b "/dev/$name" ]; then
            device_map[$index]="/dev/$name"
          
            if [ -z "$fstype" ] || [ "$fstype" = "" ]; then
                fstype_display="${RED}无文件系统${RESET}"
            else
                fstype_display="${YELLOW}$fstype${RESET}"
            fi
          
            printf "  ${GREEN}%2d${RESET}) ${BLUE}%-12s${RESET} ${CYAN}%8s${RESET} %s\n" \
                "$index" "/dev/$name" "$size" "$fstype_display"
            index=$((index+1))
        fi
    done < <(lsblk -l -n -o NAME,TYPE,SIZE,FSTYPE,MOUNTPOINT | sort -V)
  
    # 显示未分区的磁盘
    while IFS= read -r line; do
        local fields=($line)
        local disk="${fields[0]}"
        local type="${fields[1]}"
        local size="${fields[2]}"
      
        if [ "$type" = "disk" ] && [ -b "/dev/$disk" ]; then
            local has_partitions=$(lsblk -l -n -o NAME,TYPE | grep "^${disk}[0-9]" | grep -c "part")
          
            if [ "$has_partitions" -eq 0 ]; then
                device_map[$index]="/dev/$disk"
                printf "  ${GREEN}%2d${RESET}) ${BLUE}%-12s${RESET} ${CYAN}%8s${RESET} ${RED}未分区${RESET}\n" \
                    "$index" "/dev/$disk" "$size"
                index=$((index+1))
            fi
        fi
    done < <(lsblk -d -n -o NAME,TYPE,SIZE | grep -vE '^loop|^sr' | sort -V)
  
    if [ $index -eq 1 ]; then
        echo -e "  ${YELLOW}没有找到可挂载的设备${RESET}"
        echo ""
        return 1
    fi
  
    echo ""
    return 0
}

# 显示已挂载的设备列表
show_mounted_devices() {
    echo -e "${CYAN}${BOLD}已挂载的设备列表:${RESET}"
    echo ""
  
    local index=1
    declare -gA mounted_device_map
    mounted_device_map=()
  
    while IFS= read -r line; do
        local fields=($line)
        local name="${fields[0]}"
        local type="${fields[1]}"
        local size="${fields[2]}"
        local fstype="${fields[3]}"
        local mountpoint="${fields[4]}"
      
        if [ "$type" = "part" ] && [ "$fstype" != "swap" ] && [ -n "$mountpoint" ] && [ "$mountpoint" != "/" ] && [ -b "/dev/$name" ]; then
            mounted_device_map[$index]="/dev/$name|$mountpoint"
          
            printf "  ${GREEN}%2d${RESET}) ${BLUE}%-12s${RESET} ${CYAN}%8s${RESET} ${YELLOW}挂载点: $mountpoint${RESET}\n" \
                "$index" "/dev/$name" "$size"
            index=$((index+1))
        fi
    done < <(lsblk -l -n -o NAME,TYPE,SIZE,FSTYPE,MOUNTPOINT | sort -V)
  
    if [ $index -eq 1 ]; then
        echo -e "  ${YELLOW}没有找到已挂载的可卸载设备${RESET}"
        echo ""
        return 1
    fi
  
    echo ""
    return 0
}

# 显示所有分区列表(用于删除操作)- 过滤系统关键分区
show_all_partitions_for_deletion() {
    echo -e "${CYAN}${BOLD}所有分区列表(不包括系统关键分区):${RESET}"
    echo ""
  
    local index=1
    declare -gA all_partition_map
    all_partition_map=()
  
    while IFS= read -r line; do
        local fields=($line)
        local name="${fields[0]}"
        local type="${fields[1]}"
        local size="${fields[2]}"
        local fstype="${fields[3]}"
        local mountpoint="${fields[4]}"
      
        if [ "$type" = "part" ] && [ -b "/dev/$name" ]; then
            # 过滤系统关键分区
            if [ "$mountpoint" = "/" ] || [ "$mountpoint" = "/boot" ] || [ "$fstype" = "swap" ]; then
                continue  # 跳过根分区、引导分区和swap分区
            fi
          
            all_partition_map[$index]="/dev/$name|$fstype|$mountpoint|$size"
          
            local mount_display=""
            if [ -n "$mountpoint" ]; then
                mount_display="${GREEN}已挂载: $mountpoint${RESET}"
            else
                mount_display="${YELLOW}未挂载${RESET}"
            fi
          
            if [ -z "$fstype" ] || [ "$fstype" = "" ]; then
                fstype_display="${RED}无文件系统${RESET}"
            else
                fstype_display="${YELLOW}$fstype${RESET}"
            fi
          
            printf "  ${GREEN}%2d${RESET}) ${BLUE}%-12s${RESET} ${CYAN}%8s${RESET} ${YELLOW}%-10s${RESET} %s\n" \
                "$index" "/dev/$name" "$size" "$fstype_display" "$mount_display"
            index=$((index+1))
        fi
    done < <(lsblk -l -n -o NAME,TYPE,SIZE,FSTYPE,MOUNTPOINT | sort -V)
  
    if [ $index -eq 1 ]; then
        echo -e "  ${YELLOW}没有找到可安全删除的分区${RESET}"
        echo -e "  ${YELLOW}(系统关键分区已自动隐藏)${RESET}"
        echo ""
        return 1
    fi
  
    echo ""
    return 0
}

# 显示所有磁盘列表(用于删除分区表)
show_all_disks_for_deletion() {
    echo -e "${CYAN}${BOLD}所有磁盘列表:${RESET}"
    echo ""
  
    local index=1
    declare -gA all_disk_map
    all_disk_map=()
  
    while IFS= read -r line; do
        local fields=($line)
        local disk="${fields[0]}"
        local type="${fields[1]}"
        local size="${fields[2]}"
      
        if [ "$type" = "disk" ] && [ -b "/dev/$disk" ]; then
            all_disk_map[$index]="/dev/$disk"
          
            # 获取分区数量
            local partition_count=$(lsblk -l -n -o NAME,TYPE | grep "^${disk}[0-9]" | grep -c "part")
          
            printf "  ${GREEN}%2d${RESET}) ${BLUE}%-12s${RESET} ${CYAN}%8s${RESET} ${YELLOW}%d个分区${RESET}\n" \
                "$index" "/dev/$disk" "$size" "$partition_count"
            index=$((index+1))
        fi
    done < <(lsblk -d -n -o NAME,TYPE,SIZE | grep -vE '^loop|^sr' | sort -V)
  
    if [ $index -eq 1 ]; then
        echo -e "  ${YELLOW}没有找到磁盘${RESET}"
        echo ""
        return 1
    fi
  
    echo ""
    return 0
}

# 简单的进度显示
simple_progress() {
    local seconds=$1
    local message=$2
  
    echo -ne "${BLUE}[INFO]${RESET} $message "
    for ((i=0; i<seconds; i++)); do
        echo -n "."
        sleep 1
    done
    echo -e " ${GREEN}完成${RESET}"
}

# 选择分区表类型
choose_partition_table() {
    echo -e "${CYAN}${BOLD}选择分区表类型:${RESET}"
    echo ""
    echo -e "  ${GREEN}1${RESET}) GPT (推荐,支持2TB以上磁盘,最多128个分区)"
    echo -e "  ${GREEN}2${RESET}) MBR (兼容性好,支持最多4个主分区)"
    echo ""
  
    while true; do
        read -p "请选择分区表类型 1. GPT(推荐)2. MBR(兼容性好)(默认: 1): " pt_choice
        pt_choice=${pt_choice:-1}
      
        if [[ "$pt_choice" == "1" ]]; then
            echo "gpt"
            return 0
        elif [[ "$pt_choice" == "2" ]]; then
            echo "mbr"
            return 0
        else
            echo -e "${RED}[✗]${RESET} 无效选择,请输入 1 或 2"
        fi
    done
}

# 创建分区(支持多种工具和分区表)
create_partition() {
    local device=$1
    local partition_table=$2
  
    echo -e "${BLUE}[INFO]${RESET} 正在为 $device 创建分区..."
  
    # 确保分区工具可用
    if [ "$PARTITION_TOOL" = "parted" ]; then
        if ! install_package "parted" "parted分区工具"; then
            echo -e "${RED}[✗]${RESET} 无法安装parted,尝试使用fdisk"
            PARTITION_TOOL="fdisk"
        fi
    fi
  
    if [ "$PARTITION_TOOL" = "fdisk" ]; then
        if ! install_package "fdisk" "fdisk分区工具"; then
            echo -e "${RED}[✗]${RESET} 无法安装fdisk"
            return 1
        fi
    fi
  
    if [ "$PARTITION_TOOL" = "parted" ]; then
        # 使用parted创建分区
        if [ "$partition_table" = "gpt" ]; then
            parted -s "$device" mklabel gpt > /dev/null 2>&1
            parted -s "$device" mkpart primary 0% 100% > /dev/null 2>&1
        else
            parted -s "$device" mklabel msdos > /dev/null 2>&1
            parted -s "$device" mkpart primary 0% 100% > /dev/null 2>&1
        fi
    elif [ "$PARTITION_TOOL" = "fdisk" ]; then
        # 使用fdisk创建分区
        if [ "$partition_table" = "gpt" ]; then
            echo -e "g\nn\n\n\n\n\nw\n" | fdisk "$device" > /dev/null 2>&1
        else
            echo -e "o\nn\n\n\n\n\nw\n" | fdisk "$device" > /dev/null 2>&1
        fi
    fi
  
    # 刷新分区表
    sleep 2
    if command -v partprobe > /dev/null 2>&1; then
        partprobe "$device" > /dev/null 2>&1
    elif command -v udevadm > /dev/null 2>&1; then
        udevadm settle > /dev/null 2>&1
    fi
  
    sleep 2
  
    # 查找新分区
    local new_partition=""
    for i in {1..5}; do
        if [ -b "${device}1" ]; then
            new_partition="${device}1"
            break
        elif [ -b "${device}p1" ]; then
            new_partition="${device}p1"
            break
        fi
        sleep 1
    done
  
    if [ -n "$new_partition" ] && [ -b "$new_partition" ]; then
        echo "$new_partition"
        return 0
    fi
  
    return 1
}

# 扩展版格式化菜单
show_format_menu() {
    local partition=$1
    local has_fs=$2
  
    FORMAT_RESULT=""
  
    if [ "$has_fs" = "true" ]; then
        echo -e "${YELLOW}[!]${RESET} 确认重新格式化该分区(数据将丢失)"
    else
        echo -e "${YELLOW}[!]${RESET} 未检测到文件系统,需要先格式化"
    fi
  
    echo -e "${CYAN}${BOLD}文件系统类型列表:${RESET}"
    echo ""
  
    declare -A fs_map
    fs_map[1]="ext4 (推荐,兼容性好)"
    fs_map[2]="xfs (高性能,适合大文件)"
    fs_map[3]="ext3 (兼容旧系统)"
    fs_map[4]="btrfs (高级功能,快照)"
    fs_map[5]="ntfs (Windows兼容)"
    fs_map[6]="fat32 (通用兼容,小文件)"
  
    # 根据系统安装情况调整
    if ! command -v mkfs.ext4 > /dev/null 2>&1; then
        unset fs_map[1]
    fi
    if ! command -v mkfs.xfs > /dev/null 2>&1; then
        unset fs_map[2]
    fi
    if ! command -v mkfs.ext3 > /dev/null 2>&1; then
        unset fs_map[3]
    fi
    if ! command -v mkfs.btrfs > /dev/null 2>&1; then
        unset fs_map[4]
    fi
    if ! command -v mkfs.ntfs > /dev/null 2>&1; then
        unset fs_map[5]
    fi
    if ! command -v mkfs.fat > /dev/null 2>&1; then
        unset fs_map[6]
    fi
  
    if [ ${#fs_map[@]} -eq 0 ]; then
        echo -e "${RED}[✗]${RESET} 没有可用的文件系统工具"
        return 1
    fi
  
    for i in $(echo "${!fs_map[@]}" | tr ' ' '\n' | sort -n); do
        printf "  ${GREEN}%2d${RESET}) ${YELLOW}%-30s${RESET}\n" "$i" "${fs_map[$i]}"
    done
  
    echo ""
  
    while true; do
        read -p "请输入文件系统编号 (默认: 1): " fs_choice
        fs_choice=${fs_choice:-1}
      
        if [[ ! "${!fs_map[@]}" =~ $fs_choice ]]; then
            echo -e "${RED}[✗]${RESET} 无效选择"
            continue
        fi
      
        case $fs_choice in
            1)
                if ! install_package "e2fsprogs" "ext4工具"; then
                    continue
                fi
                echo -e "${BLUE}[INFO]${RESET} 正在格式化为 ext4..."
                mkfs.ext4 -F -m 0 "$partition" > /dev/null 2>&1
                simple_progress 3 "格式化ext4文件系统"
                if [ $? -eq 0 ]; then
                    echo -e "${GREEN}[✓]${RESET} 格式化完成"
                    FORMAT_RESULT="ext4"
                else
                    echo -e "${RED}[✗]${RESET} 格式化失败"
                fi
                ;;
            2)
                if ! install_package "xfsprogs" "xfs工具"; then
                    continue
                fi
                echo -e "${BLUE}[INFO]${RESET} 正在格式化为 xfs..."
                mkfs.xfs -f "$partition" > /dev/null 2>&1
                simple_progress 3 "格式化xfs文件系统"
                if [ $? -eq 0 ]; then
                    echo -e "${GREEN}[✓]${RESET} 格式化完成"
                    FORMAT_RESULT="xfs"
                else
                    echo -e "${RED}[✗]${RESET} 格式化失败"
                fi
                ;;
            3)
                if ! install_package "e2fsprogs" "ext3工具"; then
                    continue
                fi
                echo -e "${BLUE}[INFO]${RESET} 正在格式化为 ext3..."
                mkfs.ext3 -F "$partition" > /dev/null 2>&1
                simple_progress 3 "格式化ext3文件系统"
                if [ $? -eq 0 ]; then
                    echo -e "${GREEN}[✓]${RESET} 格式化完成"
                    FORMAT_RESULT="ext3"
                else
                    echo -e "${RED}[✗]${RESET} 格式化失败"
                fi
                ;;
            4)
                if ! install_package "btrfs-progs" "btrfs工具"; then
                    continue
                fi
                echo -e "${BLUE}[INFO]${RESET} 正在格式化为 btrfs..."
                mkfs.btrfs -f "$partition" > /dev/null 2>&1
                simple_progress 3 "格式化btrfs文件系统"
                if [ $? -eq 0 ]; then
                    echo -e "${GREEN}[✓]${RESET} 格式化完成"
                    FORMAT_RESULT="btrfs"
                else
                    echo -e "${RED}[✗]${RESET} 格式化失败"
                fi
                ;;
            5)
                if ! install_package "ntfs-3g" "NTFS工具"; then
                    continue
                fi
                echo -e "${BLUE}[INFO]${RESET} 正在格式化为 NTFS..."
                mkfs.ntfs -f -Q "$partition" > /dev/null 2>&1
                simple_progress 3 "格式化NTFS文件系统"
                if [ $? -eq 0 ]; then
                    echo -e "${GREEN}[✓]${RESET} 格式化完成"
                    FORMAT_RESULT="ntfs"
                else
                    echo -e "${RED}[✗]${RESET} 格式化失败"
                fi
                ;;
            6)
                if ! install_package "dosfstools" "FAT32工具"; then
                    continue
                fi
                echo -e "${BLUE}[INFO]${RESET} 正在格式化为 FAT32..."
                mkfs.fat -F 32 -n "DATA" "$partition" > /dev/null 2>&1
                simple_progress 3 "格式化FAT32文件系统"
                if [ $? -eq 0 ]; then
                    echo -e "${GREEN}[✓]${RESET} 格式化完成"
                    FORMAT_RESULT="fat32"
                else
                    echo -e "${RED}[✗]${RESET} 格式化失败"
                fi
                ;;
        esac
      
        if [ -n "$FORMAT_RESULT" ]; then
            return 0
        fi
    done
}

# 挂载分区
mount_partition() {
    local partition=$1
    local mount_point=$2
  
    if [ ! -d "$mount_point" ]; then
        mkdir -p "$mount_point"
        echo -e "${BLUE}[INFO]${RESET} 创建挂载目录: $mount_point"
    fi
  
    echo -e "${BLUE}[INFO]${RESET} 正在挂载 $partition 到 $mount_point ..."
  
    mount "$partition" "$mount_point" > /dev/null 2>&1
  
    if [ $? -eq 0 ]; then
        simple_progress 2 "挂载文件系统"
        echo -e "${GREEN}[✓]${RESET} 挂载成功"
      
        chmod 755 "$mount_point"
      
        local uuid=$(blkid -s UUID -o value "$partition" 2>/dev/null)
        if [ -n "$uuid" ]; then
            local fs_type=$(lsblk -n -o FSTYPE "$partition" 2>/dev/null | head -1)
          
            sed -i "\|^[^#].*$mount_point[[:space:]]|d" /etc/fstab 2>/dev/null
            sed -i "\|^[^#].*$partition[[:space:]]|d" /etc/fstab 2>/dev/null
          
            echo "UUID=$uuid $mount_point $fs_type defaults 0 0" >> /etc/fstab
            echo -e "${GREEN}[✓]${RESET} 已配置开机自动挂载"
          
            mount -a > /dev/null 2>&1
            simple_progress 1 "测试fstab配置"
          
            if [ $? -eq 0 ]; then
                echo -e "${GREEN}[✓]${RESET} fstab配置测试通过"
            else
                echo -e "${YELLOW}[!]${RESET} fstab配置测试失败"
            fi
        fi
      
        return 0
    else
        echo -e "${RED}[✗]${RESET} 挂载失败"
        return 1
    fi
}

# 删除分区表(清空整个磁盘)
delete_partition_table() {
    local partition=$1
    # 提取磁盘名(如从 /dev/sdb1 提取 sdb)
    local disk=$(echo "$partition" | sed -E 's/^\/dev\/([a-zA-Z0-9]+)[0-9]+$/\1/')
    local disk_path="/dev/$disk"
  
    echo -e "${RED}[WARNING]${RESET} 即将删除 $disk_path 上的所有分区!"
    echo -e "${RED}[WARNING]${RESET} 此操作将彻底清空该磁盘的分区表,所有数据将永久丢失!"
    echo -e "${RED}[WARNING]${RESET} 磁盘上的所有分区都会被删除,无法恢复!"
  
    # 显示磁盘当前分区信息
    echo -e "${YELLOW}当前分区信息:${RESET}"
    fdisk -l "$disk_path" 2>/dev/null | grep "^/dev/" || echo "    无分区信息"
  
    read -p "最终确认删除 $disk_path 的所有分区和分区表?[y/N]: " delete_confirm
  
    if [[ ! "$delete_confirm" =~ ^[Yy]$ ]]; then
        echo -e "${BLUE}[INFO]${RESET} 取消删除分区表操作"
        return 0
    fi
  
    # 安装parted(如果未安装)
    if ! command -v parted > /dev/null 2>&1; then
        echo -e "${YELLOW}[!]${RESET} 正在安装parted工具..."
        if ! install_package "parted" "parted分区工具"; then
            echo -e "${RED}[✗]${RESET} 无法安装parted"
            return 1
        fi
    fi
  
    echo -e "${BLUE}[INFO]${RESET} 正在清除 $disk_path 的分区表..."
  
    # 方法1:使用dd清除分区表(最彻底)
    echo -e "${BLUE}[INFO]${RESET} 方法1:使用dd清除分区表签名..."
    dd if=/dev/zero of="$disk_path" bs=512 count=1 conv=notrunc 2>/dev/null
    simple_progress 2 "清除MBR/GPT签名"
  
    # 方法2:使用wipefs清除所有签名
    echo -e "${BLUE}[INFO]${RESET} 方法2:使用wipefs清除文件系统签名..."
    if command -v wipefs > /dev/null 2>&1; then
        wipefs -a "$disk_path" > /dev/null 2>&1
        simple_progress 2 "清除文件系统签名"
    fi
  
    # 方法3:创建新的空分区表
    echo -e "${BLUE}[INFO]${RESET} 方法3:创建新的空GPT分区表..."
    parted -s "$disk_path" mklabel gpt > /dev/null 2>&1
    simple_progress 2 "创建新分区表"
  
    # 刷新分区表
    partprobe "$disk_path" > /dev/null 2>&1
    simple_progress 1 "刷新分区表"
  
    # 验证分区是否已删除
    local remaining_parts=$(lsblk -l -n -o NAME | grep "^${disk}[0-9]" | wc -l)
    if [ "$remaining_parts" -eq 0 ]; then
        echo -e "${GREEN}[✓]${RESET} 分区表删除成功:$disk_path 已无分区"
        return 0
    else
        echo -e "${RED}[✗]${RESET} 分区表删除失败,仍有残留分区"
        return 1
    fi
}

# 删除单个分区(不删除整个分区表)- 修复swap分区问题
delete_single_partition() {
    local partition=$1
    # 提取磁盘名(如从 /dev/sdb1 提取 sdb)
    local disk=$(echo "$partition" | sed -E 's/^\/dev\/([a-zA-Z0-9]+)[0-9]+$/\1/')
    local disk_path="/dev/$disk"
    local part_num=$(echo "$partition" | grep -o '[0-9]\+$')
  
    # 检查是否为swap分区
    local is_swap=false
    if command -v lsblk > /dev/null 2>&1; then
        local fstype=$(lsblk -n -o FSTYPE "$partition" 2>/dev/null | head -1)
        if [ "$fstype" = "swap" ]; then
            is_swap=true
        fi
    fi
  
    echo -e "${YELLOW}[!]${RESET} 即将删除分区 $partition"
    if $is_swap; then
        echo -e "${YELLOW}[!]${RESET} 这是一个swap分区"
    else
        echo -e "${YELLOW}[!]${RESET} 分区 $part_num 将被删除,该分区的数据将丢失"
    fi
  
    # 显示分区信息
    echo -e "${CYAN}分区信息:${RESET}"
    fdisk -l "$partition" 2>/dev/null | head -5 || echo "    无法获取分区信息"
  
    read -p "确认删除分区 $partition?[y/N]: " delete_confirm
  
    if [[ ! "$delete_confirm" =~ ^[Yy]$ ]]; then
        echo -e "${BLUE}[INFO]${RESET} 取消删除分区操作"
        return 0
    fi
  
    # 如果是swap分区且已启用,先关闭swap
    if $is_swap; then
        echo -e "${BLUE}[INFO]${RESET} 检测到swap分区,正在检查是否已启用..."
        if swapon --show | grep -q "$partition"; then
            echo -e "${BLUE}[INFO]${RESET} 正在关闭swap分区 $partition ..."
            swapoff "$partition"
            if [ $? -eq 0 ]; then
                echo -e "${GREEN}[✓]${RESET} swap分区已关闭"
            else
                echo -e "${RED}[✗]${RESET} 无法关闭swap分区"
                return 1
            fi
        fi
    fi
  
    # 使用fdisk非交互式删除分区
    echo -e "${BLUE}[INFO]${RESET} 正在删除分区 $partition ..."
  
    # 构建fdisk命令序列
    local fdisk_cmds="d\n"  # 删除分区
    if [ -n "$part_num" ]; then
        fdisk_cmds+="$part_num\n"  # 分区号
    fi
    fdisk_cmds+="w\n"  # 保存
  
    echo -e "$fdisk_cmds" | fdisk "$disk_path" > /dev/null 2>&1
  
    if [ $? -ne 0 ]; then
        echo -e "${RED}[✗]${RESET} fdisk删除失败,尝试使用parted"
      
        # 尝试使用parted
        if command -v parted > /dev/null 2>&1; then
            parted -s "$disk_path" rm "$part_num" > /dev/null 2>&1
            if [ $? -ne 0 ]; then
                echo -e "${RED}[✗]${RESET} parted删除也失败"
                return 1
            fi
        else
            echo -e "${RED}[✗]${RESET} parted未安装"
            return 1
        fi
    fi
  
    # 刷新分区表
    partprobe "$disk_path" > /dev/null 2>&1
    simple_progress 2 "刷新分区表"
  
    # 验证分区是否已删除
    if [ ! -b "$partition" ]; then
        echo -e "${GREEN}[✓]${RESET} 分区删除成功:$partition 已不存在"
        return 0
    else
        echo -e "${RED}[✗]${RESET} 分区删除失败"
        return 1
    fi
}

# 卸载分区
umount_partition() {
    local device_mount=$1
    local device=$(echo "$device_mount" | cut -d'|' -f1)
    local mount_point=$(echo "$device_mount" | cut -d'|' -f2)
  
    echo -e "${BLUE}[INFO]${RESET} 正在卸载 $device (挂载点: $mount_point)..."
  
    if ! mount | grep -q "$device on $mount_point"; then
        echo -e "${YELLOW}[!]${RESET} 该设备未挂载在 $mount_point"
        return 1
    fi
  
    umount "$device" > /dev/null 2>&1
  
    if [ $? -eq 0 ]; then
        simple_progress 2 "安全卸载设备"
        echo -e "${GREEN}[✓]${RESET} 卸载成功"
    else
        echo -e "${YELLOW}[!]${RESET} 设备被进程占用,正在显示占用进程..."
        fuser -v "$mount_point" 2>/dev/null || echo "  未找到占用进程"
      
        echo -e "${YELLOW}[!]${RESET} 尝试强制卸载..."
        umount -l "$device" > /dev/null 2>&1
      
        if [ $? -eq 0 ]; then
            simple_progress 2 "强制卸载设备"
            echo -e "${GREEN}[✓]${RESET} 强制卸载成功"
        else
            echo -e "${RED}[✗]${RESET} 卸载失败"
            return 1
        fi
    fi
  
    # 清理fstab中的条目
    sed -i "\|^[^#].*$mount_point[[:space:]]|d" /etc/fstab 2>/dev/null
    sed -i "\|^[^#].*$device[[:space:]]|d" /etc/fstab 2>/dev/null
  
    echo -e "${GREEN}[✓]${RESET} 已清理开机自动挂载配置"
  
    return 0
}

# 主程序
main() {
    check_root
    check_system_compatibility
  
    while true; do
        show_system_info
        show_disk_info
      
        echo -e "${CYAN}${BOLD}请选择操作类型:${RESET}"
        echo ""
        echo -e "  ${GREEN}1${RESET}) 挂载磁盘/分区"
        echo -e "  ${GREEN}2${RESET}) 卸载磁盘/分区"
        echo -e "  ${GREEN}3${RESET}) 删除分区/分区表"
        echo -e "  ${GREEN}4${RESET}) 显示系统信息"
        echo -e "  ${GREEN}q${RESET}) 退出脚本"
        echo ""
        read -p "请输入选择 [1/2/3/4/q]: " main_choice
        echo ""
      
        case $main_choice in
            1)
                # 挂载磁盘/分区
                if ! show_available_mount_devices; then
                    echo -e "${YELLOW}按回车键返回主菜单...${RESET}"
                    read -p ""
                    clear
                    continue
                fi
              
                echo -e "${CYAN}请输入设备编号 (或输入q返回):${RESET}"
                read -p "> " choice
              
                if [ "$choice" = "q" ]; then
                    clear
                    continue
                fi
              
                local selected_device="${device_map[$choice]}"
              
                if [ -z "$selected_device" ]; then
                    echo -e "${RED}[✗]${RESET} 无效的选择"
                    sleep 2
                    clear
                    continue
                fi
              
                echo ""
                echo -e "${CYAN}══════════════════════════════════════════${RESET}"
                echo -e "${CYAN}已选择设备:${RESET} ${GREEN}$selected_device${RESET}"
                echo -e "${CYAN}══════════════════════════════════════════${RESET}"
                echo ""
              
                local partition=""
                local fs_type=""
              
                if [[ "$selected_device" =~ [0-9]$ ]] || [[ "$selected_device" =~ p[0-9]+$ ]]; then
                    # 选择的是分区
                    partition="$selected_device"
                    fs_type=$(lsblk -n -o FSTYPE "$partition" 2>/dev/null | head -1 | xargs)
                  
                    if [ -n "$fs_type" ] && [ "$fs_type" != "" ]; then
                        echo -e "${CYAN}检测到文件系统:${RESET} ${YELLOW}$fs_type${RESET}"
                        read -p "是否重新格式化?[y/N]: " reformat
                      
                        if [[ "$reformat" =~ ^[Yy]$ ]]; then
                            show_format_menu "$partition" "true"
                            fs_type=$FORMAT_RESULT
                            if [ -z "$fs_type" ]; then
                                echo -e "${YELLOW}按回车返回...${RESET}"
                                read
                                clear
                                continue
                            fi
                        fi
                    else
                        show_format_menu "$partition" "false"
                        fs_type=$FORMAT_RESULT
                        if [ -z "$fs_type" ]; then
                            echo -e "${YELLOW}按回车返回...${RESET}"
                            read
                            clear
                            continue
                        fi
                    fi
                else
                    # 选择的是未分区的磁盘
                    echo -e "${CYAN}该设备是磁盘,需要先创建分区${RESET}"
                    read -p "是否创建分区?[Y/n]: " create_part
                    if [[ "$create_part" =~ ^[Nn]$ ]]; then
                        echo -e "${YELLOW}操作取消${RESET}"
                        sleep 1
                        clear
                        continue
                    fi
                  
                    # 选择分区表类型
                    local partition_table=$(choose_partition_table)
                    if [ -z "$partition_table" ]; then
                        echo -e "${YELLOW}按回车返回...${RESET}"
                        read
                        clear
                        continue
                    fi
                  
                    echo -e "${BLUE}══════════════════════════════════════════${RESET}"
                    echo -e "${BLUE}开始创建分区${RESET}"
                    echo -e "${BLUE}══════════════════════════════════════════${RESET}"
                    echo ""
                  
                    partition=$(create_partition "$selected_device" "$partition_table")
                    if [ $? -ne 0 ] || [ -z "$partition" ]; then
                        echo -e "${RED}分区创建失败,按回车返回...${RESET}"
                        read
                        clear
                        continue
                    fi
                  
                    echo -e "${GREEN}[✓]${RESET} 分区创建完成: $partition"
                    echo ""
                  
                    # 重要:创建分区表后,提示用户重新运行脚本
                    echo -e "${YELLOW}[!]${RESET} 分区表已创建,需要重新扫描设备..."
                    echo -e "${YELLOW}[!]${RESET} 请按回车键返回主菜单,然后重新选择'挂载磁盘/分区'选项"
                    echo ""
                    read -p "按回车键继续..."
                    clear
                    continue
                fi
              
                if [ -z "$fs_type" ]; then
                    echo -e "${RED}[✗]${RESET} 无法确定文件系统类型"
                    echo -e "${YELLOW}按回车返回...${RESET}"
                    read
                    clear
                    continue
                fi
              
                # 输入挂载点
                echo -e "${BLUE}══════════════════════════════════════════${RESET}"
                echo -e "${BLUE}设置挂载点${RESET}"
                echo -e "${BLUE}══════════════════════════════════════════${RESET}"
                echo ""
              
                echo -e "${CYAN}请输入挂载点路径${RESET}"
                echo -e "示例: ${YELLOW}/data${RESET}, ${YELLOW}/www${RESET}, ${YELLOW}/mnt/disk${RESET}"
              
                while true; do
                    read -p "> " mount_point
                  
                    if [ -z "$mount_point" ]; then
                        echo -e "${RED}[✗]${RESET} 挂载点不能为空"
                        continue
                    fi
                  
                    if [[ ! "$mount_point" =~ ^/ ]]; then
                        echo -e "${RED}[✗]${RESET} 挂载点必须以 / 开头"
                        continue
                    fi
                  
                    if mount | grep -q " on $mount_point "; then
                        local mounted_dev=$(mount | grep " on $mount_point " | awk '{print $1}')
                        if [ "$mounted_dev" != "$partition" ]; then
                            echo -e "${RED}[✗]${RESET} 该目录已被 $mounted_dev 挂载"
                            continue
                        fi
                    fi
                  
                    break
                done
              
                # 执行挂载
                echo ""
                echo -e "${BLUE}══════════════════════════════════════════${RESET}"
                echo -e "${BLUE}开始挂载${RESET}"
                echo -e "${BLUE}══════════════════════════════════════════${RESET}"
                echo ""
              
                if mount_partition "$partition" "$mount_point"; then
                    echo ""
                    echo -e "${PURPLE}══════════════════════════════════════════${RESET}"
                    echo -e "${GREEN}            挂载完成!                  ${RESET}"
                    echo -e "${PURPLE}══════════════════════════════════════════${RESET}"
                    echo ""
                  
                    echo -e "${CYAN}挂载信息:${RESET}"
                    echo -e "  设备: ${GREEN}$partition${RESET}"
                    echo -e "  挂载点: ${BLUE}$mount_point${RESET}"
                    echo -e "  文件系统: ${YELLOW}$fs_type${RESET}"
                    echo -e "  容量: $(lsblk -n -o SIZE "$partition" 2>/dev/null | head -1)"
                    echo ""
                  
                    echo -e "${CYAN}磁盘空间:${RESET}"
                    df -h "$mount_point" 2>/dev/null | tail -1 | awk '{print "  使用: " $3 " / " $2 " (" $5 ")"}'
                    echo ""
                fi
              
                echo ""
                read -p "按回车键返回主菜单..."
                clear
                ;;
              
            2)
                # 卸载磁盘/分区
                if ! show_mounted_devices; then
                    echo -e "${YELLOW}按回车键返回主菜单...${RESET}"
                    read -p ""
                    clear
                    continue
                fi
              
                echo -e "${CYAN}请输入设备编号 (或输入q返回):${RESET}"
                read -p "> " choice
              
                if [ "$choice" = "q" ]; then
                    clear
                    continue
                fi
              
                local selected_mounted_device="${mounted_device_map[$choice]}"
              
                if [ -z "$selected_mounted_device" ]; then
                    echo -e "${RED}[✗]${RESET} 无效的选择"
                    sleep 2
                    clear
                    continue
                fi
              
                echo ""
                echo -e "${CYAN}══════════════════════════════════════════${RESET}"
                echo -e "${CYAN}确认卸载:${RESET} ${RED}$selected_mounted_device${RESET}"
                echo -e "${CYAN}══════════════════════════════════════════${RESET}"
                echo ""
              
                read -p "确认卸载?[y/N]: " confirm_umount
                if [[ ! "$confirm_umount" =~ ^[Yy]$ ]]; then
                    echo -e "${YELLOW}操作取消${RESET}"
                    sleep 1
                    clear
                    continue
                fi
              
                if umount_partition "$selected_mounted_device"; then
                    echo ""
                    echo -e "${PURPLE}══════════════════════════════════════════${RESET}"
                    echo -e "${GREEN}            卸载完成!                  ${RESET}"
                    echo -e "${PURPLE}══════════════════════════════════════════${RESET}"
                    echo ""
                fi
              
                echo ""
                read -p "按回车键返回主菜单..."
                clear
                ;;
              
            3)
                # 删除分区/分区表
                echo -e "${CYAN}${BOLD}删除操作:${RESET}"
                echo ""
                echo -e "  1) 删除单个分区"
                echo -e "  2) 删除整个磁盘的分区表"
                echo -e "  q) 返回主菜单"
                echo ""
                read -p "请选择删除类型 [1/2/q]: " delete_type
              
                case $delete_type in
                    1)
                        # 删除单个分区
                        if ! show_all_partitions_for_deletion; then
                            echo -e "${YELLOW}按回车键返回...${RESET}"
                            read -p ""
                            clear
                            continue
                        fi
                      
                        echo -e "${CYAN}请输入分区编号 (或输入q返回):${RESET}"
                        read -p "> " choice
                      
                        if [ "$choice" = "q" ]; then
                            clear
                            continue
                        fi
                      
                        local selected_partition_info="${all_partition_map[$choice]}"
                      
                        if [ -z "$selected_partition_info" ]; then
                            echo -e "${RED}[✗]${RESET} 无效的选择"
                            sleep 2
                            clear
                            continue
                        fi
                      
                        local partition=$(echo "$selected_partition_info" | cut -d'|' -f1)
                        local current_fs=$(echo "$selected_partition_info" | cut -d'|' -f2)
                        local current_mount=$(echo "$selected_partition_info" | cut -d'|' -f3)
                        local partition_size=$(echo "$selected_partition_info" | cut -d'|' -f4)
                      
                        echo ""
                        echo -e "${CYAN}══════════════════════════════════════════${RESET}"
                        echo -e "${CYAN}确认删除分区:${RESET} ${RED}$partition${RESET}"
                        echo -e "  ${WHITE}文件系统:${RESET} ${YELLOW}${current_fs:-无}${RESET}"
                        echo -e "  ${WHITE}挂载状态:${RESET} ${YELLOW}${current_mount:-未挂载}${RESET}"
                        echo -e "  ${WHITE}分区大小:${RESET} ${CYAN}$partition_size${RESET}"
                        echo -e "${CYAN}══════════════════════════════════════════${RESET}"
                        echo ""
                      
                        if [ -n "$current_mount" ]; then
                            # 检查是否为swap分区
                            if [ "$current_fs" = "swap" ] || [ "$current_mount" = "[SWAP]" ]; then
                                echo -e "${RED}[!]${RESET} 警告:这是一个swap分区"
                                read -p "是否先关闭swap再删除?[Y/n]: " swapoff_first
                              
                                if [[ ! "$swapoff_first" =~ ^[Nn]$ ]]; then
                                    echo -e "${BLUE}[INFO]${RESET} 正在关闭swap分区 $partition ..."
                                    swapoff "$partition" 2>/dev/null
                                    if [ $? -eq 0 ]; then
                                        echo -e "${GREEN}[✓]${RESET} swap分区已关闭"
                                    else
                                        echo -e "${YELLOW}[!]${RESET} 关闭swap分区失败,继续尝试删除..."
                                    fi
                                fi
                            else
                                echo -e "${RED}[!]${RESET} 警告:该分区当前已挂载在 $current_mount"
                                read -p "是否先卸载再删除?[Y/n]: " unmount_first
                              
                                if [[ ! "$unmount_first" =~ ^[Nn]$ ]]; then
                                    echo -e "${BLUE}[INFO]${RESET} 正在卸载 $partition ..."
                                    umount "$partition" > /dev/null 2>&1
                                    if [ $? -eq 0 ]; then
                                        echo -e "${GREEN}[✓]${RESET} 卸载成功"
                                    else
                                        echo -e "${YELLOW}[!]${RESET} 卸载失败,尝试强制卸载..."
                                        umount -l "$partition" > /dev/null 2>&1
                                    fi
                                fi
                            fi
                        fi
                      
                        # 执行删除
                        delete_single_partition "$partition"
                      
                        # 删除分区后提示用户
                        echo -e "${YELLOW}[!]${RESET} 分区已删除,请按回车键返回主菜单..."
                        read -p ""
                        clear
                        continue
                        ;;
                      
                    2)
                        # 删除整个磁盘的分区表
                        if ! show_all_disks_for_deletion; then
                            echo -e "${YELLOW}按回车键返回...${RESET}"
                            read -p ""
                            clear
                            continue
                        fi
                      
                        echo -e "${CYAN}请输入磁盘编号 (或输入q返回):${RESET}"
                        read -p "> " choice
                      
                        if [ "$choice" = "q" ]; then
                            clear
                            continue
                        fi
                      
                        local selected_disk="${all_disk_map[$choice]}"
                      
                        if [ -z "$selected_disk" ]; then
                            echo -e "${RED}[✗]${RESET} 无效的选择"
                            sleep 2
                            clear
                            continue
                        fi
                      
                        echo ""
                        echo -e "${CYAN}══════════════════════════════════════════${RESET}"
                        echo -e "${CYAN}确认删除磁盘分区表:${RESET} ${RED}$selected_disk${RESET}"
                        echo -e "${CYAN}══════════════════════════════════════════${RESET}"
                        echo ""
                      
                        # 执行删除
                        delete_partition_table "$selected_disk"
                      
                        # 删除分区表后提示用户
                        echo -e "${YELLOW}[!]${RESET} 分区表已删除,请按回车键返回主菜单..."
                        read -p ""
                        clear
                        continue
                        ;;
                      
                    q)
                        clear
                        continue
                        ;;
                      
                    *)
                        echo -e "${RED}[✗]${RESET} 无效选择"
                        sleep 2
                        ;;
                esac
              
                echo ""
                read -p "按回车键返回主菜单..."
                clear
                ;;
              
            4)
                # 显示系统信息
                clear
                echo -e "${CYAN}${BOLD}详细系统信息:${RESET}"
                echo ""
                echo -e "${WHITE}操作系统:${RESET} $SYS_INFO"
                echo -e "${WHITE}内核版本:${RESET} $(uname -r)"
                echo -e "${WHITE}主机名称:${RESET} $(hostname)"
                echo -e "${WHITE}系统架构:${RESET} $(uname -m)"
                echo -e "${WHITE}运行环境:${RESET} $([ "$CONTAINER_ENV" = true ] && echo "容器" || echo "物理机/虚拟机")"
                echo -e "${WHITE}包管理器:${RESET} $PKG_MANAGER"
                echo -e "${WHITE}分区工具:${RESET} $PARTITION_TOOL"
                echo -e "${WHITE}GPT支持:${RESET} $([ "$GPT_SUPPORT" = true ] && echo "是" || echo "否")"
                echo -e "${WHITE}磁盘数量:${RESET} $(lsblk -d -n -o NAME | grep -vE '^loop|^sr' | wc -l)"
                echo ""
                read -p "按回车键返回主菜单..."
                clear
                ;;
              
            q|Q)
                echo ""
                echo -e "${GREEN}══════════════════════════════════════════${RESET}"
                echo -e "${GREEN}    感谢使用磁盘挂载助手!              ${RESET}"
                echo -e "${GREEN}══════════════════════════════════════════${RESET}"
                echo ""
                exit 0
                ;;
              
            *)
                echo -e "${RED}[✗]${RESET} 无效选择"
                sleep 2
                clear
                ;;
        esac
    done
}

# 捕获中断
trap 'echo -e "\n${RED}操作被中断${RESET}"; exit 1' INT

# 运行
main "$@"

功能详解

一、挂载新磁盘(选项1)

场景:添加新硬盘后需要分区、格式化并挂载

步骤

  1. 选择菜单选项 1
  2. 从列表中选择要操作的设备
    • 如果是未分区的磁盘,脚本会自动引导创建分区
    • 如果已有分区但未格式化,可选择文件系统类型
  3. 选择分区表类型(GPT推荐用于2TB以上磁盘)
  4. 选择文件系统类型:
    • ext4:推荐,兼容性好
    • xfs:高性能,适合大文件
    • btrfs:支持快照等高级功能
    • NTFS:Windows兼容
    • FAT32:通用兼容
  5. 指定挂载点目录(如:/data/www/mnt/disk1

脚本自动完成

  • 创建分区表(GPT/MBR)
  • 创建分区
  • 格式化指定文件系统
  • 创建挂载目录
  • 挂载分区
  • 配置开机自动挂载(/etc/fstab)
  • 验证配置有效性

二、卸载磁盘(选项2)

场景:安全移除已挂载的磁盘

步骤

  1. 选择菜单选项 2
  2. 从已挂载设备列表中选择要卸载的设备
  3. 确认卸载操作

卸载后可选操作

  • 仅卸载,保留数据
  • 重新格式化分区
  • 删除该分区(保留分区表)
  • 删除整个磁盘的分区表(清空所有分区)

三、删除分区/分区表(选项3)

场景:清理不需要的分区或重新规划磁盘

安全特性

  • 自动隐藏系统关键分区(根分区、引导分区、swap)
  • 多重确认防止误操作
  • 支持swap分区安全删除

操作类型

  1. 删除单个分区:仅删除指定分区,不影响其他分区
  2. 删除分区表:清空整个磁盘的所有分区(数据将永久丢失)

高级特性

1. 智能包管理

脚本自动检测系统包管理器并安装所需工具:

  • Debian/Ubuntu:使用apt
  • CentOS/RHEL:使用yum
  • Arch/Manjaro:使用pacman
  • openSUSE:使用zypper

2. 安全保护机制

  • Root权限检查
  • 系统关键分区保护
  • 操作前确认提示
  • 进程占用检查

3. 容器环境适配

自动检测Docker/Kubernetes容器环境,调整操作策略

4. 进度可视化

所有耗时操作都显示美观的进度条:

[INFO] 格式化ext4文件系统 [██████████████████████████████] 100% ✓

使用示例

示例1:挂载新数据盘

# 运行脚本
bash <(curl -s http://disk.6wd.cn/mount-disk.sh)

# 操作流程:
# 1. 选择选项1(挂载)
# 2. 选择新磁盘(如/dev/sdb)
# 3. 选择GPT分区表
# 4. 选择ext4文件系统
# 5. 输入挂载点:/data
# 6. 脚本自动完成所有配置

示例2:扩展磁盘空间

# 当需要重新分区时:
# 1. 先选择选项2卸载磁盘
# 2. 选择选项3删除旧分区
# 3. 重新选择选项1创建更大分区
# 4. 挂载到原目录,数据会保留(如果未格式化)

故障排除

常见问题:

  1. 权限不足

    请使用:sudo bash mount.sh
    
  2. 设备被占用

    [INFO] 设备被进程占用,正在显示占用进程...
    fuser -v 显示占用进程详情
    
  3. 包安装失败

    脚本会尝试多种安装方式,如失败请手动安装:
    # Debian/Ubuntu
    sudo apt update && sudo apt install parted e2fsprogs
    
    # CentOS/RHEL
    sudo yum install parted e2fsprogs
    

注意事项

  1. 数据安全

    • 操作前请确认已备份重要数据
    • 格式化、删除分区操作不可逆
    • 建议在非生产环境先测试
  2. 系统要求

    • Linux内核2.6以上版本
    • Root权限
    • 基本的命令行工具(lsblk、blkid等)
  3. 推荐实践

    • 生产环境先在测试机验证
    • 重要操作前手动备份fstab
    • 使用LVM管理复杂存储需求

更新日志

  • v6.1:增强容器支持,优化进度显示
  • v6.0:跨平台重构,支持更多发行版
  • v5.x:添加分区删除功能,改进UI

结语

Linux磁盘挂载助手通过自动化复杂操作,让磁盘管理变得简单直观。无论是单次部署还是批量管理,这个脚本都能显著提高工作效率。开源免费,持续更新,欢迎反馈和改进建议!

立即体验

bash <(curl -s http://disk.6wd.cn/mount-disk.sh)

作者:[昴]
许可证:开源免费使用
支持:GitHub Issues / 邮箱联系
版本:v6.1 跨平台版