diff --git a/emmc_backup_from_sd.sh b/emmc_backup_from_sd.sh new file mode 100644 index 0000000..00adef8 --- /dev/null +++ b/emmc_backup_from_sd.sh @@ -0,0 +1,143 @@ +#!/bin/bash +#=============================================================================== +# 从SD卡操作eMMC备份脚本 +#=============================================================================== + +set -e +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +error_msg() { echo -e "${RED}[ERROR] $1${NC}" >&2; exit 1; } +info_msg() { echo -e "${GREEN}[INFO] $1${NC}"; } +warn_msg() { echo -e "${YELLOW}[WARN] $1${NC}"; } + +[[ $EUID -eq 0 ]] || error_msg "需要root权限" + +EMMC_DEV="/dev/mmcblk0" +USB_DIR="/mnt/XIN_USB/rock5c" +OUTPUT_FILE="${USB_DIR}/rock5c_emmc_$(date +%Y%m%d_%H%M%S).img" + +info_msg "从SD卡备份eMMC..." +info_msg "eMMC设备: ${EMMC_DEV}" +info_msg "输出到: ${OUTPUT_FILE}" + +# 检查设备 +[[ -b "${EMMC_DEV}" ]] || error_msg "eMMC设备不存在: ${EMMC_DEV}" +[[ -d "${USB_DIR}" ]] || error_msg "USB目录不存在: ${USB_DIR}" + +# 检查eMMC没有被挂载 +if mount | grep -q mmcblk0; then + error_msg "eMMC还在使用中!请确保从SD卡启动" +fi + +info_msg "✅ eMMC设备可安全操作" + +# 步骤1: 检查eMMC分区信息 +info_msg "步骤1: 分析eMMC分区..." +parted -s ${EMMC_DEV} unit MB print + +# 检查eMMC上的数据大小 +info_msg "检查eMMC数据使用量..." +TEMP_MOUNT="/tmp/check_emmc" +mkdir -p "${TEMP_MOUNT}" + +# 临时挂载检查使用量 +mount ${EMMC_DEV}p2 "${TEMP_MOUNT}" -o ro +EMMC_USED=$(df --block-size=1M "${TEMP_MOUNT}" | tail -1 | awk '{print $3}') +umount "${TEMP_MOUNT}" + +mount ${EMMC_DEV}p1 "${TEMP_MOUNT}" -o ro +EMMC_BOOT_USED=$(df --block-size=1M "${TEMP_MOUNT}" | tail -1 | awk '{print $3}') +umount "${TEMP_MOUNT}" + +rm -rf "${TEMP_MOUNT}" + +info_msg "eMMC使用情况: Root ${EMMC_USED}MB + Boot ${EMMC_BOOT_USED}MB" + +# 步骤2: 智能收缩eMMC分区 +info_msg "步骤2: 智能收缩eMMC分区..." + +# 文件系统检查 +e2fsck -f -y ${EMMC_DEV}p2 + +# 先尝试收缩到最小值 +info_msg "计算文件系统最小大小..." +resize2fs -M ${EMMC_DEV}p2 + +# 获取收缩后的实际大小 +FS_SIZE_BLOCKS=$(dumpe2fs -h ${EMMC_DEV}p2 2>/dev/null | grep "^Block count:" | awk '{print $3}') +FS_SIZE_MB=$(( (FS_SIZE_BLOCKS * 4) / 1024 + 200 )) # 块大小4KB + 200MB缓冲 + +info_msg "文件系统最小大小: ${FS_SIZE_MB}MB" + +# 扩展一点给缓冲空间 +SHRINK_TARGET=$((FS_SIZE_MB + 300)) +resize2fs ${EMMC_DEV}p2 ${SHRINK_TARGET}M + +# 收缩分区 +P2_START=$(parted -s ${EMMC_DEV} unit B print | grep "^ 2" | awk '{print $2}' | sed 's/B$//') +NEW_P2_END=$((P2_START + SHRINK_TARGET * 1048576)) + +# 记录原始分区信息 +parted -s ${EMMC_DEV} unit B print > "${USB_DIR}/emmc_original_layout.txt" +ORIGINAL_P2_END=$(parted -s ${EMMC_DEV} unit B print | grep "^ 2" | awk '{print $3}' | sed 's/B$//') + +# 重新创建收缩的分区 +parted -s ${EMMC_DEV} rm 2 +parted -s ${EMMC_DEV} mkpart primary ext4 ${P2_START}B ${NEW_P2_END}B + +info_msg "✅ eMMC分区已收缩" + +# 步骤3: 备份收缩后的eMMC +info_msg "步骤3: 备份收缩后的eMMC..." +BACKUP_SIZE_MB=$(( (NEW_P2_END / 1048576) + 100 )) +dd if=${EMMC_DEV} of="${OUTPUT_FILE}" bs=1M count=${BACKUP_SIZE_MB} status=progress + +info_msg "✅ eMMC备份完成" + +# 步骤4: 恢复eMMC原始大小 +info_msg "步骤4: 恢复eMMC原始分区大小..." +parted -s ${EMMC_DEV} rm 2 +parted -s ${EMMC_DEV} mkpart primary ext4 ${P2_START}B ${ORIGINAL_P2_END}B +resize2fs ${EMMC_DEV}p2 + +info_msg "✅ eMMC已恢复原始大小" + +# 验证备份镜像 +info_msg "步骤5: 验证备份镜像..." +LOOP_DEV=$(losetup -P -f --show "${OUTPUT_FILE}") +sleep 3 + +if [[ -b "${LOOP_DEV}p1" ]] && [[ -b "${LOOP_DEV}p2" ]]; then + info_msg "✅ 备份镜像分区表完整" + parted -s "${LOOP_DEV}" print + + # 检查文件系统 + e2fsck -n "${LOOP_DEV}p1" && echo "✅ Boot分区文件系统正常" + e2fsck -n "${LOOP_DEV}p2" && echo "✅ Root分区文件系统正常" +else + warn_msg "❌ 备份镜像分区表有问题" +fi + +losetup -d "${LOOP_DEV}" + +FINAL_SIZE=$(du -h "${OUTPUT_FILE}" | cut -f1) +FINAL_SIZE_ACTUAL=$(du --apparent-size -h "${OUTPUT_FILE}" | cut -f1) + +info_msg "=========================================" +info_msg "🎉 eMMC备份成功完成!" +info_msg "=========================================" +info_msg "📁 备份文件: ${OUTPUT_FILE}" +info_msg "📏 实际大小: ${FINAL_SIZE}" +info_msg "📐 逻辑大小: ${FINAL_SIZE_ACTUAL}" +info_msg "💾 eMMC已恢复原状" +info_msg "" +info_msg "🚀 部署到新设备:" +info_msg " dd if=$(basename ${OUTPUT_FILE}) of=/dev/mmcblk0 bs=4M status=progress" +info_msg "" +info_msg "✅ 包含完整分区表和bootloader" +info_msg "✅ 保持所有原始配置不变" +info_msg "✅ 可在任意Rock5c上启动" +info_msg "=========================================" \ No newline at end of file