作为一个换源博主,我竟然鬼使神差地给我的Ubuntu 20.04服务器换上了22.04的源。在更新了900多个包并且重启后才发现服务器已经无法通过SSH连接。在尝试各种连接方法和求助淘宝无果后,我开始了自己抢救数据的历程。

导出镜像

服务器连SSH都无法进入了,那么还能指望什么来恢复数据呢?我在腾讯云控制台的云服务器页面翻找,希望能找到下载数据的地方。最后发现云硬盘和快照板块也许可以下载。于是在云硬盘板块中点击了创建快照,一段时间后快照创建完成了。但是在云硬盘和快照的板块并没有找到下载入口。

但是在快照的下拉菜单中,我看到了“创建自定义镜像功能”,在使用快照创建镜像之后,可以在云服务器的“镜像”板块中找到。镜像提供了导出选项,可以进行导出操作。

导出镜像仅能导出至腾讯云的对象存储服务。由于之前利用COS进行过离线下载,我已经有了一个专门用来存放文件的存储桶。

导出到存储桶后即可利用COS浏览器进行下载,由于镜像固定与云硬盘容量同样大小,所以购买一个资源包很有必要。50G的公网下行流量资源包17.5元,这是本次抢救的金钱成本。在下载完成后建议删除镜像,因为在COS中存储也需要成本。

转换镜像

下载的镜像是raw格式,我们需要一个能够读取其中文件的办法。腾讯云的文档为我们提供了一个转换镜像的软件:QEMU。但文档中只提到了Windows和Linux,没有Mac OS的安装方法。经过查阅QEMU官网后发现Mac OS需要使用Homebrew或者编译安装。由于本人最近新购入一台M2芯片的Mac mini,所以尝试使用Homebrew安装QEMU来进行镜像格式转换。终端输入以下命令来安装QEMU

brew install qemu

输入qemu的命令来确定是否成功安装:

qemu-img --version

cd至镜像下载文件夹,输入以下命令转换至vmdk格式,其中raw是源文件格式,vmdk是要转换到的文件格式,EM_img-3dojjvpf_system_snap-6yrgd9q4.raw是源镜像文件名,EM.vmdk是目标镜像文件名:

qemu-img convert -f raw -O vmdk EM_img-3dojjvpf_system_snap-6yrgd9q4.raw EM.vmdk

运行后即可在文件夹内找到EM.vmdk,我们要将这个虚拟硬盘文件以某种形式挂载,最终访问其中的文件。

挂载镜像

vmdk是虚拟机的虚拟硬盘文件,本人寻找多种方法想要直接读取其中的文件未果,只能加载到虚拟机中进行读取。由于虚拟硬盘内的文件系统也是Ubuntu的ext文件系统,最初,本人想利用Ubuntu桌面版将硬盘内文件复制进exFAT格式的U盘,但是VM Fusion虚拟机在加载ARM64每夜构建Ubuntu镜像后无法正常显示画面,只能使用官方的服务器镜像在终端操作进行挂载。

使用VM Fusion安装完Ubuntu后,打开虚拟机设置,使用vmdk文件添加硬盘。

插入U盘,将U盘连接到虚拟机。

使用以下命令,将所有磁盘设备的详细信息列出:

fdisk -l

以本人为例,得到以下输出:

Disk /dev/loop0: 43.19 MiB, 45289472 bytes, 88456 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/loop1: 109.61 MiB, 114929664 bytes, 224472 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/loop2: 59.09 MiB, 61956096 bytes, 121008 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/nvme0n1: 40 GiB, 42949672960 bytes, 83886080 sectors
Disk model: VMware Virtual NVMe Disk
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 9D140CA1-FBC3-4646-9F48-07702B7F7051

Device           Start      End  Sectors  Size Type
/dev/nvme0n1p1    2048  2203647  2201600    1G EFI System
/dev/nvme0n1p2 2203648  6397951  4194304    2G Linux filesystem
/dev/nvme0n1p3 6397952 83884031 77486080 36.9G Linux filesystem


Disk /dev/nvme0n2: 50 GiB, 53687091200 bytes, 104857600 sectors
Disk model: VMware Virtual NVMe Disk
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 884D39AE-2030-4231-B486-520515A9ADD7

Device         Start       End   Sectors Size Type
/dev/nvme0n2p1  2048      4095      2048   1M BIOS boot
/dev/nvme0n2p2  4096 104857566 104853471  50G Linux filesystem


Disk /dev/mapper/ubuntu--vg-ubuntu--lv: 18.47 GiB, 19834863616 bytes, 38739968 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

请注意,本人在AMD64ARM64平台都尝试过,该命令的表现略有不同,AMD64平台将虚拟硬盘识别为/dev/sdbARM64平台如上所示,识别为/dev/nvme0n2。根据容量推断,我们的虚拟硬盘应该就是50G的/dev/nvme0n2,这个硬盘下有两个分区,我们应当挂载/dev/nvme0n2p2分区,在root用户中使用以下命令:

mkdir /mnt/nvme0n2p2
mount /dev/nvme0n2p2 /mnt/nvme0n2p2

这样,/mnt/nvme0n2p2目录中就是虚拟硬盘中的文件。同样地,我们挂载U盘,然后利用cp命令将虚拟硬盘中的所有文件拷贝到U盘,请注意根据自己fdisk命令输出的情况调整指令:

mkdir /mnt/sda1
mount /dev/sda1 /mnt/sda1
cd /mnt/sda1
mkdir EM
cp -r /mnt/nvme0n2p2/* EM/

之后,我们便可以从U盘中恢复数据了。所幸本人设置了宝塔备份,网站、数据库等数据均能在备份文件中找到,成功地恢复了主站。

这个故事告诉我们:一定要开启网站和数据库备份,这样无论如何,总能找回一些数据。有条件的可以使用云服务器的镜像功能,一定程度上也可以帮助应对这样的灾难。