Loading... # DMG 文件直接写入硬盘导致无法启动的问题分析与解决 # 一、事件概述 ## 1. 事件背景 在 Linux 系统中将 macOS 12.7.6 安装文件(DMG 格式)写入 NVMe 硬盘,制作可启动的 macOS 安装盘。 ## 2. 影响范围 ### A. 影响操作 启动盘制作流程被迫中断,需要重新制作 ### B. 影响时长 问题发现耗时约 30 分钟,包括问题定位和重新制作 ### C. 影响功能 初次制作的启动盘无法被 Mac 识别 ## 3. 严重程度 P2 级问题(非生产环境,但浪费时间和精力) # 二、事件时间线 ## 1. 问题发生(时间:初次写入完成后) ### A. 现象描述 使用 dd 命令直接将 InstallOS.dmg 写入 /dev/sdb,写入过程显示成功,耗时约 170 秒,写入约 5GB 数据。 ### B. 初始验证 使用 file 命令检查硬盘开头,返回 zlib compressed data,而非预期的分区表格式。 ## 2. 问题发现(时间:写入验证阶段) ### A. 发现途径 在重启前验证启动盘制作结果时,使用 file 和 hexdump 命令检查硬盘内容。 ### B. 初步判断 硬盘开头为 78 DA(zlib 压缩数据魔数),而非正确的 GPT 引导扇区(00 EE)。说明 DMG 文件的压缩数据被直接写入了硬盘。 ## 3. 根因分析(时间:问题发现后) ### A. 根本原因 DMG 是 Apple 的磁盘镜像格式,内部使用 zlib 压缩。直接用 dd 写入只会把压缩数据复制到硬盘,Mac 无法识别正确的分区结构。 ### B. 正确做法 必须先使用 dmg2img 工具将 DMG 转换为原始镜像(IMG 格式),再写入设备。 ## 4. 解决方案实施(时间:根因确认后) ### A. 转换 DMG 为 IMG ```bash dmg2img /home/lab/Downloads/InstallOS.dmg /home/lab/Downloads/InstallOS.img ``` 转换过程耗时约 2 分钟,文件从 4.7GB 扩展到 5.3GB。 ### B. 重新写入硬盘 ```bash sudo dd if=/home/lab/Downloads/InstallOS.img of=/dev/sdb bs=4M oflag=direct status=progress ``` 写入耗时约 125 秒,平均速度 44.7 MB/s。 ## 5. 验证结果(时间:重新写入后) ### A. 分区表验证 GPT 分区表正确写入,包含: - 分区 1:EFI System Partition(200MB vfat) - 分区 2:Install macOS(4.9GB HFS+) ### B. 文件系统验证 挂载 HFS+ 分区后,确认 InstallOS.pkg 文件存在(约 5GB)。 ### C. 最终结果 启动盘制作成功,可在 Mac 上使用 Option 键选择启动。 ```mermaid graph LR A[DMG 文件] -->|错误方式: 直接 dd| B[压缩数据写入硬盘] B --> C[Mac 无法识别] A -->|正确方式: dmg2img| D[IMG 镜像] D -->|dd 写入| E[正确分区结构] E --> F[Mac 可识别] ```  # 三、问题分析 ## 1. 直接原因 dd 命令按字节复制文件内容,不会处理 DMG 内部的压缩结构。直接写入 DMG 文件相当于把压缩数据块写入硬盘。 ## 2. 根本原因(技术分析) ### A. DMG 文件结构 DMG(Disk Image)是 Apple 的磁盘镜像格式,具有以下特点: - 支持 zlib 压缩(默认) - 支持 AES 加密 - 支持多种分区格式(GPT、APM 等) - 包含文件系统和元数据 ### B. 压缩数据特征 DMG 文件开头的 78 DA 是 zlib 压缩的标准魔数,表示数据已压缩。 ```hexdump 00000000 78 da 63 60 18 05 43 18 fc fb ff ff 1d 10 33 02 |x.c`..C.......3. ``` ### C. GPT 分区表特征 正确的 GPT 硬盘开头应该是保护性 MBR: ```hexdump 000001c0 ff ff ee fe ff ff 01 00 00 00 f7 52 a7 00 00 00 |................| ``` ## 3. 深层反思 ### A. 文档缺陷 网络上关于 DMG 写入的教程多数存在误导,未说明 DMG 需要先转换。 ### B. 工具认知 dmg2img 工具在 Linux 生态中不够普及,容易被忽略。 ### C. 验证重要性 在重启前验证是非常必要的步骤,避免了使用无效启动盘的麻烦。 # 四、解决方案 ## 1. 临时方案(不推荐) 如果已经错误写入,需要重新制作: 1. 使用 dd 填充零清空硬盘:`dd if=/dev/zero of=/dev/sdb bs=1M count=100` 2. 重新执行正确的制作流程 ## 2. 正确方案(推荐) ### A. 完整制作流程 ```bash # 1. 转换 DMG 为 IMG dmg2img InstallOS.dmg InstallOS.img # 2. 写入硬盘 sudo dd if=InstallOS.img of=/dev/sdb bs=4M oflag=direct status=progress # 3. 同步缓冲区 sync # 4. 验证分区表 sudo fdisk -l /dev/sdb # 5. 验证文件系统(可选) sudo blkid /dev/sdb* ``` ### B. 实施计划 1. 确保 dmg2img 工具已安装:`sudo apt install dmg2img` 2. 确认目标设备路径正确 3. 预留足够时间(转换 + 写入约 5 分钟) ## 3. 预防措施 ### A. 文档更新 更新技术文档,明确说明 DMG 需要先转换。 ### B. 工具集成 考虑将 dmg2img 作为制作 macOS 启动盘的标准工具。 ### C. 验证脚本 编写自动化验证脚本,在写入后自动检查分区表格式。 # 五、经验总结 ## 1. 做得好的地方 - 在重启前进行了验证,避免浪费更多时间 - 使用 file 和 hexdump 快速定位问题 - 找到了正确的解决方案(dmg2img) ## 2. 需要改进的地方 - 事先未了解 DMG 文件格式的特殊性 - 未查阅官方文档或可靠资料 ## 3. 流程优化建议 ### A. 制作前检查 - 使用 dmg2img -l 查看 DMG 分区信息 - 确认 DMG 文件完整性 ### B. 验证步骤 1. 检查硬盘开头:`sudo file -s /dev/sdX` 2. 检查分区表:`sudo fdisk -l /dev/sdX` 3. 检查分区类型:`sudo blkid /dev/sdX*` ### C. 自动化脚本 ```bash #!/bin/bash # macOS 启动盘制作与验证脚本 DMG_FILE="$1" TARGET_DEVICE="$2" # 转换 DMG dmg2img "$DMG_FILE" "${DMG_FILE%.dmg}.img" # 写入硬盘 sudo dd if="${DMG_FILE%.dmg}.img" of="$TARGET_DEVICE" bs=4M oflag=direct status=progress # 验证 sudo fdisk -l "$TARGET_DEVICE" sudo blkid "${TARGET_DEVICE}*" ``` # 六、技术细节 ## 1. DMG 文件格式详解 ### A. 结构组成 DMG 文件由以下部分组成: - Koly块:尾部元数据区域 - 资源分叉:HFS+ 或 APFS 文件系统 - 压缩块:zlib 或 ADC 压缩的数据 - 检查表:校验和完整性信息 ### B. dmg2img 工作原理 dmg2img 解析 DMG 文件结构: 1. 读取尾部 Koly 块获取分区信息 2. 逐分区解压数据块 3. 还原为原始镜像格式(IMG) ## 2. 写入参数优化 ### A. 块大小选择 - bs=4M:平衡速度和内存占用 - bs=8M 或 16M:可能更快,但占用更多内存 ### B. 直接写入模式 - oflag=direct:绕过系统缓存,直接写入设备 - 好处:避免占用大量内存,写入更可靠 ## 3. 兼容性说明 ### A. macOS 版本 此方法适用于 macOS 10.12(Sierra)及以后的 DMG 格式。 ### B. 硬件要求 - NVMe 硬盘通过 USB 硬盘盒或内置接口连接 - 硬盘容量应大于 DMG 解压后的镜像大小 *** ## 参考资料 1. [dmg2img 官方文档](https://vu1tur.com/utilz/page.php?id=5) 2. [Apple DMG 格式规范](https://developer.apple.com/library/archive/documentation/Darwin/Conceptual/diskimagery/ 最后修改:2026 年 04 月 02 日 © 允许规范转载 赞 如果觉得我的文章对你有用,请随意赞赏