debian 12 硬盘管理脚本
(一).检测主机上所有非系统盘信息
(二).显示以分区或者未分区的硬盘信息并显示挂载目录
(1).可以对未分区的硬盘进行分区并格式化
(2).初始化以分区的硬盘,恢复未格式化状态
(3).把以分区格式化的分区挂载到系统路径,并实现开机自动挂载。(互交模式,用户需要指定挂载路径)
(4).卸载以挂载的分区
cat > /root/disk_manager.sh << 'EOF'
#!/bin/bash
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # 恢复默认颜色
# 检查root权限
if [ "$(id -u)" -ne 0 ]; then
echo -e "${RED}错误:此脚本必须以root权限运行!${NC}" >&2
exit 1
fi
# 安装必要工具
apt-get update && apt-get install -y util-linux parted e2fsprogs
# 获取系统盘
get_sys_disk() {
local root_device=$(findmnt -n -o SOURCE /)
local sys_disk=$(lsblk -no pkname "$root_device" 2>/dev/null | head -1)
[[ -z "$sys_disk" ]] && sys_disk=$(lsblk -ndo name,mountpoint | awk '$2=="/" {print $1}' | sed 's/[0-9]*$//')
[[ -z "$sys_disk" ]] && sys_disk="sda"
echo "$sys_disk"
}
# 检测所有非系统硬盘
detect_disks() {
local sys_disk=$(get_sys_disk)
declare -gA DISK_INFO
declare -ga DISK_LIST
# 清空数组
DISK_LIST=()
DISK_INFO=()
while IFS= read -r disk; do
local disk_name=$(basename "$disk")
[[ "$disk_name" == *"$sys_disk"* ]] && continue
[[ "$disk" =~ ^/dev/(sd|vd|nvme)[a-z0-9]+$ ]] || continue
# 获取磁盘信息
local size=$(lsblk -dnbo SIZE "$disk" | awk '{printf "%.1f GB", $1/1024/1024/1024}')
local partitions=$(lsblk -lno NAME,TYPE,MOUNTPOINT,FSTYPE,SIZE "$disk" 2>/dev/null | grep -v "^$disk_name ")
# 存储磁盘信息
DISK_INFO["$disk"]="size:$size;partitions:$partitions"
DISK_LIST+=("$disk")
done < <(lsblk -dpno NAME,TYPE 2>/dev/null | awk '$2=="disk" {print $1}')
return ${#DISK_LIST[@]}
}
# 显示磁盘信息
show_disks() {
echo -e "${BLUE}=============================================${NC}"
echo -e "${CYAN} 检测到的非系统硬盘 ${NC}"
echo -e "${BLUE}=============================================${NC}"
if [ ${#DISK_LIST[@]} -eq 0 ]; then
echo -e "${YELLOW}未检测到任何非系统硬盘!${NC}"
return 1
fi
for i in "${!DISK_LIST[@]}"; do
local disk="${DISK_LIST[$i]}"
local info="${DISK_INFO[$disk]}"
local size=$(echo "$info" | grep -oP 'size:\K[^;]+')
local partitions=$(echo "$info" | grep -oP 'partitions:\K.*')
echo -e "${GREEN}$((i+1)). ${disk}${NC} - ${YELLOW}$size${NC}"
if [ -z "$partitions" ] || [ "$(echo "$partitions" | wc -l)" -eq 0 ]; then
echo -e " ${RED}状态: 未分区${NC}"
else
echo -e " ${MAGENTA}分区信息:${NC}"
echo "$partitions" | while read -r line; do
if [ -z "$line" ]; then
continue
fi
local part_name=$(echo "$line" | awk '{print $1}')
local part_type=$(echo "$line" | awk '{print $2}')
local part_mount=$(echo "$line" | awk '{print $3}')
local part_fstype=$(echo "$line" | awk '{print $4}')
local part_size=$(echo "$line" | awk '{print $5}')
if [ "$part_type" == "part" ]; then
if [ -z "$part_mount" ]; then
echo -e " ${CYAN}/dev/$part_name${NC} ($part_size, $part_fstype) - ${YELLOW}未挂载${NC}"
else
echo -e " ${CYAN}/dev/$part_name${NC} ($part_size, $part_fstype) - ${GREEN}已挂载到 $part_mount${NC}"
fi
fi
done
fi
echo ""
done
return 0
}
# 分区并格式化硬盘
partition_disk() {
local disk="$1"
echo -e "${YELLOW}正在处理磁盘: $disk${NC}"
# 检查是否已有分区
if lsblk "$disk" | grep -q 'part'; then
echo -e "${RED}错误:磁盘已有分区!请先删除分区。${NC}"
return 1
fi
# 创建分区表
echo -e "${BLUE}创建GPT分区表...${NC}"
parted -s "$disk" mklabel gpt >/dev/null 2>&1
# 创建分区
echo -e "${BLUE}创建主分区...${NC}"
parted -s "$disk" mkpart primary 0% 100% >/dev/null 2>&1
# 获取分区名称
local partition
if [[ "$disk" =~ /dev/nvme ]]; then
partition="${disk}p1"
else
partition="${disk}1"
fi
# 等待分区出现
sleep 2
if [ ! -e "$partition" ]; then
# 尝试刷新分区表
partprobe "$disk"
sleep 1
if [ ! -e "$partition" ]; then
echo -e "${RED}错误:分区创建失败!${NC}"
return 1
fi
fi
# 格式化分区
echo -e "${BLUE}格式化为ext4文件系统...${NC}"
mkfs.ext4 -F "$partition" >/dev/null 2>&1
echo -e "${GREEN}磁盘 $disk 分区和格式化完成!${NC}"
return 0
}
# 删除分区
delete_partitions() {
local disk="$1"
echo -e "${YELLOW}正在删除磁盘 $disk 的所有分区...${NC}"
# 获取所有分区
local partitions=$(lsblk -lno NAME,TYPE "$disk" | awk '$2=="part" {print "/dev/"$1}')
if [ -z "$partitions" ]; then
echo -e "${YELLOW}磁盘没有分区,无需删除。${NC}"
return 0
fi
# 卸载所有分区
for part in $partitions; do
if findmnt "$part" >/dev/null; then
echo -e "${BLUE}卸载分区 $part...${NC}"
umount "$part" 2>/dev/null
fi
# 从fstab中移除
local uuid=$(blkid -s UUID -o value "$part" 2>/dev/null)
if [ -n "$uuid" ]; then
sed -i "\|^UUID=$uuid|d" /etc/fstab
fi
done
# 删除分区
echo -e "${BLUE}删除分区表...${NC}"
parted -s "$disk" mklabel gpt >/dev/null 2>&1
echo -e "${GREEN}磁盘 $disk 的所有分区已删除!${NC}"
return 0
}
# 挂载分区
mount_partition() {
local disk="$1"
local partition
if [[ "$disk" =~ /dev/nvme ]]; then
partition="${disk}p1"
else
partition="${disk}1"
fi
# 检查分区是否存在
if [ ! -e "$partition" ]; then
echo -e "${RED}错误:分区 $partition 不存在!${NC}"
return 1
fi
# 获取UUID
local uuid=$(blkid -s UUID -o value "$partition" 2>/dev/null)
if [ -z "$uuid" ]; then
echo -e "${RED}错误:无法获取分区UUID!${NC}"
return 1
fi
# 检查是否已挂载
if findmnt "$partition" >/dev/null; then
local current_mount=$(findmnt -n -o TARGET "$partition")
echo -e "${YELLOW}分区已挂载到 $current_mount${NC}"
read -rp "是否重新挂载到其他位置? (y/n): " choice
if [[ ! "$choice" =~ ^[Yy]$ ]]; then
return 0
fi
umount "$partition" 2>/dev/null
fi
# 获取挂载点
while true; do
read -rp "请输入挂载点路径 (例如 /mnt/data): " mount_point
if [[ ! "$mount_point" =~ ^/[a-zA-Z0-9/_-]+$ ]]; then
echo -e "${RED}错误:无效路径!必须是绝对路径。${NC}"
continue
fi
if [ -d "$mount_point" ]; then
if [ -n "$(ls -A "$mount_point")" ]; then
echo -e "${YELLOW}警告:目录非空!挂载后原有内容将被隐藏。${NC}"
read -rp "确认使用此目录? (y/n): " confirm
[[ "$confirm" =~ ^[Yy]$ ]] && break
else
break
fi
else
mkdir -p "$mount_point" && break
fi
done
# 挂载分区
if mount "$partition" "$mount_point"; then
echo -e "${GREEN}分区已挂载到 $mount_point${NC}"
# 添加到fstab
if ! grep -q "UUID=$uuid" /etc/fstab; then
echo "UUID=$uuid $mount_point ext4 defaults 0 2" >> /etc/fstab
echo -e "${GREEN}已添加到 /etc/fstab${NC}"
else
echo -e "${YELLOW}设备已在fstab中注册${NC}"
fi
else
echo -e "${RED}挂载失败!${NC}"
return 1
fi
return 0
}
# 卸载分区
unmount_partition() {
local disk="$1"
local partition
if [[ "$disk" =~ /dev/nvme ]]; then
partition="${disk}p1"
else
partition="${disk}1"
fi
# 检查分区是否存在
if [ ! -e "$partition" ]; then
echo -e "${RED}错误:分区 $partition 不存在!${NC}"
return 1
fi
# 检查是否已挂载
if ! findmnt "$partition" >/dev/null; then
echo -e "${YELLOW}分区未挂载${NC}"
return 0
fi
# 获取挂载点
local mount_point=$(findmnt -n -o TARGET "$partition")
echo -e "${YELLOW}正在卸载 $partition (挂载于 $mount_point)${NC}"
# 卸载分区
if umount "$partition"; then
echo -e "${GREEN}分区已卸载${NC}"
# 从fstab中移除
local uuid=$(blkid -s UUID -o value "$partition" 2>/dev/null)
if [ -n "$uuid" ]; then
sed -i "\|^UUID=$uuid|d" /etc/fstab
echo -e "${GREEN}已从 /etc/fstab 移除${NC}"
fi
# 询问是否删除目录
read -rp "是否删除挂载点目录 $mount_point? (y/n): " choice
if [[ "$choice" =~ ^[Yy]$ ]]; then
rmdir "$mount_point" 2>/dev/null
echo -e "${GREEN}目录已删除${NC}"
fi
else
echo -e "${RED}卸载失败!可能有进程正在使用。${NC}"
return 1
fi
return 0
}
# 主菜单
main_menu() {
while true; do
# 每次循环都重新检测磁盘状态
detect_disks
clear
echo -e "${BLUE}=============================================${NC}"
echo -e "${CYAN} Debian 12 硬盘管理工具 ${NC}"
echo -e "${BLUE}=============================================${NC}"
show_disks
if [ ${#DISK_LIST[@]} -eq 0 ]; then
echo -e "${YELLOW}没有可操作的硬盘!${NC}"
read -rp "按Enter键返回..." dummy
continue
fi
echo -e "${MAGENTA}请选择操作:${NC}"
echo -e " ${GREEN}1${NC}) 分区并格式化硬盘"
echo -e " ${GREEN}2${NC}) 删除硬盘所有分区"
echo -e " ${GREEN}3${NC}) 挂载分区"
echo -e " ${GREEN}4${NC}) 卸载分区"
echo -e " ${GREEN}0${NC}) 退出"
echo ""
read -rp "请输入选项 [0-4]: " choice
case $choice in
1)
echo -e "${YELLOW}请选择要分区的硬盘:${NC}"
select_disk "unpartitioned"
if [ -n "$selected_disk" ]; then
partition_disk "$selected_disk"
fi
;;
2)
echo -e "${YELLOW}请选择要删除分区的硬盘:${NC}"
select_disk "any"
if [ -n "$selected_disk" ]; then
delete_partitions "$selected_disk"
fi
;;
3)
echo -e "${YELLOW}请选择要挂载的硬盘:${NC}"
select_disk "partitioned"
if [ -n "$selected_disk" ]; then
mount_partition "$selected_disk"
fi
;;
4)
echo -e "${YELLOW}请选择要卸载的硬盘:${NC}"
select_disk "mounted"
if [ -n "$selected_disk" ]; then
unmount_partition "$selected_disk"
fi
;;
0)
echo -e "${GREEN}退出程序...${NC}"
exit 0
;;
*)
echo -e "${RED}无效选项!${NC}"
;;
esac
read -rp "按Enter键继续..." dummy
done
}
# 选择硬盘
select_disk() {
local filter="$1"
local options=()
for i in "${!DISK_LIST[@]}"; do
local disk="${DISK_LIST[$i]}"
local info="${DISK_INFO[$disk]}"
local partitions=$(echo "$info" | grep -oP 'partitions:\K.*')
case "$filter" in
"unpartitioned")
if [ -z "$partitions" ] || [ "$(echo "$partitions" | wc -l)" -eq 0 ]; then
options+=("$disk")
fi
;;
"partitioned")
if [ -n "$partitions" ] && [ "$(echo "$partitions" | grep -c 'part')" -gt 0 ]; then
options+=("$disk")
fi
;;
"mounted")
if echo "$partitions" | grep -q 'part.*/' ; then
options+=("$disk")
fi
;;
"any")
options+=("$disk")
;;
esac
done
if [ ${#options[@]} -eq 0 ]; then
echo -e "${YELLOW}没有符合条件的硬盘!${NC}"
selected_disk=""
return 1
fi
echo -e "${CYAN}可用的硬盘:${NC}"
for i in "${!options[@]}"; do
echo -e " ${GREEN}$((i+1))${NC}) ${options[$i]}"
done
echo -e " ${GREEN}0${NC}) 取消"
while true; do
read -rp "请选择硬盘 [0-${#options[@]}]: " selection
if [[ "$selection" == "0" ]]; then
selected_disk=""
break
elif [[ "$selection" =~ ^[0-9]+$ ]] && [ "$selection" -ge 1 ] && [ "$selection" -le ${#options[@]} ]; then
selected_disk="${options[$((selection-1))]}"
break
else
echo -e "${RED}无效选择!请输入 0 到 ${#options[@]} 之间的数字${NC}"
fi
done
return 0
}
# 主程序
detect_disks
main_menu
EOF进入/root目录
cd /root
添加执行权限:
chmod +x disk_manager.sh
以root运行:
sudo ./disk_manager.sh