我的 Raspberry PI 雖然已經使用 2A 的變壓器,如果 USB 裝置吃電兇一點的,拔插時仍常遇到自動 reboot 而掛點的慘劇。預防這樣的事情,最簡單的當然是將系統備份起來,不過,16GB 的 SD 卡明明就只用不到 3GB ,備份完的 image 卻有 16GB ,佔了不少磁碟空間,還原時也需要較久。如果以自訂大小的 image 檔案,經過分割、格式化後,再利用 dump & restore 來複製系統中的檔案,這樣就可以讓 image 比較接近實際使用空間的大小。很久沒玩 Linux ,本來卡在如何讓分割區可以一次下指令完成,看了下面這篇文章後,豁然開朗:
原來 Linux 還有「parted」、「losetup」和「kpartx」這三個好東西,以前在玩 FreeBSD 時,好像沒印象。它們可以處理「虛擬磁碟」及磁碟分割的問題,內容複製的部份就交給 dump & restore 。底下先做主要步驟的解說,最後只要將各個指令放在一個 script 檔中,想重新備份時,執行 script 的一道指令就可以解決。
安裝工具
FAT32 分割區的格式化需要另外安裝「dosfstools」套件,而備份檔案用的 dump & restore 則需要安裝「dump」套件,最後,當然還有「parted」和「kpartx」套件囉!以下是安裝的指令:
sudo apt-get install dosfstools
sudo apt-get install dump
sudo apt-get install parted
sudo apt-get install kpartx
由於 Raspberry PI 的 USB 實在不快,我準備將 image 直接透過網路放在 Windows XP 中。下面的指令將 Windows (IP:192.168.2.100) 分享出來的「images」這個磁碟資源,以 MyUsername 的帳號及 MyPassword 的密碼連線後,掛載到 /mnt 裡。
sudo mount -t cifs -o user=MyUsername,password=MyPassword //192.168.2.100/images /mnt掛載成功以後,切換到 /mnt 裡面,並以 dd 來產生一個檔名為「gsyan.img」,大小為「2500MB」的虛擬磁碟檔案。指令如下:
cd /mnt
sudo dd if=/dev/zero of=gsyan.img bs=1MB count=2500
分割虛擬磁碟
底下利用 parted 將虛擬磁碟切成兩個分割區
- 第一個分割區採用 FAT32,由 sector 8192 開始到 sector 12879,約 62.9MB
- 第二個分割區採用 EXT4,由 sector 122880 開始到結束。
執行底下的指令
sudo parted gsyan.img --script -- mklabel msdos
sudo parted gsyan.img --script -- mkpart primary fat32 8192s 122879s
sudo parted gsyan.img --script -- mkpart primary ext4 122880s -1
掛載虛擬磁碟並格式化
底下利用 losetup 及 kpartx 來建立虛擬磁碟分割區的裝置,為了方便後面指令的呼叫,會順便利用指令的回應,產生一些好用的變數:
- loopdevice:執行 losetup 連結 image 檔案的 loop device 代號,kpartx 需要這個裝置名稱。
- device:執行完 kpartx 後,虛擬磁碟的裝置代號。
- partBoot:由 device 加上 p1 組合而成的 FAT32 分割區的裝置代號。
- partRoot:由 device 加上 p2 組合而成的 EXT4 分割區的裝置代號。
建立虛擬磁碟及分割區裝置的指令如下:
loopdevice=`sudo losetup -f --show gsyan.img`
device=`sudo kpartx -va $loopdevice | sed -E 's/.*(loop[0-9])p.*/\1/g' | head -1`
device="/dev/mapper/${device}"
partBoot="${device}p1"
partRoot="${device}p2"
將兩個分割區格式化,執行底下指令:
sudo mkfs.vfat $partBoot
sudo mkfs.ext4 $partRoot
備份檔案
虛擬磁碟建立好後,接著我們將 /boot (Raspberry PI 的 FAT32分割區)中的檔案直接用「cp」來複製:
sudo mount -t vfat $partBoot /media
sudo cp -rfp /boot/* /media/
sudo umount /media
Linux 分割區的部份則利用 dump & restore 來複製:
卸載虛擬磁碟
所有備份檔案的工作完成後,我們就可以將虛擬磁碟斷線,依序執行下面的指令:
sudo mount -t ext4 $partRoot /media/
cd /media
sudo dump -0uaf - / | sudo restore -rf -
cd
sudo umount /media
卸載虛擬磁碟
所有備份檔案的工作完成後,我們就可以將虛擬磁碟斷線,依序執行下面的指令:
sudo kpartx -d $loopdevice
sudo losetup -d $loopdevice
umount /mnt
經過這樣的程序,下面系統再有問題,直接把 image 檔重新寫回 SD 卡,用該 SD 卡在 Raspberry PI 上開機後,再執行 raspi-config 裡的「Expand Filesystem」,即可還原系統。
底下將前述的指令組合起來:
#!/bin/sh
sudo mount -t cifs -o user=MyUsername,password=MyPassword //192.168.2.100/images /mnt
cd /mnt
sudo dd if=/dev/zero of=gsyan.img bs=1MB count=2500
sudo parted gsyan.img --script -- mklabel msdos
sudo parted gsyan.img --script -- mkpart primary fat32 8192s 122879s
sudo parted gsyan.img --script -- mkpart primary ext4 122880s -1
loopdevice=`sudo losetup -f --show gsyan.img`
device=`sudo kpartx -va $loopdevice | sed -E 's/.*(loop[0-9])p.*/\1/g' | head -1`
device="/dev/mapper/${device}"
partBoot="${device}p1"
partRoot="${device}p2"
sudo mkfs.vfat $partBoot
sudo mkfs.ext4 $partRoot
sudo mount -t vfat $partBoot /media
sudo cp -rfp /boot/* /media/
sudo umount /media
sudo mount -t ext4 $partRoot /media/
cd /media
sudo dump -0uaf - / | sudo restore -rf -
cd
sudo umount /media
sudo kpartx -d $loopdevice
sudo losetup -d $loopdevice
umount /mnt
Hi 雄大您好:
回覆刪除我在raspberry pi 3 上面操作sudo mkfs.vfat $partBoot時會跳出
invalid option --E 的錯誤 請問是不是sed 這個指令沒有-E 呢?