前言
? ? ? ?樹莓派官方的鏡像只有3種:1)lite,就是沒有圖形界面的精簡版;2)pixel的圖形界面,這個是上手就用的,有很多我用不著的軟件;3)大雜燴版本,可以自己選擇裝幾個推薦的系統(tǒng)的。
我搞樹莓派主要是學(xué)習(xí)一下linux還有學(xué)習(xí)python還有搞搞GPIO什么的,所以其實只要一個帶有圖形界面的精簡系統(tǒng)+python IDE就好了。所以簡單的作法就是用lite系統(tǒng)安裝圖形界面再安裝自己習(xí)慣的IDE就好了,不過每次都重頭做起就非常繁瑣,所以需要學(xué)會制作一個自定義鏡像。
總體步驟環(huán)節(jié)
1.生成臨時目錄、軟件準(zhǔn)備
2.生成鏡像文件
3.對鏡像文件進(jìn)行分區(qū)、格式化還有裝載
4.拷貝鏡像文件,備份文件
5.設(shè)置PARTUUID
6.清理過程文檔
使用方式:在腳本所在目錄里,執(zhí)行命令
sudo ?./backup.sh /home/pi
代碼解釋
#!/bin/bash
set -e
# start? ?設(shè)置備份的路徑,我習(xí)慣是/home/pi
if [ -z $1 ]; then??
? echo "Backup directory not set, required."
? exit 1
fi
BACKUP_DIR=$1
BACK_UP_DIR=$BACKUP_DIR/backup
sudo mkdir $BACK_UP_DIR
echo
# install? 安裝需要的軟件安裝包?
echo "Installing package ..."
apt-get install dosfstools dump parted kpartx rsync -y
echo "Finish."
echo
# create image? 生成 備份鏡像img文件
echo "Creating image ..."
ROOT=`df -P | grep /dev/root | awk '{print $3}'`? ?#獲取 ROOT的文件大小
MMCBLK0P1=`df -P | grep /dev/mmcblk0p1 | awk '{print $2}'`? #獲取主目錄的文件大小
ALL=`echo $ROOT $MMCBLK0P1 |awk '{print int(($1+$2)*1.2)}'`? #生成一個比ROOT目錄和主目錄大一點的IMG文件
#TIME=`date "+%Y%m%d%H%M%S"` ?#用于添加時間戳,不過沒有什么太大的用處。所以注釋掉。
FILE=$BACK_UP_DIR/backup.img ?#備份后的img文件名
dd if=/dev/zero of=$FILE bs=1K count=$ALL
echo "Root size is $ROOT"
echo "root size is $MMCBLK0P1"
echo "FILE Path is $FILE"
echo "Finish."
echo
# part
echo "Parting image ..." ?#格式化 ROOT和根目錄
P1_START=`fdisk -l /dev/mmcblk0 | grep /dev/mmcblk0p1 | awk '{print $2}'`
P1_END=`fdisk -l /dev/mmcblk0 | grep /dev/mmcblk0p1 | awk '{print $3}'`
P2_START=`fdisk -l /dev/mmcblk0 | grep /dev/mmcblk0p2 | awk '{print $2}'`
echo "P1_start is :$P1_START .P1_end is : $P1_END? .P2_start is :$P2_START"
parted $FILE --script -- mklabel msdos
parted $FILE --script -- mkpart primary fat32 ${P1_START}s ${P1_END}s
parted $FILE --script -- mkpart primary ext4 ${P2_START}s -1
parted $FILE --script -- quit
echo "Finish."
echo
# mount
echo "Mounting ..."
loopdevice_dst=`sudo losetup -f --show $FILE`?
echo "loopdevice_dst is $loopdevice_dst"
PART_BOOT="/dev/dm-0"
PART_ROOT="/dev/dm-1"
sleep 1
device_dst=`kpartx -va $loopdevice_dst | sed -E 's/.*(loop[0-9])p.*/\1/g' | head -1`
sleep 1
device_dst="/dev/mapper/${device_dst}"
sleep 1
sudo mkfs.vfat ${device_dst}p1? #-n boot?
sleep 1
sudo mkfs.ext4 ${device_dst}p2
sleep 1
echo "======4 copy file to img=========" ?# 開始拷貝文件
sleep 2
# backup /dev/boot
echo "Backing up disk /dev/boot ..."
sleep 1
dst_boot_path=$BACK_UP_DIR/dst_boot
sudo mkdir? $dst_boot_path
mount -t vfat ${device_dst}p1 $dst_boot_path?
cp -rfp /boot/* $dst_boot_path
echo "Finish."
echo
# backup /dev/root
echo "Backing up disk /dev/root ..."
sleep 1
dst_root_path=$BACK_UP_DIR/dst_root
sudo mkdir? $dst_root_path
sleep 1
sudo mount -t ext4 ${device_dst}p2 $dst_root_path
cd $dst_root_path
echo "dst_root_path is $dst_root_path"
sudo chmod 777? $dst_root_path/
sudo rsync -ax? -q --exclude="$FILE" --exclude=$BACK_UP_DIR/*? --exclude=/sys/* --exclude=/proc/*? --exclude=/tmp/* /? $dst_root_path/ ? #通過rsync 來同步根目錄到IMG鏡像中,排除了一些不需要同步的文件
echo "Finish."
echo "back folder? $BACKUP_DIR"
cd $BACKUP_DIR
sync
echo
# replace PARTUUID ?#替換PARTUUID 這步非常重要,liunx啟動時會對PARTUUID有特定的指定,備份的時候是把舊的也同步過來,需要根據(jù)新的IMG文件來更新PARTUUID
echo "======5 replace PARTUUID========="
opartuuidb=`blkid -o export /dev/mmcblk0p1 | grep PARTUUID`
opartuuidr=`blkid -o export /dev/mmcblk0p2| grep PARTUUID`
npartuuidb=`blkid -o export ${device_dst}p1 | grep PARTUUID`
npartuuidr=`blkid -o export ${device_dst}p2 | grep PARTUUID`
echo "BOOT uuid old=$opartuuidb -> new=$npartuuidb"
echo "ROOT uuid old=$opartuuidr -> new=$npartuuidr"
sudo sed -i "s/$opartuuidr/$npartuuidr/g" $dst_boot_path/cmdline.txt
sudo sed -i "s/$opartuuidb/$npartuuidb/g" $dst_root_path/etc/fstab
sudo sed -i "s/$opartuuidr/$npartuuidr/g" $dst_root_path/etc/fstab
echo "======6 cleaning =========" #清理釋放裝載的文件夾
echo "Create backup img done, clear job ? Y/N"
read key
if [ "$key" = "y" -o "$key" = "Y" ]; then
sleep 15
sudo umount $dst_boot_path
sudo umount $dst_root_path
? sudo? kpartx? -d ${device_dst}p1
? sudo? kpartx -d ${device_dst}p2
sudo? losetup -d $loopdevice_dst? ?
sudo rm -rf? $dst_boot_path
sudo rm -rf? $dst_root_path
fi
echo "==========Done==================="
exit 0
恢復(fù)的時候用winimage將img文件恢復(fù)就行,用鏡像文件是第一步是需要用fdisk 來擴(kuò)展根目錄的大小。