新进了几台服务器,然而厂家给安装时忘了跟他们说分区的事了,结果除了 efi 和 swap 分区以外所有空间八百多G都给了根分区。本来是想着只给根 100G 的,其余的给 /data。以前用 GParted 的 liveusb 调整过分区大小,感觉不是很难的事,而且这些服务器的 bmc 还支持远程 iso 镜像,应该更简单才对,但结果却踩了很多坑,折腾了很久才搞定!
一、GParted 不支持缩小 xfs 分区
首先,进入 BMC 控制页面,打开远程控制,html5 模式即可,点击右上角 1 处的浏览文件,选择下载好的镜像文件 gparted-live-1.5.0-6-amd64.iso,然后点击 2 启用镜像,然后在 3 处设置光盘启动,然后重启机器便可进入 gparted live cd 系统。不过注意由于是通过网络传输 iso 镜像文件,所以加载会比较慢。
进入 gparted 以后试着调整 / 分区大小,结果无法调整,原来 gparted 不支持缩小 xfs 分区,其菜单里有文件系统操作支持图表,可以看出 xfs 一行唯一不支持的就是缩小分区!看来之前的想法比较简单了。
二、变通方案
于是只能选择变通的方案,那就是先备份根分区数据,删掉 800多 G 的根分区 /dev/sda3,再重新建一个 100G 的根分区 /dev/sda3 和一个 700 多 G 的 /data 分区 /dev/sda4。
问题是如何备份数据?一开始想用 dd 来着,但后来发现不行,虽然 sda3 中只使用了十几G,但要用 dd 备份则会把空白部分也拷过去,也就是要备份 800 多 G,这显然没有必要!好在可以使用 xfsdump
和 xfsrestore
备份和恢复 xfs 分区。注意这两个命令使用时必须把分区挂载上才行。用法如下:
# 备份时先挂载 xfs 分区,比如到 /mnt/tmp,然后再用 xfsdump 备份到文件 bak.xfs
mount /dev/sda3 /mnt/tmp
xfsdump -f /path/to/bak.xfs /mnt/tmp
# 等恢复分区内容时,也要先挂载,然后用 xfsrestart 从之前备份的文件恢复
mount /dev/sda3 /mnt/tmp # 注意恢复时 sda3 里不能有数据,要么删除要么格式化
xfsrestore -f /path/to/bak.xfs /mnt/tmp
对于十几 G 大小的分区,备份和恢复都是比较快的,三五分钟即可搞定。
然而这里仍有一个问题有待解决,就是在 gparted live cd 系统下,备份的数据放在哪里?我最初的想法是在 svr 上开启 nfs 服务共享一个目录给 gparted 系统,然而 gparted 系统里没有 mount.nfs。但我发现有 mount.cifs,于是尝试在 svr 上开启 smb 服务,结果在 gparted 系统上死活挂载不上,不知道是什么原因!最后想到试试 sshfs,然而 gparted 上也没有该命令。我尝试把 ubuntu 22.04 上的 sshfs 可执行文件直接拷到 gparted 上,结果能用,太好了!
其实在这之前还有一个网络问题,那就是怎么把数据从 svr 上拷到 gparted 系统上。首先,gparted 系统默认是没有启动网络的,不过好在桌面上有网络配置图标,点一下就可以启用网卡,然后 fconfig eth0 172.100.x.x netmask 255.255.0.0
设置一下 IP 后网络就通了。但怎么传文件又是问题了。本来想用 scp,结果 gparted 上没有开 ssh 服务,虽然我尝试开启后却依然无法从 svr 连上;反过来 svr 禁用了密码登录,密钥也没法传过去。最后无奈打开了 svr 的 vsftpd 服务,好在 gparted 上有 ftp 程序,使用自己的账号密码登录 svr 上的 ftp,这样就可以传数据了,其实需要 ftp 传的数据一是 ssh 密钥,二是 sshfs 程序。有了密钥就可以从 gparted 上登录 svr,并通过 sshfs 挂载 svr 上的目录,之后的数据便可通过该挂载的目录进行交互。
三、无法启动
比如把我主目录下的 axx 目录共享,挂载到 tmp 目录,可使用 sshfs svr:axx tmp
命令。然后按上面的想法先用 xfsdump -f tmp/bak.xfs tt/
(已把 /dev/sda3 挂载到 tt 上)把根分区备份,然后删掉该分区,新建两个分区,格式化成 xfs 文件系统,然后再次挂载 sda3 到 tt 上并用 'xfsrestore -f tmp/bak.xfs tt/' 恢复数据。为了避免启动时找不到正确的系统盘,应该将新的 sda3 分区的 UUID 设成原来的值。所以在删除原来分区之前应该先用 blkid
命令或 ls -l /dev/disk/by-uuid
来查看并记录下 sda3 的 UUID。设置 xfs UUID 的命令为
xfs_admin -U xxxx-xxx-...-xxxxx /dev/sda3
注意除了 /etc/fstab 里要用到 uuid, grub.cfg (/boot/efi/EFI/centos/grub.cfg)里也有多处指定了 uuid。如果不改回原来的 uuid,那么就得修改这两个文件的 uuid 为 sda3 的当前 uuid 值,否则系统无法启动。按说做了这些之后应该就可以了,谁知道重启系统后发现根本无法进入系统!在 grub 中选中启动条目后会提示找不到分区 xxxx-...-xxxx(即 sda3 的 uuid)。通过看设置,grub 里写的是 (hd1,gpt3) 分区,然而实际有的却是 (hd0,gpt3) 分区;心想改成 hd0 后应该可以了吧,谁知还是不行,这回却提示 “unknown filesystem”。 grub 下执行 ls (hd0,gpt3)
也是说文件系统不识别,找不到文件。难道是 xfsrestore 恢复数据时出了问题?重进 gparted 系统后发现数据可以读取啊,一切看似正常!后来又发现一个奇怪的事,那就是如果在 gparted 的 grub 界面下是能识别 (hd0,gpt3) 下的文件的,但是到了 centos7 的 grub 界面下则不识别了!这说明数据应该没问题,可能是版本的原因造成的!
四、用 centos 上的 mkfs.xfs 程序格式化解决问题
后来发现果然是 mkfs.xfs 的版本问题。 gparted 上带的 mkfs.xfs 是 6.4.0 版本,而 centos 7.9 上带的却是 4.5.0 版本!如果用 gparted 格式化 xfs,用 gparted 自己的 grub 识别是没问题的,因为都是较新的版本;但是较老的 centos 7 系统上的 grub 则无法识别!为了让 centos7 上的 grub 能识别,只好用 centos7 上的 mkfs.xfs 对 /dev/sda3 进行格式化。好在直接把 centos7 上的 mkfs.xfs 直接拷到 gparted 上就能用。所以,最终解决方案是这样的:
- 先用 xfsdump 备份 /dev/sda3 上的数据
- gparted 上删除 /dev/sda3 分区
- gparted 上新建一个 100G 的分区 (sda3),文件系统选默认的 ext4 即可,不要用自带的 xfs
- gparted 上再把剩余空间建一个分区(sda4),然后执行所有操作
- 使用 centos7 上拷过来的 mkfs.xfs 对 sda3 和 sda4 重新格式化,如
./mkfs.xfs -f /dev/sda3
- 使用 xfs_admin 恢复原来 sda3 的 uuid
- 使用 xfsrestore 恢复数据到新的 sda3 分区
然后重启系统,虽然 grub 中看到的依然只是 (hd0,gpt3) 分区而 grub.cfg 文件中写的却是 hd1,gpt3 但系统依然成功启动了,所以之前无法启动的根本原因在于 xfs 文件系统的版本问题而不是 hd0 或 hd1 的问题!
注:除了第一个节点我是用 gparted 上带的 xfsdump 和 xfsrestore 操作外,其他节点我都是在节点工作时使用 centos7 系统的 xfsdump 执行的备份 xfsdump -f node_xx_bak.xfs /
(多节点同时进行备份比较快) 然后用 gparted 离得 xfsresture 进行恢复。开哈还怀疑无法启动的问题是因为使用了不同版本的 xfsdump/xfsrestore 组合造成的,但后来证实并非如此。