#1 楼
在这个答案中,我演示了逐步执行的操作,以便人们理解解决方案背后的逻辑,并能够针对其他问题应用步骤。但首先,应说明将文件系统从SD卡迁移到较小(但足以容纳数据)的SD卡是一个普遍的问题(不是raspi特有的问题)。带有微型SD卡读卡器和运行Linux(我更喜欢Ubuntu)的Linux。
当PIBOX正在运行时,我们列出了分区(此处未显示不必要的系统分区)。
/
。甚至连2GB的存储空间都没有用。 。SD_CARD_A的分区会自动安装为
/boot
和/dev/sdc1
。它们成功。PIBOX : Raspberry Pi which is used
SD_CARD_A : 8GB micro SD card which is used on PIBOX and on which Raspbian-lite (the OS) is installed
SD_CARD_B : 2GB micro SD card which will be used on PIBOX and on which Raspbian-lite (the OS) will be installed
我们详细显示SD_CARD_A的设备信息,以供下一步确认。 />上面您可以看到SD_CARD_A的容量为8GB。
我们将SD_CARD_A克隆到pibox.img文件中。复制的字节的大小,它等于我们通过
/dev/sdc2
命令获得的值。一个块设备。我们加载回送模块。
root@pibox:~# df -Th
Filesystem Type Size Used Avail Use% Mounted on
/dev/root ext4 7.3G 1.1G 5.9G 16% /
/dev/mmcblk0p1 vfat 63M 21M 43M 33% /boot
我们发现未使用的回送设备路径。
root@mylaptop:~# df -Th
Filesystem Type Size Used Avail Use% Mounted on
/dev/sdb2 ext4 22G 13G 7.9G 63% /
/dev/sdb1 vfat 197M 2.6M 195M 2% /boot/efi
/dev/sda8 ext4 66G 11G 52G 17% /home
/dev/sdc1 vfat 63M 21M 43M 33% /media/some_user_name/boot
/dev/sdc2 ext4 7.3G 1.1G 5.9G 16% /media/some_user_name/some_uuid_serial
现在,我们为pibox.img文件创建一个回送设备。
root@mylaptop:~# umount /dev/sdc1
root@mylaptop:~# umount /dev/sdc2
我们触发有关分区更改的内核。
root@mylaptop:~# fdisk -l /dev/sdc
Disk /dev/sdc: 7969 MB, 7969177600 bytes
246 heads, 62 sectors/track, 1020 cylinders, total 15564800 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 identifier: 0x2019f6d8
Device Boot Start End Blocks Id System
/dev/sdc1 8192 137215 64512 c W95 FAT32 (LBA)
/dev/sdc2 137216 15564799 7713792 83 Linux
我们确认先前的操作是否成功。
root@mylaptop:~# dd bs=4MB if=/dev/sdc of=pibox.img
1992+1 records in
1992+1 records out
7969177600 bytes (8.0 GB) copied, 416.582 s, 19.1 MB/s
我们详细显示回送设备信息,以与SD_CARD_A进行比较。
root@mylaptop:~# modprobe loop
上面您可以看到回送设备的大小(= 7969177600字节)和分区与SD_CARD_A相同。
基础数学
从现在开始,我们将集中在分区
fdisk -l /dev/sdc
上。我们将其命名为THE_PARTITION。块大小为512字节(如打印在以Units =扇区.....开头的行上)在块15564799处结束,这意味着其大小为
/dev/loop0p2
(= 15564799 − 137216 + 1)。因此,THE_PARTITION的字节大小为
15427584 blocks
(= 512 * 15427584)。 > 要使THE_PARTITION适合SD_CARD_B,我们希望它的新大小为
7898923008 bytes
,或者换句话说,为3710940 blocks
(= 512 * 3710940)。由1900001280 bytes
(= 137216)+ 3848155
(= 3710940)-start block number
计算得出。 br /> 调整文件系统大小。通过将文件系统的大小设置为
size in blocks
来缩小THE_PARTITION上的文件系统。调整分区大小。我们将通过将THE_PARTITION的结束块号设置为
1
来进行收缩。收缩文件系统
root@mylaptop:~# losetup -f /dev/loop0
我们使用
3710940 blocks
来收缩文件系统。root@mylaptop:~# losetup /dev/loop0 pibox.img
收缩分区
3848155
的THE_PARTITION号是什么。root@mylaptop:~# partprobe /dev/loop0
我们用
e2fsck
缩小THE_PARTITION。与环回设备。我们将其分离。root@mylaptop:~# losetup /dev/loop0
/dev/loop0: [0806]:69 (/root/pibox.img)
截断图像文件
我们验证新的分区表。
root@mylaptop:~# fdisk -l /dev/loop0
Disk /dev/loop0: 7969 MB, 7969177600 bytes
255 heads, 63 sectors/track, 968 cylinders, total 15564800 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 identifier: 0x2019f6d8
Device Boot Start End Blocks Id System
/dev/loop0p1 8192 137215 64512 c W95 FAT32 (LBA)
/dev/loop0p2 137216 15564799 7713792 83 Linux
在输出中,可以清楚地看到THE_PARTITION的结束块号减少了
resize2fs
。我们使用的最后一个块是
parted
。块编号从0开始。因此,我们总共有3848155 + 1个块,并且pibox.img文件的新大小应为parted
(=(3848155 + 1)* 512)。我们截断pibox.img文件。
root@mylaptop:~# e2fsck -f /dev/loop0p2
e2fsck 1.42.9 (4-Feb-2014)
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
/dev/loop0p2: 41175/475776 files (0.2% non-contiguous), 309183/1928448 blocks
我们验证了pibox.img文件的新大小。
root@mylaptop:~# resize2fs /dev/loop0p2 3710940s
resize2fs 1.42.9 (4-Feb-2014)
Resizing the filesystem on /dev/loop0p2 to 463867 (4k) blocks.
The filesystem on /dev/loop0p2 is now 463867 blocks long.
创建SD_CARD_B
我们将SD_CARD_B放入笔记本电脑的读卡器中。
SD_CARD_B的分区会自动安装到系统
from 15564799 to 3848155
和3848155
。root@mylaptop:~# parted /dev/loop0
GNU Parted 2.3
Using /dev/loop0
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) print
Model: Loopback device (loop)
Disk /dev/loop0: 7969MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Number Start End Size Type File system Flags
1 4194kB 70.3MB 66.1MB primary fat16 lba
2 70.3MB 7969MB 7899MB primary ext4
(parted) quit
/>
上面您可以看到SD_CARD_B的容量为2GB。 />
我们将pibox.img文件克隆到SD_CARD_B中。
root@mylaptop:~# parted /dev/loop0 unit s resizepart 2 3848155
Warning: Shrinking a partition can cause data loss, are you sure you want to continue?
Yes/No? Yes
检查复制字节的大小,它等于我们通过
1970255872 bytes
命令获得的值。引导PIBOX
从笔记本电脑中取出SD_CARD_B并将其放入PIBOX板后,我们将引导系统并登录PIBOX控制台。
我们列出了分区(此处未显示一些其他不必要的系统分区)。
root@mylaptop:~# losetup -d /dev/loop0
评论
好一个我认为您设置环回的某些内容可能会很长且不必要,您可能需要检查一下。一个非常相似的问题非常相似:raspberrypi.stackexchange.com/a/29952/5538
–金锁♦
16-10-13在23:07
@goldilocks,未经测试,但我认为必须使用环回。据我所知,parted无法直接在图像文件上工作,它需要一个设备接口来进行操作。
–vaha
16-10-26在17:56
是的,但是我想您会发现您不必为lostup或-o loop =任何事情而烦恼。根据其他文章,我只使用mount -o offset = 123 / imagefilepath / mntpoint,而回送的使用是隐式的。我认为现在在Linux上通常是这样-尝试看看。然后,您可以减少到只说分区是通过虚拟“回送设备”安装的。
–金锁♦
16-10-26在18:14
#2 楼
使用dd if=/dev/sdx of=/path/to/image bs=1M
时,/dev/sdx
指的是整个“磁盘”,因此映像始终是整个卡的大小。相反,您需要使用
dd if=/dev/sdxn ...
,其中n
是分区号。您可能需要执行两次-一次用于
/boot
分区,一次用于/
分区。然后您需要在新的磁盘上创建分区。至少要与两个原始卡片一样大的卡片,才能将内容dd返回。
#3 楼
使用诸如parted(分区编辑器)之类的方法将主分区缩小为较小的大小,然后使用诸如Clonezilla之类的工具从现在较小的分区复制到新卡中。不过,您可能必须在另一台计算机上执行此操作。评论
不幸的是,这没有用。我使用GParted将分区压缩到2.5 GB。但是,当我尝试从USB记忆棒创建图像时,它变得更大了(4.3 GB-但我认为由于FAT文件大小的限制,它想复制整个32 GB并停止在4.3 GB上)。
– mwld
13年5月6日在8:26
我从以下线程使用命令dd if = / dev / sdx of = / path / to / image bs = 1M:raspberrypi.stackexchange.com/questions/311/…
– mwld
13年5月6日在8:27
您对我如何将2.5 GB的主分区复制到映像中并仍然使用可启动的Raspbian创建SD卡有任何想法吗?
– mwld
13年5月6日在8:29
回复晚了非常抱歉。我首先使用4GB的SD卡,创建了一个映像,然后将该映像写入8GB及更大的卡中。我不需要为我所做的任何事情使用更大的分区。我不知道有什么工具可以让您在SD卡上创建单个分区的映像。
–杰里·加农(Jerry Gagnon)
13年5月22日在19:36
#4 楼
使用已提及的方法之一创建卡的映像-如何备份Raspberry Pi?
使用http://sirlagz.net/2013/03/10/script-上的脚本自动rpi-image-downsizer /缩小图像
将缩小的图像恢复到新的较小卡上
评论
我试图达到相同的目标以备份我的树莓图像时碰到了这个页面,但是我不希望整个卡仅与卡上的相关数据有关。根据以上建议,我在这里sirlagz.net/2013/03/10/script-automatic-rpi-image-downsizer寻找脚本,但找不到一个。如果有可用链接,可以更新此链接吗?
– shallyverma
16-10-13在12:11
我仍然可以访问该链接,而帖子本身就是一个脚本。将脚本复制到文件中,并将其命名为script.sh,使用chmod使该文件可执行并执行。
– Mihir
16-10-15在13:31
#5 楼
我一直在使用rsync
将文件系统从一个磁盘复制到另一个磁盘已有一段时间了,而且没有打ic。使用rsync的好处是它正在复制文件系统的内容,而不是对设备进行块级复制。因此,只要目标驱动器有足够的空间来容纳数据,它实际上就不会在乎目标驱动器和源驱动器的大小。 br /> 在所需的较小的新SD卡上创建新的raspbian安装。
启动新安装并扩展文件系统以填充整个磁盘。关闭pi。
现在挂载新卡和旧卡,并使用
rsync -avx oldFilesystem newFilesystem
从旧卡中复制文件/将新卡上的文件系统与文件系统覆盖。确保您的固件是一致且最新的。之后,您的新卡上应该安装了功能完善的Raspbian系统。
评论
因此,对于这种方法(第3步),我需要2个SD卡读取器?
– Victor Van Hee
2014年5月17日下午6:47
两个SD卡读取器或一个中间设备。您可以将旧文件系统rsync到硬盘驱动器上的文件夹,然后将该文件夹rsync同步到第二张SD卡(如果您不想拿起读取器)。
– sdenton4
2014年5月20日17:55
您如何处理oldFilesystem和newFilesystem?
–德里克·马哈(Derek Mahar)
20-11-10在23:14
#6 楼
Rpi的SD卡复印机是一个很棒的工具,可用于创建卡的副本,它可以将较大的SD卡复制为较小的SD卡(只要有足够的空间来存储所有文件)可以将32 GB存储卡中的Raspbian复制到16 GB,但不应使用超过16 GB的存储空间。
此功能的链接:
此更新的链接
#7 楼
我创建了一个Shell脚本来备份和还原SD卡上的所有数据。它首先删除一些数据(对应于我的项目),然后将分区缩小到最小大小,因此图像与SD卡是。另外,该脚本会创建映像的* .zip文件。
将创建的映像还原到另一个SD卡后,分区将被放大到最大大小。
脚本使用提到的命令在其他答案中。因为这是我的第一个具有如此大小的shell脚本,所以我花了几个小时来创建它,而且它并不是完美的喷气机。特别是我不知道如何处理resize2fs和fdisk的返回值,因此用户必须输入我需要的值。有什么想法可以解决吗?
我希望这个脚本可以帮助其他人。随时进行编辑和改进。
"Usage:
<skriptname> -b <path> create backup of SC Card (dev/mmcblk0) to file <path>/JJJJ-MM-DD_HHMM.img
<skriptname> -r <path>/FILENAME.img restore an exitsting image (<path>/FILENAME.img) to the SD Card (dev/mmcblk0)
<skriptname> -r <path>/FILENAME.zip unzip and restore an exitsting image (<path>/FILENAME.zip) to the SD Card (dev/mmcblk0)
<skriptname> -h show this hlep
它是:
#!/bin/bash
# check if the user is root
if (( $EUID != 0 )); then
echo "This script requires root privileges please run as root"
exit
fi
while getopts ":b:r:h" opt; do
case $opt in
b)
mode="backup"
OUTPATH=$OPTARG
;;
r)
mode="restore"
DIRFILENAME=$OPTARG
;;
h)
mode="help"
;;
\?)
echo "Invalid option: -$OPTARG. Use -h for help" >&2
exit 1
;;
:)
echo "Option -$OPTARG requires an argument. Use -h for help" >&2
exit 1
;;
esac
done
# no option
if [ $OPTIND == 1 ]
then
echo "$(basename "q4312078q") needs an option! Use -h for help"
exit 1
fi
myMount(){
# create mountpoint if not existing
if [ ! -d /tmp/sd2/ ] ; then
mkdir /tmp/sd2
fi
# mount partition
mount -v -t ext4 /dev/mmcblk0p2 /tmp/sd2
err=$?
if [ $err != 0 ]; then
echo "mount failed error: $err"
exit 1
fi
}
myUmount(){
cd /home/ # otherwise umount will fail
# fuser -vm /tmp/sd2/
# umount partition
umount -v /tmp/sd2
err=$?
if [ $err != 0 ]; then
echo "umount failed error: $err"
exit 1
fi
}
myEnlarge(){
echo "enlarge partition..."
# enlarge partition is not posible with fdisk -> delete and recreate it
(
echo d # delete partition
echo 2 # patition number
echo n # add a new partition
echo p # primary partition
echo 2 # partition number
echo # first sector (accept default: varies)
echo # last sector (accept default: varies)
echo w # write changes
) | fdisk /dev/mmcblk0
echo "\n check filesystem... "
e2fsck -f -v -C 0 /dev/mmcblk0p2
# enlarge filesystem to maxsize
resize2fs -p /dev/mmcblk0p2
}
case "$mode" in
"help")
echo "Usage:
$(basename "q4312078q") -b <path> create backup of SC Card (dev/mmcblk0) to file <path>/JJJJ-MM-DD_HHMM.img
$(basename "q4312078q") -r <path>/FILENAME.img restore an exitsting image (<path>/FILENAME.img) to the SD Card (dev/mmcblk0)
$(basename "q4312078q") -r <path>/FILENAME.zip unzip and restore an exitsting image (<path>/FILENAME.zip) to the SD Card (dev/mmcblk0)
$(basename "q4312078q") -h show this hlep
--------------------------------
Adrian Zeitler, Germany 2017"
;;
"backup") ####################################### backup #######################################
echo "an image of the SD Card (/dev/mmcblk0) whitch is as smal as possible will be created to $OUTPATH."
# ------------------ delete some data --------------------
echo "Do you want to delete tempfiles? [y/n]"
read delfiles
if [ "$delfiles" = "y" ]
then
echo "Delete tempfiles..."
myMount
# remove some data
cd /tmp/sd2/home/alarm/
rm -v -f hagelbeere.db
rm -v -f HAILcam.log
rm -v -f HAILcam.log.1
rm -v -f test.jpg
myUmount
elif [ "$delfiles" = "n" ]
then
echo "I don't delete anything."
else
echo "Sorry, I didn't understand."
exit 1
fi
# --------------------------------------------------------------
# shrink partition 2 to minimum size
echo "check file system... "
e2fsck -f -v -C 0 /dev/mmcblk0p2
err=$?
if [ $err != 0 ]; then
echo "file system check failed, error: $err"
exit 1
fi
echo "shrink filesystem of partition 2 to minimum size..."
resize2fs -p -M /dev/mmcblk0p2
err=$?
if [ $err != 0 ]; then
echo "resize2fs failed, error: $err"
exit 1
fi
# --> Das Dateisystem auf /dev/mmcblk0p2 ist nun 692365 Blöcke groß.
echo "Please tell me the new filesystem size displayed above:"
read size
# from resize2fs blocksize, fdisk wants sector: sector = block * 8
size=$(( $size*8 ))
# shrink partition is not posible with fdisk -> delete and recreate it
(
echo d # delete partition
echo 2 # patition number
echo n # add a new partition
echo p # primary partition
echo 2 # partition number
echo # first sector (accept default: varies)
echo +$size # last sector
echo w # write changes
) | fdisk /dev/mmcblk0
err=$?
if [ $err != 0 ]; then
echo "fdisk failed, error: $err"
exit 1
fi
# --------------------------------------------------------------
# fill unused space with zeros
echo "Do you want to fill unused space with zeros? [y/n]"
read fillzeros
if [ "$fillzeros" = "y" ]
then
echo "Copy zeros. This will end up with an error. But this is ok."
myMount
dd if=/dev/zero | pv | dd of=/tmp/sd2/nullen.datei conv=noerror,notrunc,sync bs=10240
# exits with error -> this is normal
# dlelete zeros
rm -v -f /tmp/sd2/nullen.datei
sync
myUmount
elif [ "$fillzeros" = "n" ]
then
echo "I don't delete anything."
else
echo "Sorry, I didn't understand."
exit 1
fi
# --------------------------------------------------------------
# find out end of partition
fdisk -l /dev/mmcblk0
echo "Please tell me the end of mmcblk0p2 displayed above."
read count
DATE=$(date +"%Y-%m-%d_%H%M")
IMGFILENAME=$DATE.img
echo "Do you want to create image with filename $OUTPATH$IMGFILENAME? [y/n]"
read answer
if [ "$answer" = "y" ]
then
echo "Do you want to create a *.zip file of the created image? [y/n]"
read zip
echo "Do you want to enlarge partition 2 to maxsize after image creation? [y/n]"
read enlarge
echo "create image..."
cd $OUTPATH
# create image with dd, stop at and of partition
# count=N copy only N input blocks
# bs=BYTES read and write up to BYTES bytes at a time = block size
# pv show status
dd if=/dev/mmcblk0 | pv -s $(( $count*512 )) | dd of=$IMGFILENAME bs=512 count=$count
err=$?
if [ $err != 0 ]; then
echo "dd failed error: $err"
exit 1
fi
# --------------------------------------------------------------
# create zip file
# or like this:
# sudo dd if=/dev/sdX | pv |gzip > /pfad/zur/datei.img.gz
if [ "$zip" = "y" ]
then
echo "create zip file..."
zip $DATE.zip $IMGFILENAME
fi
# --------------------------------------------------------------
fi
# --------------------------------------------------------------
# enlarge partition 2
if [ "$enlarge" = "y" ]
then
myEnlarge
fi
;; #end case mode backup
"restore") ####################################### restore #######################################
#chek if image exists
if [[ -s "$DIRFILENAME" ]]
then
# check if file is an image or zip file
if [[ $DIRFILENAME =~ \.img$ ]]
then
IMGFILENAME=$(basename "$DIRFILENAME")
elif [[ $DIRFILENAME =~ \.zip$ ]]
then
ZIPFILENAME=$(basename "$DIRFILENAME")
else
echo "Not the right file format. I accept *.img and *.zip"
exit 1
fi
else
echo "Image file does not exist."
exit 1
fi
echo "the file $DIRFILENAME will be restored to the SD Card /dev/mmcblk0"
#change to the path of the imagefile
SOURCEPATH=$(dirname "$DIRFILENAME")
cd $SOURCEPATH
if [ "$ZIPFILENAME" != "" ]
then
echo "unzip file"
# change file extention form zip zu img
l=$(( ${#ZIPFILENAME}-3 ))
IMGFILENAME="${ZIPFILENAME:0:l}img"
unzip $ZIPFILENAME
fi
echo "Do you realy want to restore $SOURCEPATH/$IMGFILENAME to the SD card /dev/mmcblk0?
Warning: all data on the device /dev/mmcblk0 will be lost! [y/n]"
read answer
if [ "$answer" = "y" ]
then
echo "Do you want to enlarge partition 2 to maxsize after restoring? [y/n]"
read enlarge
echo "restore image..."
filesize=$(wc -c <"$IMGFILENAME")
echo "Filesize = $filesize Byte"
dd if=$IMGFILENAME | pv -s $filesize | dd of=/dev/mmcblk0 bs=512
err=$?
if [ $err != 0 ]; then
echo "dd failed error: $err"
exit 1
fi
fi
# --------------------------------------------------------------
# enlarge partition 2
if [ "$enlarge" = "y" ]
then
myEnlarge
fi
;; #end case mode restore
esac
#8 楼
我发现最简单的解决方案是使用上面概述的dd命令备份较大的原始卡,然后使用piwriter等将映像还原到较小的存储卡。 dd可能也可以工作...不确定。 PiWriter由于空间不足而返回了错误,但是由于映像中没有任何实际数据,超出了较小卡的大小,它只是截断了空扇区。我不确定这意味着什么...分区可能需要检查或修复,但是当我将其放入Pi中时,我可以验证它是否有效。评论
这是一个非常危险的建议,您永远不会知道实际上是否有任何超出大小的数据。我们正在寻找更可靠,行之有效的解决方案。
– lenik
2014年1月13日13:30在
我生活得很危险,我该怎么说;)总体而言,尽管我没有使用dd或分区图的丰富经验,所以我处在未知的领域。我可能很幸运,因为从16GB卡到8GB卡只有大约800MB的数据。但是出于好奇,是否有任何方法可能首先对数据进行碎片整理,以确保将其全部分组在分区的开头?似乎有点黑,但也许是?
–狗
2014年1月13日19:32
我不了解碎片整理,但是您绝对可以调整分区大小并将其移至SD卡的开头,因此它们仅占据开头。比简单的dd花费更长的时间,但是结果要可靠得多。
– lenik
2014年1月13日23:40
#9 楼
我使用旧版本的win32diskimager-RELEASE-0.1-r15-win32
读取图像,它甚至从8GB SD卡创建了4GB图像,然后使用最新版本的win32diskimager写入该图像。旧的会跳过所有错误。评论
新版本0.95中没有选项,您可以这样做,即跳过每个错误吗?不幸的是,sourceforge页面似乎没有列出任何可用的选项。使用pre-beta软件似乎有点冒险
– Greenonline
16-3-27在11:22
我不会使用会跳过所有错误的程序而感到毛骨悚然。
– RufusVS
19年8月22日在17:17
评论
系统将运行得更好,并且该卡将在主分区中具有更多可用空间的情况下使用更长的时间,所以请不要将其缩小太多-使其使用量至少翻倍(例如,如果您的系统为2-3 GB,则使用8GB卡,并扩大分区以填充所有可用空间)。请注意,如果您没有扩大分区的开头,它将不会是32 GB,因此您不必缩小分区。感谢您指出这一点,但我的Raspberry目前仅使用1.8 GB,因为它是一个非常基本的安装。所以我想4 GB应该足够了。
我想我在首次安装Debian Wheezy时就将其扩展到了完整尺寸。现在我将其压缩到2.5 GB,但仍然没有成功。请在下面查看我的评论。
几乎重复:raspberrypi.stackexchange.com/q/29947/5538
如果以下答案之一满足您的问题,请检查答案。