linux shell

关注公众号 jb51net

关闭
首页 > 脚本专栏 > linux shell > Linux parted管理大磁盘分区

Linux使用parted命令管理大磁盘分区

作者:知远漫谈

文章介绍了parted工具的基本使用方法,涵盖创建、调整和删除分区,支持大容量磁盘和多种分区表格式,还提供了Java调用示例、脚本自动化技巧,以及在企业级应用中的实践建议,强调操作前备份数据的重要性,并推荐了相关学习资源,需要的朋友可以参考下

在当今数据爆炸的时代,TB 级甚至 PB 级存储设备早已不是稀罕物。传统的 fdisk 工具面对超过 2TB 的磁盘时束手无策,这时候我们就需要更强大的工具 —— parted。本文将带你从零开始掌握 parted 的使用方法,涵盖基础操作、高级技巧、脚本自动化,并附带 Java 实际调用示例,助你成为 Linux 存储管理大师!

什么是 parted?

parted(Partition Editor)是一个功能强大的命令行磁盘分区工具,支持创建、删除、调整、移动和复制分区,尤其擅长处理大于 2TB 的 GPT 分区表磁盘。与 fdisk 相比,parted 支持多种分区表格式(如 MBR、GPT、BSD、DASD 等),并能直接操作文件系统边界。

# 查看 parted 版本
parted --version

小贴士:parted 默认以交互模式运行,但也可以通过 -s 参数执行非交互式命令,非常适合脚本自动化。

安装与基本语法

大多数现代 Linux 发行版默认已安装 parted。若未安装,可使用包管理器安装:

# Ubuntu/Debian
sudo apt install parted

# CentOS/RHEL/Fedora
sudo yum install parted
# 或
sudo dnf install parted

基本语法结构:

parted [选项] [设备] [命令 [参数]...]

常用选项:

列出当前磁盘信息

首先,我们查看系统中所有磁盘及其分区情况:

parted -l

输出示例:

Model: ATA WDC WD40EFRX-68N (scsi)
Disk /dev/sda: 4001GB
Sector size (logical/physical): 512B/4096B
Partition Table: gpt
Disk Flags:

Number  Start   End     Size    File system  Name                  Flags
 1      1049kB  538MB   537MB   fat32        EFI System Partition  boot, esp
 2      538MB   26.3GB  25.8GB  ext4
 3      26.3GB  4001GB  3975GB  ext4

注意:parted 中默认单位是 MB,可通过 unit 命令切换为 GB、TB、%、sectors 等。

创建新分区(实战演示)

假设我们有一块全新的 8TB 磁盘 /dev/sdb,我们需要为其创建 GPT 分区表并划分两个分区。

步骤 1:进入交互模式

parted /dev/sdb

步骤 2:创建分区表(GPT)

(parted) mklabel gpt

提示:MBR 最大仅支持 2TB,超过必须使用 GPT!

步骤 3:创建第一个分区(1TB)

(parted) mkpart primary ext4 0% 1TB

步骤 4:创建第二个分区(剩余空间)

(parted) mkpart primary ext4 1TB 100%

步骤 5:查看并退出

(parted) print
(parted) quit

调整分区大小

parted 支持在线调整分区大小(需配合文件系统工具如 resize2fs 使用)。

# 缩小第二分区到 5TB(先缩小文件系统!)
parted /dev/sdb resizepart 2 5TB

# 扩展第一分区到 2TB
parted /dev/sdb resizepart 1 2TB

重要提醒:调整分区前务必备份数据!部分文件系统不支持在线收缩。

删除分区

删除某个分区非常简单:

parted /dev/sdb rm 2

这会删除编号为 2 的分区。

使用 unit 设置单位

parted 支持灵活的单位设置,便于精确控制:

(parted) unit TB
(parted) print

(parted) unit %
(parted) print

(parted) unit s   # sectors
(parted) print

常用单位:

高级功能:设置分区标志

某些分区需要特殊标志,比如 EFI 分区或 LVM 标志:

# 设置分区 1 为 boot/esp
parted /dev/sdb set 1 boot on
parted /dev/sdb set 1 esp on

# 设置分区 2 为 LVM
parted /dev/sdb set 2 lvm on

可用标志列表:

自动化脚本示例

以下是一个 Bash 脚本,自动为新磁盘创建 GPT + 两个 ext4 分区:

#!/bin/bash

DISK="/dev/sdb"

echo ">>> 初始化磁盘 $DISK"
parted -s $DISK mklabel gpt

echo ">>> 创建分区 1 (2TB)"
parted -s $DISK mkpart primary ext4 0% 2TB

echo ">>> 创建分区 2 (剩余空间)"
parted -s $DISK mkpart primary ext4 2TB 100%

echo ">>> 格式化分区"
mkfs.ext4 ${DISK}1
mkfs.ext4 ${DISK}2

echo ">>> 挂载分区"
mkdir -p /mnt/data1 /mnt/data2
mount ${DISK}1 /mnt/data1
mount ${DISK}2 /mnt/data2

echo "✅ 完成!"

保存为 auto-partition.sh 并赋予执行权限:

chmod +x auto-partition.sh
./auto-partition.sh

Java 调用 parted 示例

虽然 parted 是命令行工具,但我们可以通过 Java 的 ProcessBuilderRuntime.exec() 来调用它,实现图形界面或 Web 后台管理。

示例 1:列出所有磁盘信息

import java.io.*;
public class PartedManager {
    public static void listDisks() {
        try {
            Process process = Runtime.getRuntime().exec("parted -l");
            BufferedReader reader = new BufferedReader(
                new InputStreamReader(process.getInputStream())
            );
            String line;
            System.out.println("=== 磁盘分区信息 ===");
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
            int exitCode = process.waitFor();
            if (exitCode == 0) {
                System.out.println("✅ 获取成功");
            } else {
                System.err.println("❌ 获取失败");
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        listDisks();
    }
}

示例 2:创建 GPT 分区表(需 root 权限)

import java.io.*;
public class CreateGPT {
    public static boolean createGPT(String device) {
        try {
            // 构建命令:parted -s /dev/sdX mklabel gpt
            ProcessBuilder pb = new ProcessBuilder("parted", "-s", device, "mklabel", "gpt");
            pb.redirectErrorStream(true); // 合并错误流
            Process process = pb.start();
            BufferedReader reader = new BufferedReader(
                new InputStreamReader(process.getInputStream())
            );
            StringBuilder output = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                output.append(line).append("\n");
            }
            int exitCode = process.waitFor();
            if (exitCode == 0) {
                System.out.println("✅ GPT 分区表创建成功:" + device);
                return true;
            } else {
                System.err.println("❌ 创建失败:" + output.toString());
                return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    public static void main(String[] args) {
        // 示例:为 /dev/sdb 创建 GPT
        createGPT("/dev/sdb");
    }
}

示例 3:完整分区创建流程(Java GUI 后端逻辑)

import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class DiskPartitioner {
    // 执行 shell 命令并返回输出
    private static String executeCommand(String... command) {
        try {
            ProcessBuilder pb = new ProcessBuilder(command);
            pb.redirectErrorStream(true);
            Process process = pb.start();
            BufferedReader reader = new BufferedReader(
                new InputStreamReader(process.getInputStream())
            );
            StringBuilder result = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                result.append(line).append("\n");
            }
            int exitCode = process.waitFor();
            if (exitCode != 0) {
                throw new RuntimeException("命令执行失败: " + result.toString());
            }
            return result.toString();
        } catch (Exception e) {
            throw new RuntimeException("执行命令异常: " + e.getMessage(), e);
        }
    }
    // 创建分区
    public static boolean createPartition(String device, int partitionNum, 
                                          String fsType, String start, String end) {
        try {
            System.out.printf(">>> 创建分区 %d: %s 从 %s 到 %s\n", 
                              partitionNum, fsType, start, end);
            executeCommand("parted", "-s", device, "mkpart", "primary", fsType, start, end);
            String partDevice = device + partitionNum;
            // 格式化
            System.out.println(">>> 格式化 " + partDevice + " 为 " + fsType);
            if ("ext4".equalsIgnoreCase(fsType)) {
                executeCommand("mkfs.ext4", "-F", partDevice);
            } else if ("xfs".equalsIgnoreCase(fsType)) {
                executeCommand("mkfs.xfs", "-f", partDevice);
            }
            System.out.println("✅ 分区创建完成: " + partDevice);
            return true;
        } catch (Exception e) {
            System.err.println("❌ 分区创建失败: " + e.getMessage());
            return false;
        }
    }
    // 主函数测试
    public static void main(String[] args) {
        String disk = "/dev/sdb";
        // 1. 创建 GPT
        System.out.println(">>> 初始化 GPT...");
        executeCommand("parted", "-s", disk, "mklabel", "gpt");
        // 2. 创建多个分区
        createPartition(disk, 1, "ext4", "0%", "2TB");
        createPartition(disk, 2, "xfs", "2TB", "6TB");
        createPartition(disk, 3, "ext4", "6TB", "100%");
        System.out.println("🎉 所有分区创建完毕!");
    }
}

性能与最佳实践

推荐做法:

对齐分区:现代 SSD 和 RAID 阵列建议从 1MiB 开始分区以确保对齐。

parted /dev/sdb mkpart primary ext4 1MiB 100%

使用百分比或明确单位:避免歧义。

备份分区表

sfdisk -d /dev/sdb > sdb-backup.txt

操作前卸载分区

umount /dev/sdb1

parted vs fdisk vs gdisk

工具支持 >2TB支持 GPT交互性易用性适用场景
fdisk⭐⭐⭐小磁盘、MBR
gdisk⭐⭐GPT 专用
parted✅/❌⭐⭐⭐⭐大磁盘、脚本、通用

常见错误与解决方案

错误 1:Error: The backup GPT table is corrupt...

# 修复 GPT 备份表
parted /dev/sdb rescue

或使用 gdisk

gdisk /dev/sdb
# 输入 'r' 进入恢复菜单,再输入 'v' 验证,'w' 写入修复

错误 2:Partition(s) on /dev/sdb are being used

# 查看谁在使用
lsof /dev/sdb1

# 卸载
umount /dev/sdb1

# 或强制卸载(危险!)
umount -l /dev/sdb1

错误 3:Unable to open /dev/sdb - Permission denied

# 使用 sudo
sudo parted /dev/sdb

或临时提升权限:

sudo -i
parted /dev/sdb

磁盘容量计算技巧

parted 中单位换算容易混淆,记住:

# 查看真实扇区数
parted /dev/sdb unit s print

# 计算总容量(字节)
# 总扇区数 × 扇区大小 = 总字节数

文件系统与 parted 配合

parted 只负责分区,不负责格式化。常用格式化命令:

# ext4
mkfs.ext4 /dev/sdb1

# xfs
mkfs.xfs /dev/sdb1

# btrfs
mkfs.btrfs /dev/sdb1

# swap
mkswap /dev/sdb1
swapon /dev/sdb1

导航磁盘:print, select, help

在交互模式下,这些命令非常实用:

(parted) print devices    # 列出所有设备
(parted) select /dev/sdc  # 切换当前设备
(parted) help mkpart      # 查看 mkpart 帮助
(parted) help             # 所有命令帮助

数据可视化:磁盘使用情况(mermaid 图表)

我们可以用 mermaid 绘制磁盘分区结构图,便于理解:

渲染错误: Mermaid 渲染失败: Parsing failed: unexpected character: ->“<- at offset: 38, skipped 3 characters. unexpected character: ->数<- at offset: 44, skipped 4 characters. unexpected character: ->:<- at offset: 49, skipped 1 characters. unexpected character: ->“<- at offset: 60, skipped 3 characters. unexpected character: ->日<- at offset: 66, skipped 3 characters. unexpected character: ->:<- at offset: 70, skipped 1 characters. unexpected character: ->“<- at offset: 81, skipped 3 characters. unexpected character: ->备<- at offset: 87, skipped 3 characters. unexpected character: ->:<- at offset: 91, skipped 1 characters. Expecting token of type 'EOF' but found `1`. Expecting token of type 'EOF' but found `2`. Expecting token of type 'EOF' but found `3`.

注:上图单位为 GB,实际可根据 parted print 输出动态生成。

动态调整分区实战

假设我们要将 /dev/sdb2 从 4TB 扩展到 6TB:

# 1. 先扩展分区边界(如果后面有空闲空间)
parted /dev/sdb resizepart 2 6TB

# 2. 扩展文件系统(ext4)
resize2fs /dev/sdb2

# 如果是 xfs
xfs_growfs /mount/point

不支持收缩 xfs!ext4 收缩前必须先卸载并检查:

umount /dev/sdb2
e2fsck -f /dev/sdb2
resize2fs /dev/sdb2 4T
parted /dev/sdb resizepart 2 4TB

LVM 与 parted 结合使用

parted 可以为 LVM 创建物理卷分区:

# 创建分区并标记为 LVM
parted /dev/sdb mkpart primary 0% 100%
parted /dev/sdb set 1 lvm on

# 创建物理卷
pvcreate /dev/sdb1

# 创建卷组
vgcreate vg_data /dev/sdb1

# 创建逻辑卷
lvcreate -L 5T -n lv_mysql vg_data

# 格式化挂载
mkfs.ext4 /dev/vg_data/lv_mysql
mount /dev/vg_data/lv_mysql /var/lib/mysql

安全测试:使用 loop 设备模拟大磁盘

无需真实大磁盘,可用文件模拟:

# 创建 10GB 文件
dd if=/dev/zero of=disk.img bs=1G count=10

# 关联为 loop 设备
sudo losetup -fP disk.img
sudo losetup -a  # 查看分配的设备,如 /dev/loop0

# 使用 parted 操作
sudo parted /dev/loop0 mklabel gpt
sudo parted /dev/loop0 mkpart primary ext4 0% 100%

# 格式化挂载
sudo mkfs.ext4 /dev/loop0p1
sudo mkdir /mnt/test
sudo mount /dev/loop0p1 /mnt/test

# 清理
sudo umount /mnt/test
sudo losetup -d /dev/loop0
rm disk.img

Java 图形界面封装思路

设想一个 Swing 界面,用户选择磁盘、输入分区大小、选择文件系统,点击“创建”后后台调用上述 Java 代码。

关键类设计:

public class PartitionTask {
    private String device;
    private List<PartitionConfig> partitions;
    public void execute() {
        // 1. 验证输入
        // 2. 执行 parted 创建分区表
        // 3. 循环创建每个分区
        // 4. 格式化
        // 5. 挂载(可选)
        // 6. 写入 /etc/fstab(可选)
    }
}
public class PartitionConfig {
    private int number;
    private String filesystem;
    private String start;
    private String end;
    private boolean mountAtBoot;
    private String mountPoint;
    // getters & setters...
}

持久化配置:写入 /etc/fstab

分区创建完成后,建议写入 fstab 实现开机自动挂载:

# 获取 UUID
blkid /dev/sdb1

# 编辑 /etc/fstab
UUID=xxxx-xxxx-xxxx /mnt/data1 ext4 defaults,noatime 0 2

Java 中可追加写入:

public static void addToFstab(String uuid, String mountPoint, String fsType) {
    String entry = String.format("UUID=%s %s %s defaults,noatime 0 2\n", 
                                 uuid, mountPoint, fsType);
    try (FileWriter fw = new FileWriter("/etc/fstab", true)) {
        fw.write(entry);
        System.out.println("✅ 已添加到 fstab: " + mountPoint);
    } catch (IOException e) {
        System.err.println("❌ 写入 fstab 失败: " + e.getMessage());
    }
}

生产环境请先备份原 fstab!

导航历史:parted 的 undo 功能?

很遗憾,parted 没有撤销功能!一旦写入即生效。

替代方案:

操作前备份分区表:

sfdisk -d /dev/sdb > backup-sdb.txt

出错后恢复:

sfdisk /dev/sdb < backup-sdb.txt

企业级应用场景

场景 1:数据库服务器部署

# 为 MySQL 创建独立分区
parted /dev/sdb mkpart primary ext4 0% 2TB   # 数据
parted /dev/sdb mkpart primary ext4 2TB 3TB  # 日志
parted /dev/sdb mkpart primary ext4 3TB 100% # 备份

场景 2:虚拟化平台存储池

# 为 KVM 虚拟机创建 RAW 存储
parted /dev/sdc mkpart primary 0% 100%
mkfs.xfs /dev/sdc1
mount /dev/sdc1 /var/lib/libvirt/images

网络存储中的 parted 应用

在 iSCSI 或 NFS 环境中,parted 同样适用:

# 连接 iSCSI 目标后,对 /dev/sdd 操作
parted /dev/sdd mklabel gpt
parted /dev/sdd mkpart primary xfs 0% 100%
mount /dev/sdd1 /mnt/iscsi-data

UEFI/GPT 启动分区设置

现代 Linux 安装推荐 UEFI + GPT:

parted /dev/sda mklabel gpt
parted /dev/sda mkpart ESP fat32 1MiB 513MiB
parted /dev/sda set 1 boot on
parted /dev/sda set 1 esp on
parted /dev/sda mkpart primary ext4 513MiB 100%

然后格式化 ESP:

mkfs.fat -F32 /dev/sda1

清理与重建分区表

彻底清空磁盘签名和分区表:

# 清除 GPT/MBR 签名
sgdisk --zap-all /dev/sdb

# 或使用 dd(危险!)
dd if=/dev/zero of=/dev/sdb bs=1M count=10

# 重建
parted /dev/sdb mklabel gpt

健康检查与 SMART

分区前建议检查磁盘健康:

smartctl -a /dev/sdb

Java 调用示例:

public static boolean isDiskHealthy(String device) {
    try {
        String output = executeCommand("smartctl", "-H", device);
        return output.contains("PASSED");
    } catch (Exception e) {
        return false;
    }
}

Docker 与容器中的磁盘管理

在容器中通常无法直接使用 parted(需要特权和设备访问),但可在宿主机操作后挂载给容器:

# 宿主机创建分区并格式化
parted /dev/sdb mkpart ...
mkfs.ext4 /dev/sdb1
mount /dev/sdb1 /docker-volumes/app-data

# 启动容器时挂载
docker run -v /docker-volumes/app-data:/data my-app

性能基准:不同文件系统对比

虽然不属于 parted 范畴,但分区后选择合适文件系统很重要:

文件系统优点缺点适用场景
ext4稳定、兼容性好不适合超大文件通用、桌面
xfs高并发、大文件性能优不支持收缩数据库、媒体存储
btrfs快照、压缩、RAID相对较新实验性、NAS
zfs企业级功能内存占用高企业存储

故障转移与高可用

在集群环境中,共享磁盘需谨慎分区:

# 在主节点操作
parted /dev/mapper/mpathb mklabel gpt
parted /dev/mapper/mpathb mkpart ...

# 所有节点扫描新分区
partprobe /dev/mapper/mpathb

避免多节点同时写入分区表!

总结:parted 的核心优势

  1. 支持超大磁盘(>2TB)
  2. 多分区表支持(GPT/MBR/BSD等)
  3. 脚本友好(-s 静默模式)
  4. 精确控制(扇区级操作)
  5. 跨平台(GNU/Linux、BSD、甚至 macOS)

掌握 parted,你就掌握了 Linux 存储世界的钥匙!

最后提醒

现在,你已经准备好征服任何规模的磁盘了!去创建、调整、管理你的存储王国吧!

Bonus Tip: 使用 lsblk -fdf -hT 配合 parted,获得完整的存储视图!

以上就是Linux使用parted命令管理大磁盘分区的详细内容,更多关于Linux parted管理大磁盘分区的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文