dd if=/dev/sdb of=bckup.img
但如果磁盘容量为32GB,仅使用了4GB,则32GB的镜像文件就是浪费空间和时间。是否有任何方法或工具可以创建仅包含有效数据的映像文件?
解决这个问题的一个非常好而简单的方法是通过gzip进行管道传输,类似于以下内容:
# dd if=/dev/sdb | gzip > backup.img.gz
这样,您的图像将被压缩,可能未使用的空间将被挤压至几乎为零。
您可以使用此方法来恢复此类图像:
# cat backup.img.gz | gunzip | dd of=/dev/sdb
需要注意的一点是,如果你最近删除了很多文件,图像大小可能仍然很大(删除文件并不一定会将基础扇区置零)。您可以通过创建并立即删除包含零的大文件来擦除空闲空间:
# cd /media/flashdrive
# dd if=/dev/zero of=bigfile bs=1M # let it run and quit by disk full error
# rm bigfile
最好的做法是:
复制所有分区中的文件,并保留元数据
mkdir -p myimage/partition1
mkdir myimage/partition2
sudo cp -rf --preserve=all /media/mount_point_partition1/* myimage/partition1/
sudo cp -rf --preserve=all /media/mount_point_partition2/* myimage/partition2/
提取MBR
sudo dd if=/dev/sdX of=myimage/mbr.img bs=446 count=1
用相应的设备替换 /dev/sdX
。
使用 gparted
将目标磁盘分区,分区大小应大于复制的数据,并且应具有相同的格式和相同的标志。Google如何分区硬盘。
挂载刚刚格式化和分区的磁盘。在大多数计算机上,只需要连接磁盘即可在 /media
文件夹中找到挂载的分区。
使用以下命令将之前复制的数据复制到目标分区
sudo cp -rf --preserve=all myimage/partition1/* /media/mount_point_partition1/
sudo cp -rf --preserve=all myimage/partition2/* /media/mount_point_partition2/
将MBR复制回来
sudo dd if=myimage/mbr.img of=/dev/sdX bs=446 count=1
现在,享受您的新磁盘吧!
cp
命令中的-r
或-R
之一:它们是相同的开关。 - JealieMBR
时,你可能指的是 Bootloader
,它的大小为446个字节 - 这是你正在提取的数量。实际上,MBR
的大小是512个字节。 - Ryan Amaraldd
的bs和count参数,你可以限制图像的大小,如答案1665017中的步骤2所示。df
中得到一个好的想法。df -H --total /
将 /
替换为与磁盘分区相关的挂载点列表,用空格分隔。
更准确的方法可能是使用 fdisk
或您喜欢的分区编辑器,并使用计算器进行操作。
$ fdisk -l /dev/mmcblk0
Disk /dev/mmcblk0: 7.4 GiB, 7948206080 bytes, 15523840 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
Disklabel type: dos
Disk identifier: 0x00057540
Device Boot Start End Sectors Size Id Type
/dev/mmcblk0p1 2048 186367 184320 90M c W95 FAT32 (LBA)
/dev/mmcblk0p2 186368 3667967 3481600 1.7G 5 Extended
/dev/mmcblk0p5 188416 3667967 3479552 1.7G 83 Linux
总使用空间(以字节为单位)=最后一个分区的结束扇区 X 扇区大小(这里是 3667967 x 512)。
总使用空间(以GB为单位)= 总使用空间(以字节为单位)/ 10243 (这里是1.749023 GB)。
如果您决定,例如,您的图像应该正好是2 GB,则以下命令将执行此操作:
dd if=/dev/mmcblk0 of=/path/to/pi_updated.img bs=1M count=2048
sudo
上述命令。dd
,我遵循了这个建议,因为它似乎是直觉上正确的;这确实有点像试图在镜子里画自己正在画的素描,并且你正在制作的素描也在素描中可见。这有点靠不住。在尝试多种不同的方法后,我找到了以下文章:
https://medium.com/platformer-blog/creating-a-custom-raspbian-os-image-for-production-3fcb43ff3630
它被创建用于缩小和调整大小(在第一次启动时)树莓派镜像,但可以轻松调整为任何其他Linux发行版。我成功地在基于自定义ARM芯片的Debian 9上使其工作。由pishrink脚本创建的rc.local
首先使用raspi-config
调整根文件系统大小,然后退回到使用parted
的方法(我不得不提前在我的机器上安装)。我注释掉了代码部分,其中使用了raspi-config
。我的SD卡映像从15 GB缩小到了1.1 GB。我使用etcher刷写了缩小后的SD卡映像。只需要不到5分钟,而完整的15 GB映像需要半个多小时。将带有映像文件的可引导Ubuntu持久化Live USB插入单板电脑(例如UP² Board)。启动到USB(默认持久化Live选项)。 启动终端并输入以下命令(一行):
sudo dd if=/media/ubuntu/usbdata/ubuntu.img of=/dev/mmcblk0 bs=1M status=progress
等待15-20分钟。完成后,关闭并断开USB。启动内部eMMC驱动器。
从内部eMMC创建未压缩的稀疏映像文件,并保存到闪存驱动器中。
sudo dd if=/dev/mmcblk0 bs=1M status=progress | cp --sparse=always /dev/stdin /media/ubuntu/usbdata/ubuntu.img
sudo dd if=/media/ubuntu/usbdata/ubuntu.img of=/dev/mmcblk0 bs=1M status=progress
sudo dd if=/dev/mmcblk0 bs=1M status=progress | gzip > /home/user/Desktop/ubuntu.img.gz
将压缩的镜像文件提取到内部 eMMC 中
sudo gzip -cd /home/user/Desktop/ubuntu.img.gz | dd of=/dev/mmcblk0 bs=1M status=progress
sudo mkdir /media/root
sudo mount -t ext4 -o loop,offset=537919488 /media/user/usbdata/ubuntu.img /media/root
要确定您的图像或驱动器的偏移量,请运行:
fdisk -l /media/user/usbdata/ubuntu.img
然后,将512字节的块大小乘以Linux分区的起始块1050624。512*1050624 = 537,919,488。
同时挂载其他系统文件夹:
for i in /dev /dev/pts /proc /sys /run; do sudo mount -B $i /media/root$i; done
然后进入img的根目录并使用chroot命令:
cd /media/root
sudo chroot .
然后您可以更新文件、密码等。要卸载,请运行:
for i in /dev /dev/pts /proc /sys /run; do sudo umount /media/root$i; done
sudo umount /media/root
如果您有一张大的SD卡,比如16GB、32GB等,但想要通过备份节省空间,您可以使用:
sudo apt-get install gnome-disk-utility
打开磁盘工具检查你的USB驱动器实际上是哪个字母:
gnome-disks
在我的情况下,一张带有Raspbian镜像的32GB SD卡被识别为:/dev/sde
因此我使用 /dev/sde
运行:
sudo dd bs=4M status=progress if=/dev/sde | gzip > \
/you-selected-full-path-here/raspberry-images/`date +%Y%m%d`_rpi_image_backup.gz
status=progress gives you progress bar indication
| gzip > compresses the 32 GB total size and not writing the empty space from the 32 GB
`date +%Y%m%d` writes today date in the filename
输出文件名: 20190529_rpi_image_backup.gz
而且大小只有3.5GB。 如果你想将这个映像写入新的SD卡,请使用:
此外,你可以将这个32 GB的映像写入16 GB或8 GB的磁盘中,不再提示映像太大的错误。
我的解决方案是制作一个定制化的Raspios镜像:
DIR="./img"
DEVICE=/dev/sdb
# declare custom copy functions
copy() {
echo "[$1] copy $2 to $3..."
if [ "$1" == 'ext' ]; then
sudo rsync -aHAXX \
--no-inc-recursive \
--numeric-ids \
--filter='-x security.selinux' \
--delete \
--exclude={"/lost+found"} \
--info=progress2 \
$2 \
$3
else
sudo rsync -rtD \
--modify-window=1 \
--no-inc-recursive \
--delete \
--exclude={"/lost+found"} \
--info=progress2 \
$2 \
$3
fi
}
# create working directories
mkdir -p $DIR/{mount,image}/{boot,rootfs}
# mount initial device partitions
sudo mount ${DEVICE}1 $DIR/mount/boot
sudo mount ${DEVICE}2 $DIR/mount/rootfs
# preserve partitions UUIDs
PTUUID=0x`sudo blkid -p $DEVICE | sed -e 's/.*PTUUID="\([0-9a-f]*\)".*/\1/'`
BOOTUUID=`sudo blkid -p ${DEVICE}1 | sed -e 's/.* UUID="\([0-9a-zA-Z\-]*\)".*/\1/' | tr -d '-'`
ROOTUUID=`sudo blkid -p ${DEVICE}2 | sed -e 's/.* UUID="\([0-9a-zA-Z\-]*\)".*/\1/'`
# copy contents from physical device to local folder
copy fat $DIR/mount/boot/ $DIR/image/boot/
copy ext $DIR/mount/rootfs/ $DIR/image/rootfs/
umount ${DEVICE}1
umount ${DEVICE}2
# show contents size
BOOTSIZE=`sudo du -hs $DIR/image/boot`
ROOTSIZE=`sudo du -hs $DIR/image/rootfs`
echo "boot is $BOOTSIZE"
echo "root is $ROOTSIZE"
# allocate the final .img file
# change size as needed
SIZE="5"
echo "allocating ${SIZE}G image..."
rm $DIR/$IMAGE
fallocate -l ${SIZE}G $DIR/$IMAGE
# create partitions
echo "formatting image..."
sed -e 's/\s*\([\+0-9a-zA-Z]*\).*/\1/' << EOF | fdisk $DIR/$IMAGE > /dev/null
o # create MBR partition scheme
n # new partition
p # primary
1 # partition #1
8192 # start block
532479 # end block
t # define type
0c # W95 FAT32 (LBA)
n # new partition
p # primary
2 # partition #2
532480 # start block
# last end block
t # define type
2 # for partition #2
83 # linux
x # advanced menu
i # change disk identifier
$PTUUID # identifier from original fstab
r # return to normal menu
w # write changes
EOF
# locally mount the .img
echo "mounting image..."
LOOP=`sudo losetup -fP --show $DIR/$IMAGE`
echo "mounted image under $LOOP"
ls -la $LOOP*
echo "creating partition boot with FAT32"
sudo mkfs.fat \
-F 32 \
-S 512 \
-i $BOOTUUID \
-n boot \
${LOOP}p1
echo "creating partition rootfs with ext4"
sudo mkfs.ext4 \
-b 4096 \
-U $ROOTUUID \
-L rootfs \
${LOOP}p2
echo "mounting image loops"
sudo mount ${LOOP}p1 $DIR/mount/boot
sudo mount ${LOOP}p2 $DIR/mount/rootfs
echo "copying contents to image"
copy fat $DIR/image/boot/ $DIR/mount/boot/
copy ext $DIR/image/rootfs/ $DIR/mount/rootfs/
echo "unmounting image"
unmount "$LOOP+" > /dev/null
echo "removing loop"
sudo losetup -d ${LOOP}
tar cvfz mybackup.tar.gz /media/flashdrive
进行备份。它会捕获除可启动的USB驱动器之外的所有内容,它们将失去可启动状态。 - mvptar
会丢失 MBR,您需要使用boot-repair
来使驱动器再次可引导。但是,除此之外,tar 应该会保留一切并且操作系统应该是完全可用的(但请确保以 root 用户身份运行 tar!)。 - mvp