u盘安装linux 提示no such device_树莓派学习笔记2-U盘挂载和系统备份

b61e1743bb59ca6c86d558dbc818db3e.png

上一次我们说到系统配置的一些工作,在那些工作完成之后我突然想到之前从来没有做过的一个工作:系统备份。这一次我们就研究一下系统备份是怎么做的。

系统备份其实很简单,你总是可以把树莓派上的SD卡拔下来,在电脑上用Win32DiskImager来备份,但是这样备份出来的文件会和SD卡容量一样大,这种备份方法不可持续。那么参考网上的使用linux下的dd指令来完成这个工作。

我看了一下,在使用linux电脑备份的时候是把树莓派的卡插到电脑上,然后用dd把SD卡内容拷贝到本地。我手上只有树莓派作为linux电脑,那就先用我的4B测试一下,看看效果。

875c84c3f54feab4bcaf1287ae38a08c.png
树莓派4B

害怕树莓派上空间不够,先挂个U盘备份到U盘里试试。一只没弄明白U盘是怎么挂载的,借此机会研究一下。

挂载U盘

U盘直接插上是读不了内容的,所以必须要使用mount指令进行挂载。虽然mount天然支持FAT文件系统,然而FAT有个文件尺寸上限,不是很好。因此考虑使用exFAT文件系统。安装新的工具包来使mount支持exFAT。

sudo apt install exfat-fuse

好下一步将我的U盘格式化为exFAT格式,在里面放一个文件以备后续测试。

76f870675f5de8c6f893b028576a4f2e.png

把U盘插到树莓派上。

171832c1f09c5f86dd576fdb46361db0.png
忘了U盘是不是支持USB3.0

使用上一次学的指令查看USB设备。

c5d6682361fe2fa527d1851e2f8a3915.png

奇怪,U盘是16GB的,为什么这里显示是64GB?问题不大,下一步查看一下/dev下的设备。这里目录下的sd表示存储设备,sda表示第一个存储设备,sdb表示第二个,以此类推。sda1就表示这个设备的第一个分区,sda2表示第二个分区,以此类推。

b0f40d1fdc799e06b52ac4b0e0485794.png

可以看到已经连接上了,我的U盘没有分区所以只有一个sda1。

下面创建挂载点,一般在/mnt或者/media目录下创建挂载点。 我现在没有挂载东西所以这俩目录底下都是空的。这里我就在mnt下挂载了。注意指令里面的uid和gid是权限设置,后面是你的用户名。

sudo mkdir /mnt/backup_flash
sudo mount -o uid=pi,gid=pi /dev/sda1 /mnt/backup_flash

67eea824e5d7f05b03fc814f7dfcf75c.png

挂载成功了,下面看一下我放在U盘里的文件都有啥。

054a1ddece26943dd765ec8a4aa85eb5.png

我在电脑上整文件的时候没有搞换行,导致这么一个效果,整体来看没啥问题。

尝试修改这个文件,然后取消挂载,再到电脑上看看。

e1a2a491ac7221df1e21a39b89d470d5.png

09a75de1c2f80a426fd271dda865af60.png

成功。


习得新指令:mountumount

功能:挂载和卸载移动存储设备


系统备份1

我现在想备份的系统正在树莓派上跑着,没法搞,现在先用另一个有系统的sd卡测试一下备份功能。

e84f7a301fe234631bf360491ad5db37.png
闪迪打钱(雾)

97cd70f4e110c01d513b4be6041b13cf.png

还是查看一下设备

27c367c1c9d4b9d3c1d34ce9595e31b3.png

注意到Device 006和/dev下的sdb系列。在烧录系统得时候sd卡被分成了两个分区,所以这里有sdb1和sdb2。

可以使用df -h指令来查看挂载情况。

05b798ecfc9df3312b71ff84f6cf6f4e.png

这里由于sdb没有挂载,所以这里没有显示。使用上面的指令进行挂载。

84a174c1cd88609178c75d374c0ea23c.png

注意这里的区别。烧录到sd卡后较大的分区是ext4文件系统,挂载的时候要强调这个。另外由于系统烧录后所属权限是root,所以这里的uid和gid设置要去掉,否则挂载会不成功。

挂载成功,下一步进行备份测试。

sudo dd if=/dev/sdb of=/mnt/backup_flash/RPi_backup_64GB_test.img bs=4M

使用dd指令进行拷贝,拷贝到U盘下的RPi_backup_64GB_test.img下。注意:这里的if表示输入文件(input file),of表示输出文件(output file),bs表示分包大小(bag size?)。如果想查看进度可以新建一个终端并输入如下执行查看进度。

sudo pkill -USR1 -n -x dd

6a0524e912b9f67cb0b5869927b6930d.png

到这一步可能按道理就应该完成了,但实际上并不是这样。经过漫长的等待(半个小时),终于拷贝完成的时候,系统提示空间不足,备份失败。

3d72e0e60ce2ff6fb236757767b9c97b.png

这和我想象的不太一样啊,又查阅了更多的资料后发现直接对SD卡使用dd指令的结果和在windows上用Win32DiskImager的结果是一样的:镜像文件和SD卡一样大。

此路不通,换道。


习得新指令:dd

功能:文件拷贝和创建


系统备份2

试错之后发现了新的方法,这个方法需要更多的工具,也更复杂,但网上有人写好了脚本我可以直接使用。与直接使用dd拷贝SD卡不同,这里我们要先使用dd创建一个合适尺寸的镜像文件,然后将这个镜像文件划分为两个分区, root区为FAT32文件系统,Linux区为ext4文件系统。分区完成后需要把这个镜像文件作为虚拟磁盘挂载,挂载完成以后就可以进行格式化。此后就可以进行备份了。

工具准备

这个方法里面需要三个工具:

  • dosfstools:fat32分区格式化工具
  • dump:dump& restore 备份工具
  • parted & kpartx:虚拟磁盘工具

使用如下指令安装。

sudo apt install dosfstools dump parted kpartx

创建镜像

根据系统尺寸决定使用的空间大小。

96751e2fa3ae58cd80f8f1f388520f83.png

使用指令df -P的时候,显示的数据是以1K(1024字节)为单位,注意到sdb1和sdb2分别使用的空间,下面要进行img空间分配。

应该注意到,boot分区其实是很小的,不过几十兆,分配的时候不应该用boot分区已经使用的空间,而是boot分区整个的大小,也就是表中第二列。root分区就不一样了,里面存放的是系统各项文件,这个分区在空间划分的时候应该照顾已经使用的空间,所以要注意的是表中第三列

使用下列指令获取上面的参数。

bootsz=`df -P | grep /dev/sdb1 | awk '{print $2}'`# 注意到最后的那个$2
rootsz=`df -P | grep /dev/sdb2 | awk '{print $3}'`# 注意到最后的那个$3

然后利用下面指令计算镜像文件尺寸。

totalsz=`echo $rootsz $bootsz | awk '{print int(($1+$2)*1.3)}'`

注意到上面的参数1.3,这个参数是网上一个同学经过测试测出来的。使用原始大小的1.3倍是极好的,兼顾尺寸和完备程度。

利用下面的指令申请镜像空间。

img=/mnt/backup_flash/PRi_64GB_test.img
sudo dd if=/dev/zero of=$img bs=1k count=$totalsz

申请空间这一步会花不少时间,像我这个9GB多大概一小时吧。

ea42040cdf9a497d455245d215232dd1.png

至此,空间分配完成,下面开始分区。

空间分区

使用fdisk指令查看分区情况。

sudo fdisk -l /dev/sdb

6526cb1c185ddc2fc05cf5d170f301d4.png

在镜像文件分区的时候是根据扇区编号来确定的。和分配空间类似,sdb1分区应该完整划分,剩下的都是sdb2分区。

使用以下指令获得分区始末位置。

bootstart=`sudo fdisk -l /dev/sdb | grep sdb1 | awk '{print $2}'`
bootend=`sudo fdisk -l /dev/sdb | grep sdb1 | awk '{print $3}'`
rootstart=`sudo fdisk -l /dev/sdb | grep sdb2 | awk '{print $2}'`

bafc5f7d3cf5ba7283783e093ac071ee.png

奇怪,为什么分区始末是不连续的?暂时不管,使用下面的指令查看数据。

echo "boot: $bootstart -> $bootend, root: $rootstart -> end"

d6d0545ef59c7718ac477fd8fa3606e4.png

使用下面的指令进行分区。

sudo parted $img --script -- mklabel msdos
sudo parted $img --script -- mkpart primary fat32 ${bootstart}s ${bootend}s
sudo parted $img --script -- mkpart primary ext4 ${rootstart}s -1

注意,这里第三个指令最后一个参数是负一,不是英文字母l,表示的含义是到最后一个,千万不要搞错了。

分区完毕之后进行格式化操作。

loopdevice=`sudo losetup -f --show $img`
device=`sudo kpartx -va $loopdevice | sed -E 's/.*(loop[0-9])p.*/1/g' | head -1`
device="/dev/mapper/${device}"
sudo mkfs.vfat ${device}p1 -n boot
sudo mkfs.ext4 ${device}p2

挂载并备份

使用下面的指令挂载虚拟磁盘的boot分区。

sudo mkdir -p /mnt/vir_img/boot
sudo mount -t vfat ${device}p1 /mnt/vir_img/boot

注意,boot区是FAT32格式,可以直接用cp指令进行拷贝。使用下面指令即可。

sudo cp -rfp /mnt/rpi_sd/boot/* /mnt/vir_img/boot/

从要备份的SD卡,拷贝到目标文件挂载的目录。

然后挂载root分区。

sudo mkdir -p /mnt/vir_img/root
sudo mount -t ext4 ${device}p2 /mnt/vir_img/root

注意,root分区是exf4格式,需要使用dump & restore进行备份。

cd /mnt/vir_img/root
sudo chattr +d $img
sudo dump -0uaf - /mnt/rpi_sd/root/ | sudo restore -rf - 
cd
sudo sync

经过漫长的拷贝过程,完成之后就可以卸载虚拟磁盘了。

sudo umount /mnt/vir_img/*
sudo kpartx -d $loopdevice
sudo losetup -d $loopdevice
sudo umount /mnt/backup_flash

好的,现在把得到的镜像拷贝到电脑上,烧到一个新的SD卡里用旧的树莓派测试一下。

5ff831afc217b1dda655a62f6bcac5f3.png

emmmmm卡住不动了,备份失败

把上面的参数1.3改一下,改成1.5,新写一个自动化脚本测试一下。

#!/bin/bash

# 时间
now=`date +%Y-%m-%d-%H%M%S`
exho "time:%t $now"

# 备份文件写入位置
target_file_dir=/home/pi/Documents/backup_test
sudo mkdir -p $target_file_dir
img=${target_file_dir}/backup-${now}.img
echo "target file" $img

# 虚拟磁盘挂载位置
vir_dir=/mnt/vir_img

# 目标文件文件系统和目录
bootfs=/dev/sdb1
rootfs=/dev/sdb2
bootdir=`df -P | grep ${bootfs} | awk '{print $6}'`
rootdir=`df -P | grep ${rootfs} | awk '{print $6}'`
echo $bootfs "mounted on" $bootdir
echo $rootfs "mounted on" $rootdir

# 计算目标空间尺寸
bootsz=`df -P | grep $bootfs | awk '{print $2}'`
rootsz=`df -P | grep $rootfs | awk '{print $3}'`
totalsz=`echo $rootsz $bootsz | awk '{print int(($1+$2)*1.5)}'`
echo "total size" ${totalsz}KB

# 获取分区始末位置
bootstart=`sudo fdisk -l | grep $bootfs | awk '{print $2}'`
bootend=`sudo fdisk -l | grep $bootfs | awk '{print $3}'`
rootstart=`sudo fdisk -l | grep $rootfs | awk '{print $2}'`
echo "boot: $bootstart -> $bootend, root: $rootstart -> end"

# 申请镜像空间
sudo dd if=/dev/zero of=$img bs=1k count=$totalsz

# 目标镜像分区
sudo parted $img --script -- mklabel msdos
sudo parted $img --script -- mkpart primary fat32 ${bootstart}s ${bootend}s
sudo parted $img --script -- mkpart primary ext4 ${rootstart}s -1

# 创建虚拟磁盘
loopdevice=`sudo losetup -f --show $img`
device=`sudo kpartx -va $loopdevice | sed -E 's/.*(loop[0-9])p.*/1/g' | head -1`
sleep 5     # 暂停来避开bug
device="/dev/mapper/${device}"

# 格式化
sudo mkfs.vfat ${device}p1 -n BOOT
sudo mkfs.ext4 ${device}p2

# 挂载虚拟磁盘
vir_boot=${vir_dir}/boot
vir_root=${vir_dir}/root
sudo mkdir -p $vir_boot $vir_root
sudo mount -t vfat ${device}p1 $vir_boot
sudo mount -t ext4 ${device}p2 $vir_root

# 备份boot分区
sudo cp -rfp ${bootdir}/* ${vir_boot}/

# 备份root分区
cd $vir_root
sudo chattr +d $img
sudo dump -0uaf - $rootdir | sudo restore -rf - 
cd
sudo sync

# 卸载虚拟磁盘
sudo umount ${vir_dir}/*
sudo kpartx -d $loopdevice
sudo losetup -d $loopdevice

保存,执行,还是不行。

咋回事呢?我一步步按照教程来的啊,怎么就不好使呢?

莫非是备份目标的问题?教程里是把正在运行的树莓派固件备份,我这里是把一个挂载的卡备份,会不会不一样呢?会不会是刚才不连续的问题造成的呢?

修改脚本,重新测试,依旧失败,出现了教程里面一个broken pipe的问题。

0d7f33fc3630d0d2bf1f424ff2e70b97.png

时间有点晚了,暂时到这里,系统备份失败,下次再继续研究。

总结

虽然系统备份是失败的,但是我挂载U盘的指令由于反复使用已经烂熟于心,另外dffdisk指令也是经常使用,也熟练了不少。

参考文献

树莓派挂载U盘或移动硬盘:http://shumeipai.nxez.com/2013/09/08/raspberry-pi-to-mount-the-removable-hard-disk.html

linux下mount指令详解:https://blog.csdn.net/daydayup654/article/details/78788310

linux下uid和gid详解:https://blog.csdn.net/36/article/details/86573899

dd指令系统备份:https://blog.csdn.net/just_s0so/article/details/88825716

系统备份:https://www.cnblogs.com/javazhu/articles/9234097.html

系统备份(蜜汁1.3):http://www.360doc.com/content/17/0805/03/40492717_676751545.shtml

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值