├── README.md ├── back.sh └── resize.sh /README.md: -------------------------------------------------------------------------------- 1 | # rpi-backup 2 | 3 | 树莓派系统备份脚本 4 | 5 | ## 一、测试系统 6 | 7 | 1、2020-02-13-raspbian-buster-lite (成功) 8 | 9 | 2、ubuntu-20.04-preinstalled-server-arm64 (成功) 10 | 11 | 3、ubuntu-18.04-desktop-arm64 (成功) 12 | 13 | 4、2019-12-30-OPENFANS-Debian-Buster-Aarch64-ext4-v2019-2.0-U2-Release-plus++ (成功) 14 | 15 | ## 二、back.sh(备份脚本,需要root权限) 16 | 17 | 用法:sudo bash back.sh xxx.img (xxx.img为备份文件名,自行修改) 18 | 19 | **1. 备份镜像大小计算:(boot分区全部 + root分区已使用) * 1.2** 20 | 21 | **2. 如果sd卡剩余空间充足,可以备份到卡内,如果剩余空间有限,请备份到外部设备** 22 | 23 | **3. 如果需要备份到外部设备,设备务必挂载到/media,不要挂载到/mnt,因为创建的镜像会挂载到/mnt进行操作** 24 | 25 | ## 三、resize.sh(扩容脚本,需要root权限) 26 | 27 | 用法:恢复系统后执行 sudo bash resize.sh 扩容root分区,也可以用树莓派raspi-config进行扩容 28 | 29 | ## 四、参考资料 30 | 1. https://blog.csdn.net/lzjsqn/article/details/72058293 31 | 2. 4.14.114-OPENFANS+20190602-v8 64位debain系统 /usr/sbin/resize.root 脚本 32 | -------------------------------------------------------------------------------- /back.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ `whoami` != "root" ];then 4 | echo "This script must be run as root!" 5 | exit 1 6 | fi 7 | 8 | # install software 9 | apt update 10 | apt install -y dosfstools parted kpartx rsync 11 | 12 | echo "" 13 | echo "software is ready" 14 | 15 | file="rpi-`date +%Y%m%d%H%M%S`.img" 16 | 17 | if [ "x$1" != "x" ];then 18 | file="$1" 19 | fi 20 | 21 | # boot mount point 22 | boot_mnt=`findmnt -n /dev/mmcblk0p1 | awk '{print $1}'` 23 | 24 | root_info=`df -PT / | tail -n 1` 25 | 26 | root_type=`echo $root_info | awk '{print $2}'` 27 | 28 | dr=`echo $root_info | awk '{print $4}'` 29 | db=`df -P | grep /dev/mmcblk0p1 | awk '{print $2}'` 30 | ds=`echo $dr $db |awk '{print int(($1+$2)*1.2)}'` 31 | 32 | echo "create $file ..." 33 | 34 | dd if=/dev/zero of=$file bs=1K count=0 seek=$ds 35 | #truncate -s ${ds}k $file 36 | 37 | start=`fdisk -l /dev/mmcblk0| awk 'NR==9 {print $2}'` 38 | end=`fdisk -l /dev/mmcblk0| awk 'NR==9 {print $3}'` 39 | 40 | if [ "$start" == "*" ];then 41 | start=`fdisk -l /dev/mmcblk0| awk 'NR==9 {print $3}'` 42 | end=`fdisk -l /dev/mmcblk0| awk 'NR==9 {print $4}'` 43 | fi 44 | 45 | start=`echo $start's'` 46 | end=`echo $end's'` 47 | 48 | end2=`fdisk -l /dev/mmcblk0| awk 'NR==10 {print $2}'` 49 | end2=`echo $end2's'` 50 | 51 | echo "start=$start" 52 | echo "end=$end" 53 | echo "end2=$end2" 54 | 55 | parted $file --script -- mklabel msdos 56 | parted $file --script -- mkpart primary fat32 $start $end 57 | parted $file --script -- mkpart primary ext4 $end2 -1 58 | 59 | loopdevice=`losetup -f --show $file` 60 | device=`kpartx -va $loopdevice | sed -E 's/.*(loop[0-9])p.*/\1/g' | head -1` 61 | device="/dev/mapper/${device}" 62 | 63 | echo "device=$device" 64 | 65 | partBoot="${device}p1" 66 | partRoot="${device}p2" 67 | 68 | echo "partBoot=$partBoot" 69 | echo "partRoot=$partRoot" 70 | 71 | sleep 5s 72 | 73 | opartuuidb=`blkid -o export /dev/mmcblk0p1 | grep PARTUUID` 74 | opartuuidr=`blkid -o export /dev/mmcblk0p2 | grep PARTUUID` 75 | 76 | npartuuidb=`blkid -o export ${partBoot} | grep PARTUUID` 77 | npartuuidr=`blkid -o export ${partRoot} | grep PARTUUID` 78 | 79 | boot_label=`dosfslabel /dev/mmcblk0p1 | tail -n 1` 80 | root_label=`e2label /dev/mmcblk0p2 | tail -n 1` 81 | 82 | mkfs.vfat -F 32 -n "$boot_label" $partBoot 83 | echo "$partBoot format success" 84 | 85 | mkfs.ext4 $partRoot 86 | e2label $partRoot $root_label 87 | echo "$partRoot format success" 88 | 89 | mount -t vfat $partBoot /mnt 90 | cp -rfp ${boot_mnt}/* /mnt/ 91 | 92 | sed -i "s/$opartuuidr/$npartuuidr/g" /mnt/cmdline.txt 93 | 94 | sync 95 | 96 | umount /mnt 97 | 98 | mount -t ext4 $partRoot /mnt 99 | 100 | if [ -f /etc/dphys-swapfile ]; then 101 | SWAPFILE=`cat /etc/dphys-swapfile | grep ^CONF_SWAPFILE | cut -f 2 -d=` 102 | if [ "$SWAPFILE" = "" ]; then 103 | SWAPFILE=/var/swap 104 | fi 105 | EXCLUDE_SWAPFILE="--exclude $SWAPFILE" 106 | fi 107 | 108 | cd /mnt 109 | 110 | rsync --force -rltWDEgop --delete --stats --progress \ 111 | $EXCLUDE_SWAPFILE \ 112 | --exclude ".gvfs" \ 113 | --exclude "$boot_mnt" \ 114 | --exclude "/dev" \ 115 | --exclude "/media" \ 116 | --exclude "/mnt" \ 117 | --exclude "/proc" \ 118 | --exclude "/run" \ 119 | --exclude "/snap" \ 120 | --exclude "/sys" \ 121 | --exclude "/tmp" \ 122 | --exclude "lost\+found" \ 123 | --exclude "$file" \ 124 | / ./ 125 | 126 | if [ ! -d $boot_mnt ]; then 127 | mkdir $boot_mnt 128 | fi 129 | 130 | if [ -d /snap ]; then 131 | mkdir /mnt/snap 132 | fi 133 | 134 | for i in boot dev media mnt proc run sys boot; do 135 | if [ ! -d /mnt/$i ]; then 136 | mkdir /mnt/$i 137 | fi 138 | done 139 | 140 | if [ ! -d /mnt/tmp ]; then 141 | mkdir /mnt/tmp 142 | chmod a+w /mnt/tmp 143 | fi 144 | 145 | cd 146 | 147 | sed -i "s/$opartuuidb/$npartuuidb/g" /mnt/etc/fstab 148 | sed -i "s/$opartuuidr/$npartuuidr/g" /mnt/etc/fstab 149 | 150 | sync 151 | 152 | umount /mnt 153 | 154 | kpartx -d $loopdevice 155 | losetup -d $loopdevice 156 | 157 | 158 | -------------------------------------------------------------------------------- /resize.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | FSTYPE=$(cat /proc/cmdline |tr ' ' '\n' | awk -F= '/rootfstype/{print $2}') 3 | BLKDEV_ROOTPART=$(findmnt / -o SOURCE -n) 4 | ROOTPART_SEQ=$(echo $BLKDEV_ROOTPART | grep -o "[0-9]$") 5 | BLKDEV_ROOTPART_NAME=$(echo $BLKDEV_ROOTPART | cut -d "/" -f 3) 6 | BLKDEV=/dev/$(find /sys/block/*/ | grep $BLKDEV_ROOTPART_NAME$ | cut -d "/" -f 4) 7 | RESIZE_TARGET=$BLKDEV_ROOTPART 8 | 9 | if [ ! $RESIZER ]; then 10 | case $FSTYPE in 11 | f2fs) 12 | RESIZER=$(which resize.f2fs) 13 | ;; 14 | ext2|ext3|ext4) 15 | RESIZER=$(which resize2fs) 16 | ;; 17 | btrfs) 18 | RESIZER=$(which btrfs) 19 | RESIZER_ARGS="filesystem resize max" 20 | RESIZE_TARGET="/" 21 | mount -o remount,rw $RESIZE_TARGET 22 | ;; 23 | *) 24 | RESIZER=$(which resize.$FSTYPE) 25 | echo "FSTYPE is $FSTYPE, RESIZER could be $RESIZER" 26 | ;; 27 | esac 28 | if [ ! -e $RESIZER ]; then 29 | echo "Filesystem resizer for $FSTYPE not found!" 30 | exit 1 31 | fi 32 | fi 33 | 34 | echo "Resizing partiton..." 35 | parted -s $BLKDEV -- resizepart $ROOTPART_SEQ 100% 36 | 37 | echo "Informing kernel..." 38 | # Make sure we have updated partition info 39 | partx -u $BLKDEV 40 | partx -u $BLKDEV_ROOTPART 41 | partprobe $BLKDEV 42 | partprobe $BLKDEV_ROOTPART 43 | 44 | echo "Resizing filesystem..." 45 | $RESIZER $RESIZER_ARGS $RESIZE_TARGET 46 | 47 | systemctl daemon-reload 2>/dev/null 48 | ldconfig 2>/dev/null 49 | 50 | echo "Syncing to disk..." 51 | sync && sync 52 | 53 | echo '' 54 | echo "Rebooting in 5 seconds..." 55 | a=5 56 | for i in $(seq 1 5); do 57 | echo $a 58 | sleep 1 59 | a=$((a-1)) 60 | done 61 | 62 | echo "Rebooting..." 63 | init 6 64 | --------------------------------------------------------------------------------