Administrator
Administrator
发布于 2024-09-29 / 14 阅读
1

Linux使用自动化脚本进行fdisk磁盘分区

最近遇到一个需要在linux中使用fdisk分区几十块盘,每块盘都要分15个分区的工作,为了提升效率写了一个自动化脚本,希望能帮到和我有一样遭遇的人。

#!/bin/bash

# 检查是否以 root 权限运行
if [ "$(id -u)" != "0" ]; then
    echo "This script must be run as root." 1>&2
    echo "此脚本必须以 root 权限运行。" 1>&2
    exit 1
fi

# 检查 fdisk 是否可用
if ! command -v fdisk &> /dev/null; then
    echo "Error: fdisk is not installed. Please install fdisk and try again."
    echo "错误:fdisk 未安装。请安装 fdisk 并重试。"
    exit 1
fi

# 检查 partprobe 是否可用
if ! command -v partprobe &> /dev/null; then
    echo "Warning: partprobe is not installed. Please install partprobe to ensure proper partition detection."
    echo "警告:partprobe 未安装。请安装 partprobe 以确保正确的分区检测。"
fi

# 初始化 force 标志
FORCE=false

# 解析选项参数
while getopts "f" opt; do
    case "$opt" in
        f) FORCE=true ;;
        *) 
            echo "Usage: $0 [-f] <device> <size1> <size2> ... <sizeN>"
            echo "用法:$0 [-f] <设备> <大小1> <大小2> ... <大小N>"
            exit 1
            ;;
    esac
done
shift $((OPTIND - 1))  # 跳过已处理的选项

# 至少需要2个参数(设备名和至少1个分区大小)
if [ "$#" -lt 2 ]; then
    echo "Usage: $0 [-f] <device> <size1> <size2> ... <sizeN>"
    echo "用法:$0 [-f] <设备> <大小1> <大小2> ... <大小N>"
    exit 1
fi

# 获取设备名
DISK=$1
shift

# 检查设备是否存在
if [ ! -b "$DISK" ]; then
    echo "Error: Device $DISK does not exist or is not a valid block device."
    echo "错误:设备 $DISK 不存在或不是有效的块设备。"
    exit 1
fi

# 获取分区大小参数
PARTITIONS=("$@")

# 确保不超过15个分区(3个主分区 + 12个逻辑分区)
if [ "${#PARTITIONS[@]}" -gt 15 ]; then
    echo "Error: Too many partitions. A disk can have a maximum of 15 partitions (3 primary + 12 logical)."
    echo "错误:分区过多。一个磁盘最多可以有 15 个分区(3 个主分区 + 12 个逻辑分区)。"
    exit 1
fi

# 验证分区大小的格式是否正确
for size in "${PARTITIONS[@]}"; do
    if ! [[ $size =~ ^[0-9]+[KMG]$ ]]; then
        echo "Error: Invalid partition size format: $size."
        echo "错误:无效的分区大小格式:$size。"
        echo "Partition sizes must be in a format like '10M', '20G', etc."
        echo "分区大小必须采用 '10M'、'20G' 等格式。"
        exit 1
    fi
done

# 检查磁盘是否存在分区
EXISTING_PARTS=$(fdisk -l $DISK 2>/dev/null | grep "^$DISK[0-9]")

if [ -n "$EXISTING_PARTS" ]; then
    echo "Warning: The disk $DISK already has partitions:"
    echo "警告:磁盘 $DISK 已经有分区:"
    fdisk -l $DISK | grep "^$DISK[0-9]"
    
    if [ "$FORCE" = false ]; then
        read -p "Do you want to continue and delete all existing partitions? [y/N]: " response
        read -p "您是否要继续并删除所有现有分区? [y/N]: " response
        case "$response" in
            [yY][eE][sS]|[yY])
                echo "Deleting all existing partitions on $DISK..."
                echo "正在删除 $DISK 上的所有现有分区..."
                ;;
            *)
                echo "Aborting script."
                echo "正在中止脚本。"
                exit 0
                ;;
        esac
    else
        echo "Force mode enabled. Deleting all existing partitions on $DISK..."
        echo "强制模式已启用。正在删除 $DISK 上的所有现有分区..."
    fi

    # 获取现有分区数量
    PART_NUM=$(fdisk -l $DISK | grep "^$DISK" | wc -l)
    
    # 循环删除每个分区
    for ((i=PART_NUM; i>0; i--)); do
        echo "Deleting partition $i..."
        echo "正在删除分区 $i..."
        fdisk $DISK <<EOF
d
$i
w
EOF
    done
fi

# 创建分区的逻辑
fdisk $DISK <<EOF
o
EOF

# 创建主分区
for i in $(seq 1 3); do
    if [ $i -le ${#PARTITIONS[@]} ]; then
        echo "Creating primary partition $i with size ${PARTITIONS[$((i-1))]}"
        echo "正在创建主分区 $i,大小为 ${PARTITIONS[$((i-1))]}"
        fdisk $DISK <<EOF
n
p
$i

+${PARTITIONS[$((i-1))]}
w
EOF
    fi
done

# 创建扩展分区(如果需要)
if [ ${#PARTITIONS[@]} -gt 3 ]; then
    echo "Creating extended partition..."
    echo "正在创建扩展分区..."
    fdisk $DISK <<EOF
n
e
4


w
EOF
fi

# 创建逻辑分区
if [ ${#PARTITIONS[@]} -gt 3 ]; then
    LOGICAL_PARTITIONS=("${PARTITIONS[@]:3}")
    for size in "${LOGICAL_PARTITIONS[@]}"; do
        echo "Creating logical partition with size $size"
        echo "正在创建逻辑分区,大小为 $size"
        fdisk $DISK <<EOF
n
l

+$size
w
EOF
    done
fi

# 刷新分区表,通知内核
if command -v partprobe &> /dev/null; then
    echo "Running partprobe to refresh partition table..."
    echo "正在运行 partprobe 刷新分区表..."
    partprobe $DISK
else
    echo "Warning: partprobe is not installed. You may need to reboot or run partprobe manually."
    echo "警告:partprobe 未安装。您可能需要重新启动或手动运行 partprobe。"
fi

# 显示最终的分区表
fdisk -l $DISK


# 获取磁盘总大小(单位为字节)
TOTAL_DISK_SIZE=$(fdisk -l $DISK 2>/dev/null | grep "Disk $DISK:" | awk '{print $5}')
if [[ -z "$TOTAL_DISK_SIZE" || ! "$TOTAL_DISK_SIZE" =~ ^[0-9]+$ ]]; then
    echo "Error: Could not determine the total disk size for $DISK."
    echo "错误:无法确定 $DISK 的总磁盘大小。"
    exit 1
fi

# 计算所有已用的分区大小
USED_DISK_SIZE=$(fdisk -l $DISK 2>/dev/null | grep Linux| awk '{used+=$4} END {print used}')
if [[ -z "$USED_DISK_SIZE" || ! "$USED_DISK_SIZE" =~ ^[0-9]+$ ]]; then
    USED_DISK_SIZE=0  # 如果没有分区,则使用 0
fi

# 比较剩余空间
if [ "$USED_DISK_SIZE" -lt "$TOTAL_DISK_SIZE" ]; then
    REMAINING_SPACE=$((TOTAL_DISK_SIZE / 1024 - USED_DISK_SIZE))

    # 将字节转换为GB (整数运算)
    REMAINING_SPACE_GB=$((REMAINING_SPACE / (1024 * 1024)))

    echo "================================================================="
    echo "警告: 磁盘上还有未使用的空间: $REMAINING_SPACE_GB GB。"
    echo "Warning: There is unused space left on the disk: $REMAINING_SPACE_GB GB."
fi