前言
树莓派官方的镜像只有3种:1)lite,就是没有图形界面的精简版;2)pixel的图形界面,这个是上手就用的,有很多我用不着的软件;3)大杂烩版本,可以自己选择装几个推荐的系统的。
我搞树莓派主要是学习一下linux还有学习python还有搞搞GPIO什么的,所以其实只要一个带有图形界面的精简系统+python IDE就好了。所以简单的作法就是用lite系统安装图形界面再安装自己习惯的IDE就好了,不过每次都重头做起就非常繁琐,所以需要学会制作一个自定义镜像。
总体步骤环节
1.生成临时目录、软件准备
2.生成镜像文件
3.对镜像文件进行分区、格式化还有装载
4.拷贝镜像文件,备份文件
5.设置PARTUUID
6.清理过程文档
使用方式:在脚本所在目录里,执行命令
sudo ./backup.sh /home/pi
代码解释
#!/bin/bash
set -e
# start 设置备份的路径,我习惯是/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有特定的指定,备份的时候是把旧的也同步过来,需要根据新的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
恢复的时候用winimage将img文件恢复就行,用镜像文件是第一步是需要用fdisk 来扩展根目录的大小。