Linux 磁盘管理

磁盘查询

主要是 df 这个命令,经常用来查询系统中磁盘剩余空间。比如发现根目录 / 满了,说明系统危险了。

查询磁盘容量

使用 df 查看磁盘使用量,df 读取的是在 Superblock 内的信息。

例如查看系统内所有的文件系统:

[root@101c7 /]$ df -h
Filesystem               Size  Used Avail Use% Mounted on
devtmpfs                 1.9G     0  1.9G   0% /dev
tmpfs                    1.9G     0  1.9G   0% /dev/shm
tmpfs                    1.9G   12M  1.9G   1% /run
tmpfs                    1.9G     0  1.9G   0% /sys/fs/cgroup
/dev/mapper/centos-root   17G  2.1G   15G  13% /
/dev/sda1               1014M  187M  828M  19% /boot
tmpfs                    378M     0  378M   0% /run/user/0
/dev/sdb1                991M  1.3M  939M   1% /ext333

当查询目标是目录或文件时,df 会自动分析该目录所在分区,实际看到的是分区容量信息。

将所有特殊文件格式和名称(例如内存挂载点 /proc)都列出来,可以使用 -aT 参数:

[root@101c7 ext333]$ df -aT
Filesystem              Type        1K-blocks    Used Available Use% Mounted on
sysfs                   sysfs               0       0         0    - /sys
proc                    proc                0       0         0    - /proc
/dev/mapper/centos-root xfs          17811456 2724256  15087200  16% /
/dev/sda1               xfs           1038336  190536    847800  19% /boot
/dev/mapper/VG400-LV400 ext3           190145   63472    117934  35% /ext333

查询各分区中可用 inode 数量:

[root@101c7 /]$ df -ih
Filesystem              Inodes IUsed IFree IUse% Mounted on
/dev/mapper/centos-root   8.5M   46K  8.5M    1% /
/dev/sda1                 512K   335  512K    1% /boot
tmpfs                     472K     1  472K    1% /run/user/0
/dev/sdb1                  64K    13   64K    1% /ext333

列出分区信息

可以使用命令 lsblk 来查询所有储存设备。

例如查看当前系统下所有磁盘与分区情况:

[root@101c7 ext333]$ lsblk -i
NAME                 MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda                    8:0    0   20G  0 disk 
|-sda1                 8:1    0    1G  0 part /boot
`-sda2                 8:2    0   19G  0 part 
  |-centos-root      253:0    0   17G  0 lvm  /
  `-centos-swap      253:1    0    2G  0 lvm  [SWAP]

其中 MAJ:MIN 代表主要 : 次要设备代码,RM 标记是否为可移动(removable)设备,RO 为是否以只读挂载。

也可以只单独查询某个磁盘,用 -p 参数显示分区全名:

[root@101c7 ext333]$ lsblk -ip /dev/sda
NAME                        MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
/dev/sda                      8:0    0  20G  0 disk 
|-/dev/sda1                   8:1    0   1G  0 part /boot
`-/dev/sda2                   8:2    0  19G  0 part 
  |-/dev/mapper/centos-root 253:0    0  17G  0 lvm  /
  `-/dev/mapper/centos-swap 253:1    0   2G  0 lvm  [SWAP]

UUID(Universally Unique Identifier)是全域单一识别码,也可以用 UUID 来挂载设备。使用 blkid 命令来查询:

[root@101c7 ext333]$ blkid
/dev/mapper/centos-root: UUID="bb5b6906-0dff-46c4-832e-1701522802e6" TYPE="xfs" 
/dev/sda2: UUID="0lYfzD-6Mqj-AtC4-Jgf1-LGpk-ODIk-xbJIa7" TYPE="LVM2_member" 

磁盘分区

如果是 MBR 分区表,使用 fdisk 分区;GPT 分区使用 gdisk 分区。两种工具在使用方法上没有区别。这里使用 fdisk 演示。

查看分区

例如,查看系统内的所有分区:

[root@101c7 ext333]$ fdisk -l
Disk /dev/sda: 21.5 GB, 21474836480 bytes, 41943040 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x000a3a75

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *        2048     2099199     1048576   83  Linux
/dev/sda2         2099200    41943039    19921920   8e  Linux LVM

Disk /dev/mapper/centos-root: 18.2 GB, 18249416704 bytes, 35643392 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes


Disk /dev/mapper/centos-swap: 2147 MB, 2147483648 bytes, 4194304 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

由上述信息可见,sda 分了两个区,其中 sda 可做启动引导。

对新增的磁盘 sdb 进行操作:

[root@101c7 ext333]$ fdisk /dev/sdb
Welcome to fdisk (util-linux 2.23.2).

Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


Command (m for help): 

进入 fdisk 后输入 m 可以查看帮助。常用命令有:d 删除分区,n 新增分区,p 显示分区表,w 写入分区信息并退出。

先看看分区状态:

Command (m for help): p

Disk /dev/sdb: 1073 MB, 1073741824 bytes, 2097152 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x2de15e6d

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1            2048     2097151     1047552   83  Linux

由上表中可以看到:磁盘大小 1073 MB,扇区数 2097152,每个扇区大小 512 Bytes,分区开始扇区号 2048,截止扇区号 2097151,block 数(1KB 为单位)1047552。

删除分区

假设要删除 sdb1 分区,在等待命令页面输入 d 会提示要删除的分区编号(sdb 后面带的数字):

Command (m for help): d
Selected partition 1
Partition 1 is deleted

再次查看分区已经被删除了,保存退出:

Command (m for help): w
The partition table has been altered!

新增分区

输入 n 以后会进入新建分区交互界面:

  1. 选择新增的分区类型是主分区 p
  2. 设置为 4 号;
  3. 起始扇区号采用默认 2048;
  4. 结束扇区号可以输入扇区号,也可以输入大小,这里输入 +100M 大小:
Command (m for help): n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p
Using default response p
Partition number (1-4, default 1): 4
First sector (2048-2097151, default 2048): 
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-2097151, default 2097151): +100M
Partition 4 of type Linux and of size 100 MiB is set

再新增一个 200M 大小的扩展分区:

Command (m for help): n
Partition type:
   p   primary (1 primary, 0 extended, 3 free)
   e   extended
Select (default p): e
Partition number (1-3, default 1): 1
First sector (206848-2097151, default 206848): 
Using default value 206848
Last sector, +sectors or +size{K,M,G} (206848-2097151, default 2097151): +200M
Partition 1 of type Extended and of size 200 MiB is set

完成后输入 p 查看状态:

Command (m for help): p

Disk /dev/sdb: 1073 MB, 1073741824 bytes, 2097152 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x951d99c8

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1          206848      616447      204800    5  Extended
/dev/sdb4            2048      206847      102400   83  Linux

Partition table entries are not in disk order

可以看到有个主分区名字为 sdb4,扩展分区名为 sdb1,是我们手动设定的样子。

在扩展分区上建立个 80M 大小的逻辑分区,选择类型时输入 l,系统会自动分配分区号:

Command (m for help): n
Partition type:
   p   primary (1 primary, 1 extended, 2 free)
   l   logical (numbered from 5)
Select (default p): l
Adding logical partition 5
First sector (208896-616447, default 208896): 
Using default value 208896
Last sector, +sectors or +size{K,M,G} (208896-616447, default 616447): +80M
Partition 5 of type Linux and of size 80 MiB is set

完成后输入 w 保存更改并退出:

Command (m for help): w

提示说要重启让改动生效,可以使用 partprobe 命令让内核重新扫描分区表:

[root@101c7 ext333]$ partprobe -s
/dev/sda: msdos partitions 1 2
/dev/sdb: msdos partitions 1 2 3 4
/dev/sdc: msdos partitions 1
/dev/sr0: msdos partitions 2

下面展示使用 gdisk 制作一个 500MB 大小 GPT 分区的过程:

[root@101c7 ext333]$ gdisk /dev/sdd
GPT fdisk (gdisk) version 0.8.10

Command (? for help): n
Partition number (1-128, default 1): 1
First sector (34-2097118, default = 2048) or {+-}size{KMGTP}: 
Last sector (2048-2097118, default = 2097118) or {+-}size{KMGTP}: +500MB
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300): 
Changed type of partition to 'Linux filesystem'

Command (? for help): w

Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!

Do you want to proceed? (Y/N): y
OK; writing new GUID partition table (GPT) to /dev/sdd.
The operation has completed successfully.
[root@101c7 ext333]$ partprobe -s
/dev/sda: msdos partitions 1 2
/dev/sdb: msdos partitions 1 2 3 4
/dev/sdc: msdos partitions 1
/dev/sdd: gpt partitions 1
/dev/sr0: msdos partitions 2

格式化分区

建立分区后要格式化分区才可使用,格式化通过 mkfs 类命令操作。

将 sdb4 格式化成 ext3 文件系统:

[root@101c7 ~]$ mkfs -t ext3 /dev/sdb4 
mke2fs 1.42.9 (28-Dec-2013)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
25688 inodes, 102400 blocks
5120 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=67371008
13 block groups
8192 blocks per group, 8192 fragments per group
1976 inodes per group
Superblock backups stored on blocks: 
        8193, 24577, 40961, 57345, 73729

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done

如果要指定 label,block 大小,inode 数量等参数,需要使用 mke2fs 命令。

例如将 sdb4 设定卷标 boss,block 大小 2048,每 8192 bytes 分配一个 inode 后格式化成 ext3 文件系统:

[root@101c7 ~]$ mke2fs -j -L "boss" -b 2048 -i 8192 /dev/sdb4

设置文件系统不区分大小写:

[root@101c7 ~]$ mkfs.xfs -L datavolume -f -n version=ci /dev/md0

mkfs.xfs 格式化 xfs 文件系统,要设定具体分区数值可用 -d 参数。指定储存区群组数量为 16 并强制格式化 sdd1:

[root@101c7 ext333]$ mkfs.xfs -f -d agcount=16 /dev/sdd1
meta-data=/dev/sdd1              isize=512    agcount=16, agsize=8000 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=0, sparse=0
data     =                       bsize=4096   blocks=128000, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal log           bsize=4096   blocks=855, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

新建 swap 分区

swap 内存交换空间用来在系统内存不足时,替代内存使用的硬盘空间。虽然内存不足的情况已经很少发生,但有些旧程序会要求使用 swap 分区,或者作为出现内存溢出等异常状态时缓冲一下,还是有必要建一个的。

下面将在 sdb 上使用空闲容量新建一个 256MB 大小的 swap 分区(代码 82):

Command (m for help): n
Partition type:
   p   primary (1 primary, 1 extended, 2 free)
   l   logical (numbered from 5)
Select (default p): p
Partition number (2,3, default 2): 
First sector (616448-2097151, default 616448): 
Using default value 616448
Last sector, +sectors or +size{K,M,G} (616448-2097151, default 2097151): +256M
Partition 2 of type Linux and of size 256 MiB is set

Command (m for help): t
Partition number (1,2,4,5, default 5): 2
Hex code (type L to list all codes): 82
Changed type of partition 'Linux' to 'Linux swap / Solaris'

Command (m for help): w
The partition table has been altered!

[root@101c7 tinycore_iso]$ partprobe

也可以使用 dd 命令来创建一个空文件,当作 swap 分区使用。

使用 mkswap 格式化:

[root@101c7 tinycore_iso]$ mkswap /dev/sdb2
Setting up swapspace version 1, size = 262140 KiB
no label, UUID=2cfd898c-2b54-467b-94a4-96c29567cb7d

接着用 swapon 命令加载 swap:

[root@101c7 tinycore_iso]$ free
              total        used        free      shared  buff/cache   available
Mem:        3861280      248320     3108468       11880      504492     3329556
Swap:       2097148           0     2097148
[root@101c7 tinycore_iso]$ swapon /dev/sdb2
[root@101c7 tinycore_iso]$ free
              total        used        free      shared  buff/cache   available
Mem:        3861280      248636     3108120       11880      504524     3329304
Swap:       2359288           0     2359288

可以查看到已经在使用的 swap 设备有哪些:

[root@101c7 tinycore_iso]$ swapon -s
Filename                                Type            Size    Used    Priority
/dev/dm-1                               partition       2097148 0       -2
/dev/sdb2                               partition       262140  0       -3

如果要开机启动记得修改 /etc/fstab 文件来开机挂载。

使用 swapoff 来关掉 swap file:

[root@101c7 ~]$ swapoff /dev/sdb2; swapon -s
Filename                                Type            Size    Used    Priority
/dev/dm-1                               partition       2097148 0       -2

大容量磁盘分区

由于 fdisk 无法支持 2TB 以上的分区,可以使用 parted 程序来分区,它同时支持 MBR 和 GPT 两种分区表格式。

查看当前的分区表资料:

[root@101c7 2]$ parted /dev/sdb print
Model: VMware, VMware Virtual S (scsi)
Disk /dev/sdb: 1074MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags: 

Number  Start   End    Size    Type      File system     Flags
4      1049kB  106MB  105MB   primary   ext3
1      106MB   316MB  210MB   extended
5      107MB   191MB  83.9MB  logical
2      316MB   584MB  268MB   primary   linux-swap(v1)

新建一个 ext3 格式 110M 大小的逻辑分区:

[root@101c7 2]$ parted /dev/sdb mkpart logical ext3 191MB 301MB
Warning: The resulting partition is not properly aligned for best performance.
Ignore/Cancel? Ignore                                                     
Information: You may need to update /etc/fstab.

[root@101c7 2]$ parted /dev/sdb print
Model: VMware, VMware Virtual S (scsi)
Disk /dev/sdb: 1074MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags: 

Number  Start   End    Size    Type      File system     Flags
4      1049kB  106MB  105MB   primary   ext3
1      106MB   316MB  210MB   extended
5      107MB   191MB  83.9MB  logical
6      191MB   301MB  110MB   logical
2      316MB   584MB  268MB   primary   linux-swap(v1)

删除刚刚新建的 sdb6 分区:

[root@101c7 2]$ parted /dev/sdb rm 6
Information: You may need to update /etc/fstab.

磁盘工具

主要包括一些读写性能测试,文件系统修复等工具。

Ext 磁盘扫描

Ext 文件系统可使用 fsck 来对磁盘进行扫描,检查文件系统错误。通常情况下只有出现问题才使用这个命令。

例如进入到单用户模式下,被检查的分区务必不可挂载到系统上,否则可能造成部分文件系统损坏。

可用参数:

选项 说明
-C 检验过程中显示进度
-f 强制检查,将所有状态为 clean 的扇区也纳入检查范围
-D 针对文件系统下的目录进行优化配置
-p 自动修复文件系统存在的问题
-b 接 superblock 位置,用来恢复主 superblock。一般备份在 1K=8193 / 2K=16384 / 4k=32768 位置
-c 对文件系统进行坏块检查,并添加到坏块列表中。

检查 sdb4 分区:

[root@101c7 ~]$ fsck -C -f /dev/sdb4
fsck from util-linux 2.23.2
e2fsck 1.42.9 (28-Dec-2013)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure                                           
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
boss: 11/12800 files (0.0% non-contiguous), 5076/51200 blocks

使用备份恢复 sdb4 损坏的 superblock:

[root@101c7 ext333]$ fsck.ext3 -b 32768 /dev/sdb4

Xfs 磁盘扫描

xfs 文件系统扫描使用 xfs_repair 工具。可用选项:

选项 说明
-f 后面接文件文件而不是磁盘
-n 单纯检查并不修改文件系统的任何数据
-d 通常用在救援模式下面对根目录进行检查与修复的动作

修复时同样要求先卸载目标分区,例如检查 /dev/sdd1

[root@101c7 ext333]$ xfs_repair /dev/sdd1
Phase 1 - find and verify superblock...
Phase 2 - using internal log
Phase 3 - for each AG...
Phase 4 - check for duplicate blocks...
Phase 5 - rebuild AG headers and trees...
Phase 6 - check inode connectivity...
Phase 7 - verify and correct link counts...
done

坏道扫描

badblocks 命令用来检测硬盘扇区有没有坏道。其实等于 mke2fs -c 在进行格式化时处理磁盘表面的读取测试。

例如检查 sdb4 分区:

[root@101c7 ~]$ badblocks -sv /dev/sdb4
Checking blocks 0 to 102399
Checking for bad blocks (read-only test): done                                                 
Pass completed, 0 bad blocks found. (0/0/0 errors)

修改设备代码

有时需要手动处理设备文件,可以使用 mknod 命令来修改设备代码。

可修改的设备种类有 b(外部储存,移动硬盘),c(外部输入,鼠标),p(FIFO 文件)。

常见磁盘设备代码如下:

磁盘文件名 Major Minor
/dev/sda 8 0-15
/dev/sdb 8 16-31
/dev/loop0 7 0
/dev/loop1 7 1

例如创建 sdb5 的设备代码 Maj:Min 为 8,21:

[root@101c7 ~]$ mknod /dev/sdb5 b 8 21; ll /dev/sdb5
brw-rw----. 1 root disk 8, 21 Sep 10 04:08 /dev/sdb5

修改分区卷标

可以使用 e2label 来修改 ext 文件系统卷标(Label),卷标类似与 Win 中的 本地磁盘

例如修改 sdb4 的卷标为 P1

[root@101c7 ~]$ e2label /dev/sdb4 "P1"
[root@101c7 ~]$ dumpe2fs -h /dev/sdb4 | grep name
dumpe2fs 1.42.9 (28-Dec-2013)
Filesystem volume name:   P1

也可使用 tune2fs 命令来修改:

[root@101c7 ext333]$ tune2fs -L P2 /dev/sdb4

修改 UUID

XFS 文件系统使用 UUID 作为标识符,可以使用 xfs_admin 命令修改 UUID 和 Label。

例如修改 sdd1 的 Label name 为 xfs1:

[root@101c7 ext333]$ xfs_admin -L xfs1 /dev/sdd1
writing all SBs
new label = "xfs1"

修改 UUID 需要先生成 UUID 号码,可以使用 uuidgen 命令生成,然后再设置到 sdd1 上:

[root@101c7 ext333]$ xfs_admin -U $(uuidgen) /dev/sdd1
Clearing log and setting UUID
writing all SBs
new UUID = c96b6650-756a-4496-bf26-6e7286c55891

磁盘阵列

使用 mdadm 软件模拟磁盘整列 RAID。如果需要监控 mdadm 建立的软磁盘阵列,可以使用 mdmonitor 服务。

组建软磁盘阵列

使用 mdadm 命令来设置软磁盘阵列,语法如下:

mdadm --detail /dev/md0

mdadm --create --auto=yes /dev/md[0-9] --raid-devices=N --level=[015] --chuck=NK --spare-devices=N /dev/sdx /dev/hdx...

主要参数:

参数 说明
–create 新建 RAID 的参数
–auto=yes 决定新建后面接的软磁盘阵列设备,如 /dev/md0
–chunk=Nk 决定这个设备的 chunk 大小,一般是 64K 或 512K
–raid-devices=N 使用 N 个磁盘组件阵列
–spare-devices=N 使用 N 个磁盘作为备用设备
–level=[015] 设置磁盘阵列的等级
–detail 查询磁盘阵列设备的信息

例如用组建 RAID 5 环境,每个分区为 10MB 大小(sdb6-9),有一块热备盘(sdb10),一块闲置盘(sdb11):

[root@101c7 ~]$ mdadm --create --auto=yes /dev/md0 --level=5 --chunk=512K --raid-devices=4 --spare-devices=1 /dev/sdb{6,7,8,9,10}
mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md0 started.

如果设置错误,可以使用 mdadm --zero-superblock DEVICE 命令来清空每个组成磁盘的超级块区。

查看组建好的软 RAID 5 设备 /dev/md0

[root@101c7 ~]$ mdadm --detail /dev/md0
/dev/md0:
           Version : 1.2
     Creation Time : Mon Sep 13 15:24:49 2021
        Raid Level : raid5
        Array Size : 24576 (24.00 MiB 25.17 MB)
     Used Dev Size : 8192 (8.00 MiB 8.39 MB)
      Raid Devices : 4
     Total Devices : 5
       Persistence : Superblock is persistent

       Update Time : Mon Sep 13 15:24:50 2021
             State : clean 
    Active Devices : 4
   Working Devices : 5
    Failed Devices : 0
     Spare Devices : 1

            Layout : left-symmetric
        Chunk Size : 512K

Consistency Policy : resync

              Name : 101c7:0  (local to host 101c7)
              UUID : f64354f8:cf945331:eee97c66:84776736
            Events : 18

    Number   Major   Minor   RaidDevice State
       0       8       22        0      active sync   /dev/sdb6
       1       8       23        1      active sync   /dev/sdb7
       2       8       24        2      active sync   /dev/sdb8
       5       8       25        3      active sync   /dev/sdb9

       4       8       26        -      spare   /dev/sdb10

也可以通过 /proc/mdstat 文件查看磁盘阵列情况:

[root@101c7 ~]$ cat /proc/mdstat 
Personalities : [raid6] [raid5] [raid4] 
md0 : active raid5 sdb9[5] sdb10[4](S) sdb8[2] sdb7[1] sdb6[0]
      24576 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/4] [UUUU]
      
unused devices: <none>

格式化并挂载 RAID 到 /mnt/raid

[root@101c7 ~]$ mkfs -t ext3 /dev/md0
[root@101c7 ~]$ mkdir /mnt/raid ; mount /dev/md0 /mnt/raid ; df | grep 'md0'
/dev/md0                    22773     209     21336   1% /mnt/raid

如果格式化成 xfs 格式,可以手动设置 su 和 sw 值:

[root@101c7 ~]$ mkfs.xfs -f -d su=512k, sw=3 -r extsize=1536k /dev/md0

恢复磁盘阵列数据

mdadm 命令救援模式语法为:

mdadm --manage /dev/md[0-9] [--add 设备] [--remove 设备] [--fail 设备]

模拟磁盘出错可以使用 --fail 参数,模拟 sdb6 出错:

[root@101c7 mnt]$ mdadm --manage /dev/md0 --fail /dev/sdb6
mdadm: set /dev/sdb6 faulty in /dev/md0

再次查看 RAID 状态:

[root@101c7 mnt]$ cat /proc/mdstat
Personalities : [raid6] [raid5] [raid4] 
md0 : active raid5 sdb9[5] sdb10[4] sdb8[2] sdb7[1] sdb6[0](F)
      24576 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/4] [UUUU]
      
unused devices: <none>

磁盘阵列已经自动恢复好了。将闲置磁盘 sdb11 替换掉损坏的 sdb6:

[root@101c7 mnt]$ mdadm --manage /dev/md0 --add /dev/sdb11 --remove /dev/sdb6
mdadm: added /dev/sdb11
mdadm: hot removed /dev/sdb6 from /dev/md0

自动挂载 RAID

设置 /etc/mdadm.conf 文件来将 RAID 设备自动挂载:

[root@101c7 mnt]$ mdadm --detail /dev/md0 | grep -i uuid
              UUID : f64354f8:cf945331:eee97c66:84776736
[root@101c7 mnt]$ vi /etc/mdadm.conf
ARRAY /dev/md0 UUID=f64354f8:cf945331:eee97c66:84776736
[root@101c7 mnt]$ vi /etc/fstab
/dev/md0        /mnt/raid       ext3    defaults        1       2
[root@101c7 mnt]$ umount /dev/md0; mount -a
[root@101c7 mnt]$ df /mnt/raid
Filesystem     1K-blocks  Used Available Use% Mounted on
/dev/md0           22773   212     21333   1% /mnt/raid

关闭软 RAID

先删除配置文件 /etc/fstab/dev/md0 的挂载行:

[root@101c7 mnt]$ vi /etc/fstab
# /dev/md0      /mnt/raid       ext3    defaults        1       2

卸载 /dev/md0 并关闭:

[root@101c7 mnt]$ umount /dev/md0
[root@101c7 mnt]$ mdadm --stop /dev/md0
mdadm: stopped /dev/md0

如果要重新启用使用 mdadm --assemble --scan /dev/md0 命令。

最后删除 /etc/mdadm.conf 中与 md0 有关的内容:

[root@101c7 mnt]$ vi /etc/mdadm.conf 
# ARRAY /dev/md0 UUID=f64354f8:cf945331:eee97c66:84776736

LVM

如果安装系统分区使用默认配置,系统会自动建立 LVM 格式。

建立 PV

首先用 fdisk 建立分区,假设四个分区为 sdb1-4,然后用 fdisk 依次更改 system ID8e

[root@101c7 ~]$ fdisk /dev/sdb
Welcome to fdisk (util-linux 2.23.2).

Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


Command (m for help): p

Disk /dev/sdb: 1073 MB, 1073741824 bytes, 2097152 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x0006fb94

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1            2048      206847      102400   8e  Linux LVM
/dev/sdb2          206848      411647      102400   8e  Linux LVM
/dev/sdb3          411648      616447      102400   8e  Linux LVM
/dev/sdb4          616448      821247      102400   8e  Linux LVM

Command (m for help): t
Partition number (1-4, default 4): 1
Hex code (type L to list all codes): 8e
Changed type of partition 'Linux LVM' to 'Linux LVM'

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.

配置好后更新系统:

[root@101c7 ~]$ partprobe

PV 有关的命令有下面这些:

命令 作用
pvcreate 将物理分区新建成 PV
pvscan 查询目前系统里的 PV
pvdisplay 显示出目前系统上面的 PV 状态
pvremove 将 PV 属性删除

先使用 pvcreate 命令将 sdb1-4 转换成 PV:

[root@101c7 ~]$ pvcreate /dev/sdb{1,2,3,4}
WARNING: ext3 signature detected on /dev/sdb1 at offset 1080. Wipe it? [y/n]: y
  Wiping ext3 signature on /dev/sdb1.
WARNING: dos signature detected on /dev/sdb2 at offset 510. Wipe it? [y/n]: y
  Wiping dos signature on /dev/sdb2.
WARNING: swap signature detected on /dev/sdb4 at offset 4086. Wipe it? [y/n]: y
  Wiping swap signature on /dev/sdb4.
  Physical volume "/dev/sdb1" successfully created.
  Physical volume "/dev/sdb2" successfully created.
  Physical volume "/dev/sdb3" successfully created.
  Physical volume "/dev/sdb4" successfully created.

然后使用 pvscan 查询已存在的 PV:

[root@101c7 ~]$ pvscan
  PV /dev/sda2   VG centos          lvm2 [<19.00 GiB / 0    free]
  PV /dev/sdb2                      lvm2 [100.00 MiB]
  PV /dev/sdb1                      lvm2 [100.00 MiB]
  PV /dev/sdb3                      lvm2 [100.00 MiB]
  PV /dev/sdb4                      lvm2 [100.00 MiB]
  Total: 5 [<19.39 GiB] / in use: 1 [<19.00 GiB] / in no VG: 4 [400.00 MiB]

最后 pvdisplay 查看每个 PV 的详细信息,确认准确无误:

[root@101c7 ~]$ pvdisplay
"/dev/sdb2" is a new physical volume of "100.00 MiB"
  --- NEW Physical volume ---
  PV Name               /dev/sdb2
  VG Name               
  PV Size               100.00 MiB
  Allocatable           NO
  PE Size               0   
  Total PE              0
  Free PE               0
  Allocated PE          0
  PV UUID               0pMJ0Q-1h7w-1fMb-OTKS-Xqa5-sjQj-XSUdSi

建立 VG

与 VG 相关的命令有下面这些:

命令 作用
vgcreate 新建 VG 的命令
vgscan 查找系统上的 VG
vgdisplay 显示系统上的 VG 状态
vgextend 在 VG 内增加额外 PV
vgreduce 在 VG 内删除 PV
vgchange 设置 VG 是否启动 (active)
vgremove 删除一个 VG

新建 VG 使用 vgcreate 命令的语法如下:

vgcreate [-s PE大小[MGT]] VG名称 PV名称

/dev/sdb1-3 新建成一个 VG 名为 VG400,并指定 PE 为 4MB:

[root@101c7 ~]$ vgcreate -s 4M VG400 /dev/sdb{1,2,3}
  Volume group "VG400" successfully created

查看 VG 和 PV 的信息:

[root@101c7 ~]$ vgscan
  Reading volume groups from cache.
  Found volume group "centos" using metadata type lvm2
  Found volume group "VG400" using metadata type lvm2
[root@101c7 ~]$ pvscan
  PV /dev/sda2   VG centos          lvm2 [<19.00 GiB / 0    free]
  PV /dev/sdb1   VG VG400           lvm2 [96.00 MiB / 96.00 MiB free]
  PV /dev/sdb2   VG VG400           lvm2 [96.00 MiB / 96.00 MiB free]
  PV /dev/sdb3   VG VG400           lvm2 [96.00 MiB / 96.00 MiB free]
  PV /dev/sdb4                      lvm2 [100.00 MiB]
  Total: 5 [<19.38 GiB] / in use: 4 [<19.28 GiB] / in no VG: 1 [100.00 MiB]
[root@101c7 ~]$ vgdisplay
--- Volume group ---
  VG Name               VG400
  System ID             
  Format                lvm2
  Metadata Areas        3
  Metadata Sequence No  1
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                0
  Open LV               0
  Max PV                0
  Cur PV                3
  Act PV                3
  VG Size               288.00 MiB
  PE Size               4.00 MiB
  Total PE              72
  Alloc PE / Size       0 / 0   
  Free  PE / Size       72 / 288.00 MiB
  VG UUID               mWWhO0-wuDl-z62s-BPZZ-L1Ck-0Pbs-DNTCIf

可以看到 3 个 PV 已经加入到 VG400 当中了,VG 容量 288MB,PE 大小 4MB,总共有 72 个 PV。

要给 VG 扩容,将剩下的 sdb4 加入到 VG400 中可以使用 vgextend 命令:

[root@101c7 ~]$ vgextend VG400 /dev/sdb4
  Volume group "VG400" successfully extended

建立 LV

和 LV 有关的命令如下:

命令 作用
lvcreate 新建 LV
lvscan 查询系统上的 LV
lvdisplay 显示系统上的 LV 状态
lvextend 在 LV 里面增加容量
lvreduce 在 LV 里面减少容量
lvremove 删除一个 LV
lvresize 对 LV 进行容量大小调整

建立 LV 使用命令 lvcreate 基本语法如下:

lvcreate [-L 容量[MGT]] [-n LV名称] VG名称

lvcreate [-l PE个数] [-n LV名称] VG名称

将整个 VG400 分配给 LV400(不带 -l 参数默认会分配全部容量):

[root@101c7 ~]$ lvcreate -l 96 -n LV400 VG400
  Logical volume "LV400" created.
[root@101c7 ~]$ lvdisplay
  --- Logical volume ---
  LV Path                /dev/VG400/LV400
  LV Name                LV400
  VG Name                VG400
  LV UUID                21Hgtc-LzS0-2XvL-XiXD-3DPd-94Cu-zQfcvU
  LV Write Access        read/write
  LV Creation host, time 101c7, 2021-09-13 17:26:08 -0400
  LV Status              available
  # open                 0
  LV Size                384.00 MiB
  Current LE             96
  Segments               4
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     8192
  Block device           253:2

LV400 格式化成 ext3 并挂载到 /ext333

[root@101c7 ~]$ mkfs.ext3 /dev/VG400/LV400 
[root@101c7 ~]$ mount /dev/VG400/LV400 /ext333/
[root@101c7 ~]$ df
Filesystem              1K-blocks    Used Available Use% Mounted on
devtmpfs                  1918780       0   1918780   0% /dev
tmpfs                     1930640       0   1930640   0% /dev/shm
tmpfs                     1930640   11924   1918716   1% /run
tmpfs                     1930640       0   1930640   0% /sys/fs/cgroup
/dev/mapper/centos-root  17811456 2598096  15213360  15% /
/dev/sda1                 1038336  190536    847800  19% /boot
tmpfs                      386128       0    386128   0% /run/user/0
/dev/mapper/VG400-LV400    372615    2095    350860   1% /ext333

LVM 扩容

扩容分为以下步骤:

  1. fdisk 设置新分区 system ID 为 8e;
  2. 利用 pvcreate 构建 PV;
  3. 利用 vgextend 将 PV 加入 VG;
  4. 利用 lvresize 将新加入 VG 内的 PE 加入到 LV 中;
  5. 利用 resize2fs 将文件系统容量增加。

先扫描新增加的 SCSI 接口硬盘:

[root@101c7 ~]$ echo "- - -" > /sys/class/scsi_host/host0/scan

对新扫描到的硬盘 /dev/sdc 进行分区,并设置 8e 标志:

[root@101c7 ~]$ fdisk /dev/sdc
Command (m for help): n
Command (m for help): t
Hex code (type L to list all codes): 8e
Command (m for help): w
[root@101c7 ~]$ partprobe

通过 sdc1 建立 PV:

[root@101c7 ~]$ pvcreate /dev/sdc1

sdc1 加入到 VG400 中:

[root@101c7 ~]$ vgextend VG400 /dev/sdc1

使用 lvresize 命令对 LV400 进行扩容。如果要使用所有空闲容量可以使用 +100%FREE 参数:

[root@101c7 ~]$ lvresize -l +255 /dev/VG400/LV400 
  Size of logical volume VG400/LV400 changed from 384.00 MiB (96 extents) to 1.37 GiB (351 extents).
  Logical volume VG400/LV400 successfully resized.

最后使用 resize2fs 扩容:

[root@101c7 ~]$ resize2fs /dev/VG400/LV400 
resize2fs 1.42.9 (28-Dec-2013)
Filesystem at /dev/VG400/LV400 is mounted on /ext333; on-line resizing required
old_desc_blocks = 2, new_desc_blocks = 6
The filesystem on /dev/VG400/LV400 is now 1437696 blocks long.

xfs 文件系统使用的是 xfs_growfs 命令:

[root@101c7 ~]$ xfs_growfs /dev/VG400/LV400

LVM 缩容

XFS 文件系统不支持缩容。如果要进行缩容,需要将 /dev/sdc1 抽出来,首先需要 umount 挂载点:

[root@101c7 ~]$ umount /ext333/

然后对 LV400 运行磁盘检查:

[root@101c7 ~]$ e2fsck -f /dev/VG400/LV400

resize2fs 命令对 LV400 的容量进行缩减 sdc1 的大小:

[root@101c7 ~]$ resize2fs /dev/VG400/LV400 200M

重新挂载 LV400/ext333

[root@101c7 ~]$ mount /dev/VG400/LV400 /ext333/

去除 sdc1 上的 PE 数 255

[root@101c7 ~]$ lvresize -l -255 /dev/VG400/LV400

转移 sdc1 上 PE 的数据到 sdb2pvmove 同样可以用来在想要更换物理磁盘时使用:

[root@101c7 ~]$ pvmove /dev/sdc1 /dev/sdb2

sdc1 移出 VG400

[root@101c7 ~]$ vgreduce VG400 /dev/sdc1

最后删除 sdc1 上的 pv 标记:

[root@101c7 ~]$ pvremove /dev/sdc1

LVM Thin Volume

LVM Thin Volume 先创建一个磁盘容量储存池(Thin Pool),再由这个储存池去产生一个指定要固定容量大小的 LV 设备,它可以设定任意大小,但在需要用到时才从储存池划取所需容量。只要实际用量不超过储存池总容量就行。

先从 VG400 的剩余容量中取出 100 MB 来创建储存池 vpool

[root@101c7 ~]$ lvcreate -L 100M -T /dev/VG400/vpool
  Thin pool volume with chunk size 64.00 KiB can address at most 15.81 TiB of data.
  Logical volume "vpool" created.
[root@101c7 ~]$ lvdisplay /dev/VG400/vpool
  --- Logical volume ---
  LV Name                vpool
  VG Name                VG400
  LV UUID                Zl8N7t-SiIF-edLi-COKJ-PrVx-Ma7H-vA1e2U
  LV Write Access        read/write
  LV Creation host, time 101c7, 2021-09-17 16:43:00 -0400
  LV Pool metadata       vpool_tmeta
  LV Pool data           vpool_tdata
  LV Status              available
  # open                 0
  LV Size                100.00 MiB
  Allocated pool data    0.00%
  Allocated metadata     10.84%
  Current LE             25
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     8192
  Block device           253:8
  [root@101c7 ~]$ lvs VG400
  LV     VG    Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  LV400  VG400 owi-aos--- 384.00m                                                    
  VG400m VG400 swi-I-s---  96.00m      LV400  100.00                                 
  vpool  VG400 twi-a-tz-- 100.00m             0.00   10.84  

创建 vthin1 设备,大小定为 1 GB:

[root@101c7 ~]$ lvcreate -V 1G -T /dev/VG400/vpool -n vthin1
  WARNING: Sum of all thin volume sizes (34.00 GiB) exceeds the size of thin pool VG400/vpool and the size of whole volume group (1.37 GiB).
  WARNING: You have not turned on protection against thin pools running out of space.
  WARNING: Set activation/thin_pool_autoextend_threshold below 100 to trigger automatic extension of thin pools before they get full.
  Logical volume "vthin1" created.
[root@101c7 ~]$ lvs VG400
  LV     VG    Attr       LSize   Pool  Origin Data%  Meta%  Move Log Cpy%Sync Convert
  LV400  VG400 owi-aos--- 384.00m                                                     
  VG400m VG400 swi-I-s---  96.00m       LV400  100.00                                 
  vpool  VG400 twi-aotzD- 100.00m              100.00 12.11                           
  vthin1 VG400 Vwi-a-tz--  34.00g vpool        0.29   

格式化成 xfs 文件系统并挂载到 /root/thin1

[root@101c7 ~]$ mkfs.xfs /dev/VG400/vthin1
[root@101c7 ~]$ mount /dev/VG400/vthin1 /root/thin1/
[root@101c7 ~]$ df -hT
/dev/mapper/VG400-LV400  ext3      186M   62M  116M  35% /ext333
/dev/sdd1                xfs       497M   56M  441M  12% /xfs333
/dev/mapper/VG400-vthin1 xfs      1014M   33M  982M   4% /root/thin1
[root@101c7 ~]$ lvs
  LV     VG     Attr       LSize   Pool  Origin Data%  Meta%  Move Log Cpy%Sync Convert
  LV400  VG400  owi-aos--- 384.00m                                                     
  VG400m VG400  swi-I-s---  96.00m       LV400  100.00                                 
  vpool  VG400  twi-aotz-- 100.00m              10.69  10.94                           
  vthin1 VG400  Vwi-aotz--   1.00g vpool        1.04         

使用储存池一定要注意容量问题,否则超容量使用会造成数据损毁,并且没有系统提示。

LVM 快照

LVM 可以使用系统快照(snapshot)功能来备份需要的原始数据。快照区与被快照区为不同 LV 中,但要在同一个 VG 上面。

这里使用 sdc1 作为快照区使用。使用 lvcreate -s 来新建系统快照区 VG400m,并给予一个 PV 占用的 PE 数量 24:

[root@101c7 ~]$ lvcreate -l 24 -s -n VG400m /dev/VG400/LV400 
  Logical volume "VG400m" created.

使用 lvdisplay 查看一下新建的快照区 snap_lv400 信息:

[root@101c7 ~]$ lvdisplay
  --- Logical volume ---
  LV Path                /dev/VG400/VG400m
  LV Name                VG400m
  VG Name                VG400
  LV UUID                cNZB7T-8D2u-IlRt-05sP-e8We-R4ox-WDNqW1
  LV Write Access        read/write
  LV Creation host, time 101c7, 2021-09-13 18:22:45 -0400
  LV snapshot status     active destination for LV400
  LV Status              available
  # open                 0
  LV Size                384.00 MiB
  Current LE             96
  COW-table size         96.00 MiB
  COW-table LE           24
  Allocated to snapshot  0.01%
  Snapshot chunk size    4.00 KiB
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     8192
  Block device           253:5

其中 COW-table size 是快照区的实际容量。可以将快照区挂载后查看内容,取出里面数据。

如果是 xfs 文件系统挂载时得使用 nouuid 参数。

要想建立快照区,必须注意快照区剩余容量要能装得下原始数据,如果快照区容纳不了,快照功能会失效。

也可以将快照挂载后卸载原先 LV,使用快照区作为测试环境在上面测试,测试完毕后直接将快照区删除。

要删除快照,先 umount 再使用 lvremove 命令即可。