Linux 調整根分區大小(非 LVM )
2016.7.24 by flb
起因:因一個項目需求,需在線將 ubuntu 系統刷成 openwrt x86 。 30G 的磁盤升級成 openwrt 后,只用了 50M 左右。固需將其根目錄掛載的分區進行擴容。因為不能使用 live CD 之類的工具( gparted ),固有以下文章。
配置: Linux version 3.2.0-72-generic (buildd@toyol) (gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) )
本文主要完成兩個工作:
1 、將 ubuntu 系統刷成 openwrt x86 。
2 、擴大磁盤的容量。
一、刷成 openwrt x86 有兩種方法。
1 )簡易部署
使用 U 盤啟動,將 combined.img 直接 dd 到目標盤。
gunzip
bin/x86/openwrt-x86-generic-combined-ext4.img.gz dd
if =bin/x86/openwrt-x86-generic-combined-ext4.img of=/dev/sdb # 根據自己情況選擇磁盤
2 )自定義部署
a 、建立分區、文件系統。
b 、用 dd 將 rootfs.ext4.img 寫入分區。
c 、復制 vmlinuz 到分區。
d 、修改 grub 文件,使其使用該 vmlinuz 加載內核。
e 、啟動。
二、調整根分區磁盤容量。
基本思路:我們知道,我們不能調整 mount 的分區,也不可能 umount 根分區。固最 簡單調整磁盤容易的方法就是使用 live CD 或 U 盤啟動后使用 Gparted 工具。或者進入 rescue 模式,然后使用 fdisk 及 resize2fs 這兩個命令就可以輕松搞定。但以上都不 符合我的情況。
查資料方法大概有兩種 :
1 、使用 pivot_root , umount 掉根目錄;然后對其操作。具體方法參加: http://unix./questions/226872/how-to-shrink-root- filesystem-without-booting-a-livecd/227318#227318 ( 本人未成功 )
2 、既然不能操作已 mount 的根目錄;故只能在未 mount 根目錄時對分區進行操作。 我們知道 啟動流程: BIOS 加電- > 啟動 grub 引導程序 ->grub 解壓內核,加載 initrd-> 在 initrd 環境中運行 -> 掛載根文件系統并切換。 可知系統在 initrd 環境中 運行使用的是虛擬文件系統,因此可在其掛載根文件系統前調整根分區的容量。
關于 initrd 的相關知識可參考: http://www./blog/2014/02/20/CentOS- initrd%E5%88%86%E6%9E%90.html 此處不再重述。
三、具體方法
1 、將 initrd.img 文件解壓。
2 、解壓后的目錄結構如下:
3 、 initrd 環境中沒有 fdisk 、 resize2fs 、 e2fsck 命令,所以需將這三個命令拷貝到 bin 目錄中,并用 ldd 查看相關聯的庫文件是否都存在(我所用的系統都含用相關的 庫)。
3 、掛載根目錄的操作是 init 里的調用 mountroot 函數(/ scripts/local 里);我 們修改 local 里的代碼。
disk=sda2
說明:使用用 fdisk 將要擴展的分區刪除(記住起始點),再重新新建。然后 e2fsck 檢 查磁盤,再使用 resize2fs 即可;若是縮小分區容量,則先 resize2fs 再 fdisk 。
4 、修改完成將 initrd.img 重新打包壓縮。
5 、修改 grub 引導,使其使用該 initrd.img 啟動。
參考資料:
1 ) How to shrink root filesystem without booting a livecd
2 ) CentOS-initrd 分析
3 ) Howto shrink a remote root ext3 filesystem on Debian wheezy
4) Linux2.6 內核的 Initrd 機制解析
附兩個腳本:
1 、 upgradePkg.sh #!/bin/bash
echo "Start to modify the initrd file....." mkdir ./initrdTmp initrdName=`ls /boot | grep initrd.img-` cp /boot/$initrdName ./initrdTmp/$initrdName.gz gunzip ./initrdTmp/$initrdName.gz cd ./initrdTmp cpio -i -d < ./$initrdName rm -f ./$initrdName cp ../openwrt-x86-generic-combined-ext4.img ./ #copy fdisk e2fsck resize2fs cp /sbin/fdisk ./bin cp /sbin/e2fsck ./bin cp /sbin/resize2fs ./bin
#cp resize.sh to /scripts cp ../resize.sh ./scripts chmod +x ./scripts/resize.sh
sed '/Mount root/i\. /scripts/resize.sh' ./scripts/local > ./scripts/local.tmp mv ./scripts/local.tmp ./scripts/local
echo "Start to gzip the initrd file....." find ./ | cpio -H newc -o | gzip -v -9 >/boot/$initrdName.tmp mv /boot/$initrdName.tmp /boot/$initrdName echo "Finish the initrd flie , will be reboot....." reboot
2 、 resize.sh #!/bin/bash ######################### #1 、通過 dd 命令將 openwrt 鏡像寫入 sda 磁盤
#2 、 fdisk 修改 sda2 (根目錄)的分區
#3 、 resize2fs 擴大 sda2 的大小
######################### disk="sda2" echo "Start to write openwrt image(/dev/sda) with dd......" dd if=/openwrt-x86-generic-combined-ext4.img of=/dev/sda
part2_start=`fdisk -l /dev/sda | grep $disk | awk '{print $2}'` echo "Start toextend partion2 from $part2_start to end ....." /bin/fdisk /dev/sda << __EOF__ >> /dev/null |
|