/********************************************************************************** * raspi-config Expand root partition to fill SD card 原理 * 说明: * 想知道树莓派是如何完成SD卡扩展的,记录相关文档。 * * 2017-2-20 深圳 南山平山村 曾剑锋 ********************************************************************************/ 一、参考文档: 1. Raspbian: how to resize the root partition to fill SD card https://coderwall.com/p/mhj8jw/raspbian-how-to-resize-the-root-partition-to-fill-sd-card 2. raspi-config https://github.com/asb/raspi-config/blob/master/raspi-config 3. Making a bootable .img image file http://www.orangepi.org/Docs/Makingabootable.html 4. Setting up the Linux distribution root file system http://www.orangepi.org/Docs/SettinguptheLinux.html 5. Bootable SD card http://sunxi.org/Bootable_SD_card#Cleaning 二、raspi-config主要源代码有关SD卡扩展函数分析: do_expand_rootfs() { # -h : FILE exists and is a symbolic link (same as -L) if ! [ -h /dev/root ]; then whiptail --msgbox "/dev/root does not exist or is not a symlink. Don't know how to expand" 20 60 2 return 0 fi # readlink用来找出符号链接所指向的位置。 ROOT_PART=$(readlink /dev/root) # 从变量$string的开头, 删除最短匹配$substring的子串 PART_NUM=${ROOT_PART#mmcblk0p} if [ "$PART_NUM" = "$ROOT_PART" ]; then whiptail --msgbox "/dev/root is not an SD card. Don't know how to expand" 20 60 2 return 0 fi # NOTE: the NOOBS partition layout confuses parted. For now, let's only # agree to work with a sufficiently simple partition layout if [ "$PART_NUM" -ne 2 ]; then whiptail --msgbox "Your partition layout is not currently supported by this tool. You are probably using NOOBS, in which case your root filesystem is already expanded anyway." 20 60 2 return 0 fi # 再次确认分区表和设备节点提取的数值是否一致 # # shell script: # root@zengjf:/home/zengjf/hacking# parted /dev/sdb -ms unit s p # BYT; # /dev/sdb:1953525168s:scsi:512:4096:gpt:ATA ST1000LM035-1RK1:; # 1:2048s:943720448s:943718401s:ntfs:Basic data partition:msftdata; # 2:943722496s:1953523711s:1009801216s:ntfs:Basic data partition:msftdata; LAST_PART_NUM=$(parted /dev/mmcblk0 -ms unit s p | tail -n 1 | cut -f 1 -d:) if [ "$LAST_PART_NUM" != "$PART_NUM" ]; then whiptail --msgbox "/dev/root is not the last partition. Don't know how to expand" 20 60 2 return 0 fi # Get the starting offset of the root partition # 获取文件系统分区起始位置 PART_START=$(parted /dev/mmcblk0 -ms unit s p | grep "^${PART_NUM}" | cut -f 2 -d:) [ "$PART_START" ] || return 1 # Return value will likely be error for fdisk as it fails to reload the # partition table because the root fs is mounted fdisk /dev/mmcblk0 <<EOF p d $PART_NUM n p $PART_NUM $PART_START p w EOF ASK_TO_REBOOT=1 # now set up an init.d script cat <<EOF > /etc/init.d/resize2fs_once && #!/bin/sh ### BEGIN INIT INFO # Provides: resize2fs_once # Required-Start: # Required-Stop: # Default-Start: 2 3 4 5 S # Default-Stop: # Short-Description: Resize the root filesystem to fill partition # Description: ### END INIT INFO . /lib/lsb/init-functions case "$1" in start) log_daemon_msg "Starting resize2fs_once" && resize2fs /dev/root && # 真正调整大小的地方 rm /etc/init.d/resize2fs_once && # 删除文件,表明该文件只能被运行一次 update-rc.d resize2fs_once remove && log_end_msg $? ;; *) echo "Usage: $0 start" >&2 exit 3 ;; esac EOF chmod +x /etc/init.d/resize2fs_once && # 给出下次运行的权限 update-rc.d resize2fs_once defaults && # 默认运行 if [ "$INTERACTIVE" = True ]; then whiptail --msgbox "Root partition has been resized. The filesystem will be enlarged upon the next reboot" 20 60 2 fi } 三、获取磁盘编号、起始偏移地址、结束偏移地址、分区格式: zengjf@zengjf:~/zengjf/mksdImageFile$ sudo parted /dev/sdc -ms unit s p BYT; /dev/sdc:3887104s:scsi:512:512:msdos:NORELSYS 1081:; 1:2048s:43007s:40960s:fat16::; 2:43008s:204799s:161792s:ext4::; 四、resizefs重新调整分区大小: zengjf@zengjf:/media/zengjf/e09b9d90-3b63-43fa-9b31-485e153c3ccb$ sudo resize2fs /dev/sdc2 resize2fs 1.43.3 (04-Sep-2016) /dev/sdc2 上的文件系统已被挂载于 /media/zengjf/e09b9d90-3b63-43fa-9b31-485e153c3ccb;需要进行在线调整大小 old_desc_blocks = 1, new_desc_blocks = 15 /dev/sdc2 上的文件系统现在为 1922048 个块(每块 1k)。