macos-migration
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesemacOS 系统迁移助手
macOS System Migration Assistant
两阶段设计:旧系统采集 → 新系统还原。中间通过一个 JSON 清单文件衔接。
A two-phase design: old-system collection → new-system restoration. The two phases are connected through a JSON manifest file.
前置要求(务必先做)
Prerequisites (Do This First)
在旧系统上先做一次 Time Machine 全量备份。 这是整个迁移的安全网——新系统上
任何一步出问题,都能从这份全量备份里捞回来。还原阶段也直接从 Time Machine 挂载点
读取数据。
没有 Time Machine 全量备份,就不要开始迁移。
Make a full Time Machine backup on the old system first. This is the migration's safety net—any problem on the new system can be recovered from this full backup. The restoration phase also reads data directly from the Time Machine mount point.
Do not begin the migration without a full Time Machine backup.
运行模式检测
Runtime Mode Detection
判断「采集还是还原」只看一个信号:清单文件在不在。
bash
ls ~/migration-manifest.json 2>/dev/null| 条件 | 模式 |
|---|---|
| 无清单文件 | 采集模式(在旧系统上,生成清单) |
| 有清单文件 | 还原模式(在新系统上,读清单还原) |
Time Machine 只是还原阶段的数据来源,不参与模式判断。
用户也可以直接指定:「采集」「备份」「还原」「迁移」。
Whether to collect or restore depends on only one signal: whether the manifest file exists.
bash
ls ~/migration-manifest.json 2>/dev/null| Condition | Mode |
|---|---|
| No manifest file | Collection mode (on the old system, generate a manifest) |
| Manifest file exists | Restoration mode (on the new system, read the manifest and restore) |
Time Machine is only the data source for the restoration phase and does not participate in mode detection.
The user can also explicitly specify: “Collect,” “Back Up,” “Restore,” or “Migrate.”
第零步:Homebrew 检查(两种模式都必须)
Step Zero: Homebrew Check (Required in Both Modes)
bash
which brew && brew --version || echo "NOT_INSTALLED"-
已安装 → 继续
-
未安装 → 引导用户在终端手动执行安装命令。这一步需要输入管理员密码(sudo), 无法静默完成:bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"装完后按提示把 brew 加入 PATH(Apple Silicon:), 再继续。eval "$(/opt/homebrew/bin/brew shellenv)"
bash
which brew && brew --version || echo "NOT_INSTALLED"-
Installed → Continue
-
Not installed → Guide the user to manually run the installation command in a terminal. This step requires an administrator password (sudo) and cannot be completed silently:bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"After installation, follow the instructions to add brew to PATH (Apple Silicon:), then continue.eval "$(/opt/homebrew/bin/brew shellenv)"
模式 A:旧系统采集
Mode A: Collection on the Old System
在旧系统上运行,扫描所有软件、配置、开发环境,生成 。
~/migration-manifest.jsonRun this on the old system to scan all software, configuration, and development environments and generate .
~/migration-manifest.jsonA1. Homebrew 软件包
A1. Homebrew Packages
bash
brew list --formula
brew list --cask
brew tapbash
brew list --formula
brew list --cask
brew tapA2. 系统 Applications
A2. System Applications
bash
ls /Applications/
ls ~/Applications/ 2>/dev/null与 Homebrew cask 列表对比,标记哪些是 Homebrew 装的、哪些是手动/App Store 装的。
bash
ls /Applications/
ls ~/Applications/ 2>/dev/nullCompare the results with the Homebrew cask list and mark which applications were installed through Homebrew and which were installed manually or from the App Store.
A3. Mac App Store 应用
A3. Mac App Store Applications
bash
mas list 2>/dev/null || echo "mas not installed"如果 未安装,提示用户是否要安装()。
masbrew install masbash
mas list 2>/dev/null || echo "mas not installed"If is not installed, ask the user whether to install it ().
masbrew install masA4. npm 全局包
A4. npm Global Packages
bash
npm ls -g --depth=0 2>/dev/nullbash
npm ls -g --depth=0 2>/dev/nullA5. uv 工具
A5. uv Tools
bash
uv tool list 2>/dev/nullbash
uv tool list 2>/dev/nullA6. pip/pipx 包
A6. pip/pipx Packages
bash
pip list 2>/dev/null
pipx list 2>/dev/nullbash
pip list 2>/dev/null
pipx list 2>/dev/nullA7. Go 全局工具
A7. Go Global Tools
bash
ls ~/go/bin/ 2>/dev/nullbash
ls ~/go/bin/ 2>/dev/nullA8. 配置文件扫描
A8. Configuration File Scan
扫描 home 目录下的 dotfiles 和配置目录:
bash
ls -la ~/重点采集:
- Shell:,
.zshrc,.zshenv,.zprofile,.bashrc.bash_profile - Git:,
.gitconfig.gitignore_global - SSH:
.ssh/ - 编辑器:,
.claude/,.codex/,.config/,.cursor/.zed/ - 容器:,
.docker/.kube/ - 包管理器:,
.npm/,.nvm/,.bun/,.cargo/.rustup/ - 其他应用配置:,
.SwitchHosts/,.ollama/等.syncthing/
敏感数据先问后采:(私钥)、dotfiles 里可能含 token、、、
钥匙串等都是密钥级信息。采集这些之前先问用户是否纳入:
.ssh/.aws/.kube/- 用户同意 → 正常采集,并明确提醒:「清单和备份里含私钥/凭据,传输、存放、 通过网盘或聊天工具发送时注意不要外泄。」
- 用户拒绝 → 跳过这些项,在清单里记入 ,让用户日后 自行手动迁移(差异报告里也会再列一次)。
"skipped_sensitive": [...]
Scan dotfiles and configuration directories under the home directory:
bash
ls -la ~/Focus on collecting:
- Shell: ,
.zshrc,.zshenv,.zprofile,.bashrc.bash_profile - Git: ,
.gitconfig.gitignore_global - SSH:
.ssh/ - Editors: ,
.claude/,.codex/,.config/,.cursor/.zed/ - Containers: ,
.docker/.kube/ - Package managers: ,
.npm/,.nvm/,.bun/,.cargo/.rustup/ - Other application configurations: ,
.SwitchHosts/,.ollama/, etc..syncthing/
Ask before collecting sensitive data: (private keys), tokens that may exist in dotfiles, , , keychains, and similar key-level information are highly sensitive. Before collecting these items, ask the user whether they should be included:
.ssh/.aws/.kube/- User agrees → Collect them normally and explicitly warn the user: “The manifest and backup contain private keys and credentials. When transferring, storing, or sending them through cloud storage or chat tools, take care not to disclose them.”
- User declines → Skip these items and record them in the manifest as so the user can migrate them manually later. They will also be listed again in the discrepancy report.
"skipped_sensitive": [...]
A9. LaunchAgents(自启动服务)
A9. LaunchAgents (Startup Services)
bash
ls ~/Library/LaunchAgents/bash
ls ~/Library/LaunchAgents/A10. 用户项目目录
A10. User Project Directories
列出 home 目录下非 dotfile 的顶层目录:
bash
ls -d ~/*/ 2>/dev/null排除系统目录(Library, Applications, Public 等),记录用户自建的项目/数据目录。
List non-dotfile top-level directories under the home directory:
bash
ls -d ~/*/ 2>/dev/nullExclude system directories such as Library, Applications, and Public, and record user-created project and data directories.
A11. Shell 环境
A11. Shell Environment
bash
undefinedbash
undefined当前 shell 版本
当前 shell 版本
zsh --version
zsh --version
Homebrew 路径 / 版本管理器(nvm、fnm 等)配置
Homebrew 路径 / 版本管理器(nvm、fnm 等)配置
grep -iE 'brew|nvm|fnm' ~/.zshrc
undefinedgrep -iE 'brew|nvm|fnm' ~/.zshrc
undefinedA12. 其他易漏项
A12. Other Easily Missed Items
迁移时最容易漏、丢了又很烦的几类:
bash
undefinedThese categories are most commonly missed during migration and can be particularly troublesome to recover:
bash
undefined编辑器扩展
编辑器扩展
code --list-extensions 2>/dev/null
cursor --list-extensions 2>/dev/null
code --list-extensions 2>/dev/null
cursor --list-extensions 2>/dev/null
自购/自装字体
自购/自装字体
ls ~/Library/Fonts/ 2>/dev/null
ls ~/Library/Fonts/ 2>/dev/null
定时任务
定时任务
crontab -l 2>/dev/null
crontab -l 2>/dev/null
手动装到非 Homebrew 路径的命令行工具
手动装到非 Homebrew 路径的命令行工具
ls /usr/local/bin/ 2>/dev/null
ls /opt/ 2>/dev/null
> 系统偏好(`defaults`)量大且与机型强相关,不自动采集;如用户在意,在还原差异
> 报告里提醒手动核对(键盘、触控板、Dock、快捷键等)。ls /usr/local/bin/ 2>/dev/null
ls /opt/ 2>/dev/null
> System preferences (`defaults`) are extensive and highly dependent on the machine model, so they are not collected automatically. If the user cares about them, remind the user in the restoration discrepancy report to verify them manually, including the keyboard, trackpad, Dock, shortcuts, and other settings.A13. 生成清单文件
A13. Generate the Manifest File
将以上所有信息写入 :
~/migration-manifest.jsonjson
{
"version": 1,
"captured_at": "2026-06-28T16:00:00+08:00",
"source_macos": "15.5",
"source_hostname": "old-macbook",
"homebrew": {
"taps": ["user/repo", "..."],
"formulas": ["git", "node@22", "..."],
"casks": ["1password", "docker-desktop", "..."]
},
"applications": {
"homebrew_casks": ["claude", "firefox", "..."],
"app_store": [{"id": 123456, "name": "App Name"}],
"manual": ["Final Cut Pro.app", "..."]
},
"package_managers": {
"npm_global": ["@anthropic-ai/claude-code", "..."],
"uv_tools": ["nano-pdf", "..."],
"pip_packages": ["package1", "..."],
"go_binaries": ["tool1", "..."]
},
"configs": {
"dotfiles": [".zshrc", ".gitconfig", ".ssh", "..."],
"config_dirs": [".claude", ".codex", ".config", ".docker", "..."],
"app_support_keys": ["Syncthing", "obs-studio", "..."]
},
"editor_extensions": {
"vscode": ["ms-python.python", "..."],
"cursor": ["..."]
},
"fonts": ["MyFont.otf", "..."],
"crontab": "<crontab -l 原文,无则空>",
"manual_bins": ["/usr/local/bin/foo", "/opt/bar", "..."],
"launch_agents": ["com.github.syncthing.plist", "..."],
"user_dirs": ["Projects", "Sites", "..."],
"shell": {
"shell": "zsh",
"brew_in_path": true,
"nvm_installed": true,
"custom_env_vars": {}
},
"skipped_sensitive": []
}Write all the information above into :
~/migration-manifest.jsonjson
{
"version": 1,
"captured_at": "2026-06-28T16:00:00+08:00",
"source_macos": "15.5",
"source_hostname": "old-macbook",
"homebrew": {
"taps": ["user/repo", "..."],
"formulas": ["git", "node@22", "..."],
"casks": ["1password", "docker-desktop", "..."]
},
"applications": {
"homebrew_casks": ["claude", "firefox", "..."],
"app_store": [{"id": 123456, "name": "App Name"}],
"manual": ["Final Cut Pro.app", "..."]
},
"package_managers": {
"npm_global": ["@anthropic-ai/claude-code", "..."],
"uv_tools": ["nano-pdf", "..."],
"pip_packages": ["package1", "..."],
"go_binaries": ["tool1", "..."]
},
"configs": {
"dotfiles": [".zshrc", ".gitconfig", ".ssh", "..."],
"config_dirs": [".claude", ".codex", ".config", ".docker", "..."],
"app_support_keys": ["Syncthing", "obs-studio", "..."]
},
"editor_extensions": {
"vscode": ["ms-python.python", "..."],
"cursor": ["..."]
},
"fonts": ["MyFont.otf", "..."],
"crontab": "<crontab -l 原文,无则空>",
"manual_bins": ["/usr/local/bin/foo", "/opt/bar", "..."],
"launch_agents": ["com.github.syncthing.plist", "..."],
"user_dirs": ["Projects", "Sites", "..."],
"shell": {
"shell": "zsh",
"brew_in_path": true,
"nvm_installed": true,
"custom_env_vars": {}
},
"skipped_sensitive": []
}A14. 采集完成
A14. Collection Complete
输出清单摘要,提示用户:
✅ 采集完成!清单已保存到 ~/migration-manifest.json
采集内容:
- Homebrew: X taps, Y formulas, Z casks
- 应用: X 个 Homebrew, Y 个 App Store, Z 个手动安装
- npm 全局包: X 个
- 配置文件: X 个 dotfiles, Y 个配置目录
- 编辑器扩展: X 个 / 字体: Y 个 / 定时任务: 有/无
- 自启动服务: X 个
- 用户目录: X 个
- 跳过的敏感项: X 个(用户选择不采集)
⚠️ 若采集了 .ssh / dotfiles 中的凭据,清单与备份含私钥,传输存放注意不要外泄。
下一步:确认已有 Time Machine 全量备份,将 migration-manifest.json 复制到新系统,
再次运行此 skill。Output a manifest summary and prompt the user:
✅ 采集完成!清单已保存到 ~/migration-manifest.json
采集内容:
- Homebrew: X taps, Y formulas, Z casks
- 应用: X 个 Homebrew, Y 个 App Store, Z 个手动安装
- npm 全局包: X 个
- 配置文件: X 个 dotfiles, Y 个配置目录
- 编辑器扩展: X 个 / 字体: Y 个 / 定时任务: 有/无
- 自启动服务: X 个
- 用户目录: X 个
- 跳过的敏感项: X 个(用户选择不采集)
⚠️ 若采集了 .ssh / dotfiles 中的凭据,清单与备份含私钥,传输存放注意不要外泄。
下一步:确认已有 Time Machine 全量备份,将 migration-manifest.json 复制到新系统,
再次运行此 skill。模式 B:新系统还原
Mode B: Restoration on the New System
在新系统上运行,读取 并逐步还原。
migration-manifest.jsonRun this on the new system to read and restore the system step by step.
migration-manifest.jsonB0. 获取清单
B0. Obtain the Manifest
bash
ls ~/migration-manifest.json如果不存在:
找不到 migration-manifest.json。
请将旧系统上采集的清单文件复制到新系统的 home 目录:
scp old-mac:~/migration-manifest.json ~/migration-manifest.json
或者手动指定路径。bash
ls ~/migration-manifest.jsonIf it does not exist:
找不到 migration-manifest.json。
请将旧系统上采集的清单文件复制到新系统的 home 目录:
scp old-mac:~/migration-manifest.json ~/migration-manifest.json
或者手动指定路径。B1. Homebrew 软件安装
B1. Homebrew Software Installation
前提:第零步已确认 Homebrew 装好(需用户手动输密码安装)。装好之后这一步才能跑。
读取清单中的 字段。
homebrewbash
undefinedPrerequisite: Homebrew has been confirmed as installed in Step Zero. The user must manually enter the password to install it. This step can run only after Homebrew is ready.
Read the field from the manifest.
homebrewbash
undefined添加 taps(逐个)
添加 taps(逐个)
brew tap <user>/<repo>
brew tap <user>/<repo>
信任第三方 taps
信任第三方 taps
brew trust <user>/<repo>
brew trust <user>/<repo>
安装 formulas(批量,失败不回滚整批)
安装 formulas(批量,失败不回滚整批)
brew install <formula1> <formula2> ...
brew install <formula1> <formula2> ...
安装 casks(逐个,避免回滚)
安装 casks(逐个,避免回滚)
for cask in <cask1> <cask2> ...; do
brew install --cask "$cask" 2>&1 | tail -3
done
没装上的(需 sudo、网络失败等)先记下,最后在 B7 差异报告统一列给用户。for cask in <cask1> <cask2> ...; do
brew install --cask "$cask" 2>&1 | tail -3
done
Record anything that could not be installed, such as packages requiring sudo or those that failed due to network issues, and present it to the user in the discrepancy report in B7.B2. 其他包管理器
B2. Other Package Managers
读取清单中的 字段。
package_managersbash
undefinedRead the field from the manifest.
package_managersbash
undefinednpm
npm
npm install -g <pkg1> <pkg2> ...
npm install -g <pkg1> <pkg2> ...
uv
uv
uv tool install <pkg1> <pkg2> ...
uv tool install <pkg1> <pkg2> ...
pip(如果需要)
pip(如果需要)
pip install <pkg1> <pkg2> ...
pip install <pkg1> <pkg2> ...
go binaries
go binaries
go install <pkg1>@latest <pkg2>@latest ...
undefinedgo install <pkg1>@latest <pkg2>@latest ...
undefinedB3. 配置文件恢复
B3. Configuration File Restoration
读取清单中的 字段。
configs有两种数据来源,优先级:
- Time Machine 直接复制(如果有挂载)
- 用户手动提供(如果清单是从别的方式获取的)
bash
TM="<Time Machine 用户目录路径>"
LOCAL="/Users/<username>"Read the field from the manifest.
configsThere are two possible data sources, in priority order:
- Copy directly from Time Machine if it is mounted
- Provided manually by the user if the manifest was obtained through another method
bash
TM="<Time Machine 用户目录路径>"
LOCAL="/Users/<username>"dotfiles
dotfiles
rsync -av --ignore-existing "$TM/.zshrc" "$LOCAL/"
rsync -av --ignore-existing "$TM/.gitconfig" "$LOCAL/"
rsync -av --ignore-existing "$TM/.ssh/" "$LOCAL/.ssh/"
rsync -av --ignore-existing "$TM/.zshrc" "$LOCAL/"
rsync -av --ignore-existing "$TM/.gitconfig" "$LOCAL/"
rsync -av --ignore-existing "$TM/.ssh/" "$LOCAL/.ssh/"
配置目录
配置目录
for dir in .claude .codex .config .docker .SwitchHosts ...; do
rsync -av --ignore-existing "$TM/$dir/" "$LOCAL/$dir/"
done
> 恢复 `.ssh/` 后确认权限:`chmod 700 ~/.ssh && chmod 600 ~/.ssh/id_*`。
> 如无 Time Machine,提示用户提供配置文件的来源路径。for dir in .claude .codex .config .docker .SwitchHosts ...; do
rsync -av --ignore-existing "$TM/$dir/" "$LOCAL/$dir/"
done
> After restoring `.ssh/`, verify the permissions: `chmod 700 ~/.ssh && chmod 600 ~/.ssh/id_*`.
> If Time Machine is unavailable, ask the user to provide the source path for the configuration files.B4. Library 关键子目录
B4. Key Library Subdirectories
从 Time Machine 恢复(如果有):
| 子目录 | 命令 | 说明 |
|---|---|---|
| Preferences | | 应用偏好设置 |
| Keychains | | 钥匙串 |
| Containers | | 沙盒应用数据 |
| Group Containers | | 共享容器 |
| 邮件数据 | |
| Safari | | 书签/历史 |
rsync 在 Time Machine APFS 快照上会报错误,Library 用io_read_flush。cp -rn
Restore these from Time Machine if available:
| Subdirectory | Command | Description |
|---|---|---|
| Preferences | | Application preferences |
| Keychains | | Keychains |
| Containers | | Sandboxed application data |
| Group Containers | | Shared containers |
| Mail data | |
| Safari | | Bookmarks/history |
reportsrsyncerrors on Time Machine APFS snapshots. Useio_read_flushfor Library subdirectories.cp -rn
B5. LaunchAgents(自启动服务)
B5. LaunchAgents (Startup Services)
读取清单中的 字段。
launch_agents逐个检查并创建对应的 plist 文件,然后 。
launchctl loadRead the field from the manifest.
launch_agentsCheck and create the corresponding plist files one by one, and then run .
launchctl loadB6. 其他易漏项还原
B6. Restoration of Other Easily Missed Items
对应采集阶段的 A12:
bash
undefinedThese correspond to A12 in the collection phase:
bash
undefined编辑器扩展(逐个装)
编辑器扩展(逐个装)
for ext in <清单 editor_extensions.vscode>; do code --install-extension "$ext"; done
for ext in <清单 editor_extensions.vscode>; do code --install-extension "$ext"; done
字体
字体
rsync -av --ignore-existing "$TM/Library/Fonts/" "$LOCAL/Library/Fonts/"
rsync -av --ignore-existing "$TM/Library/Fonts/" "$LOCAL/Library/Fonts/"
定时任务:先看新机器有没有现成的,再决定是否合并写入,避免覆盖
定时任务:先看新机器有没有现成的,再决定是否合并写入,避免覆盖
crontab -l 2>/dev/null
> `/usr/local/bin`、`/opt` 里的手动安装工具无法自动还原,列入 B7 差异报告提醒用户。crontab -l 2>/dev/null
> Manually installed tools in `/usr/local/bin` and `/opt` cannot be restored automatically. List them in the discrepancy report in B7 and remind the user about them.B7. 未安装项目处理
B7. Handling Items That Could Not Be Installed
对比清单和实际安装结果,输出差异:
undefinedCompare the manifest with the actual installation results and output the differences:
undefined还原差异报告
还原差异报告
❌ 安装失败(需手动处理)
❌ 安装失败(需手动处理)
- docker-desktop: 需要 sudo → 手动执行
brew install --cask docker-desktop - tailscale-app: 需要 sudo → 手动执行
brew install --cask tailscale-app - android-platform-tools: 网络问题 → 稍后重试
- docker-desktop: 需要 sudo → 手动执行
brew install --cask docker-desktop - tailscale-app: 需要 sudo → 手动执行
brew install --cask tailscale-app - android-platform-tools: 网络问题 → 稍后重试
⚠️ 清单中有但无 Homebrew cask
⚠️ 清单中有但无 Homebrew cask
- Final Cut Pro: App Store 应用
- DaVinci Resolve Studio: 手动下载 → blackmagicdesign.com
- Final Cut Pro: App Store 应用
- DaVinci Resolve Studio: 手动下载 → blackmagicdesign.com
ℹ️ App Store 应用(需手动安装或用 mas)
ℹ️ App Store 应用(需手动安装或用 mas)
- GarageBand
- Infuse
- GarageBand
- Infuse
🔧 需手动核对(非软件)
🔧 需手动核对(非软件)
- 系统偏好 defaults:键盘 / 触控板 / Dock / 快捷键
- /usr/local/bin、/opt 手动工具:<manual_bins 列表>
- 拒绝采集的敏感项:<skipped_sensitive 列表>
---- 系统偏好 defaults:键盘 / 触控板 / Dock / 快捷键
- /usr/local/bin、/opt 手动工具:<manual_bins 列表>
- 拒绝采集的敏感项:<skipped_sensitive 列表>
---踩坑记录
Troubleshooting Notes
1. brew bundle
一个失败全部回滚
brew bundle1. brew bundle
Rolls Back the Entire Batch When One Item Fails
brew bundle问题: 中任何一个 cask 下载失败,整批已安装的包全部回滚。
brew bundle --file=Brewfile解决:不用 。taps 逐个添加,formulas 批量安装,casks 逐个安装。
brew bundleProblem: If any cask download fails in , the entire batch of installed packages is rolled back.
brew bundle --file=BrewfileSolution: Do not use . Add taps one by one, install formulas in a batch, and install casks one at a time.
brew bundle2. 第三方 taps 未信任
2. Third-Party Taps Are Not Trusted
问题:Homebrew 6+ 要求显式信任第三方 taps,否则报 。
Refusing to load cask from untrusted tap解决:
brew trust <user>/<repo>Problem: Homebrew 6+ requires third-party taps to be explicitly trusted; otherwise, it reports .
Refusing to load cask from untrusted tapSolution:
brew trust <user>/<repo>3. rsync 在 Time Machine APFS 快照上报错
3. rsync
Reports an Error on Time Machine APFS Snapshots
rsync问题: 复制 Library 子目录时报 错误。
rsync -av --ignore-existingio_read_flush解决:Library 子目录改用 。
cp -rnProblem: reports an error when copying Library subdirectories.
rsync -av --ignore-existingio_read_flushSolution: Use for Library subdirectories.
cp -rn4. cp -rn
的 "Operation not permitted"
cp -rn4. cp -rn
Reports "Operation not permitted"
cp -rn问题:macOS SIP/TCC 保护的文件无法直接复制(系统 Preferences、Mail 数据库等)。
影响:不影响使用。系统或应用在首次启动时自动重建。
Problem: Files protected by macOS SIP/TCC cannot be copied directly, including system Preferences and Mail databases.
Impact: This does not affect usage. The system or applications rebuild these files automatically on first launch.
5. cp -rn
的 "Not a directory" 错误
cp -rn5. cp -rn
Reports "Not a directory"
cp -rn问题:Containers 中系统容器使用符号链接指向标准目录。
影响:不影响使用。用户应用的容器数据已正确复制。
Problem: Some system containers in Containers use symbolic links that point to standard directories.
Impact: This does not affect usage. User application container data has been copied correctly.
6. 需要 sudo 的 casks
6. Casks That Require sudo
问题:、、 安装时需要 sudo。
docker-desktoptailscale-appadobe-creative-cloud解决:记录在差异报告中,让用户手动执行。
Problem: Packages such as , , and require sudo during installation.
docker-desktoptailscale-appadobe-creative-cloudSolution: Record them in the discrepancy report and have the user run the commands manually.
7. node 版本冲突
7. node Version Conflict
问题: 后 失败。
brew install node@22brew link解决:
brew link --overwrite node@22Problem: fails after running .
brew linkbrew install node@22Solution:
brew link --overwrite node@228. Homebrew 检测不到非 Homebrew 安装的软件
8. Homebrew Cannot Detect Software Not Installed Through Homebrew
问题:旧系统上通过 DMG/PKG/App Store 安装的软件,Homebrew 无法感知。
解决:采集阶段扫描 并与 对比,标记出手动安装的应用,还原时单独处理。
/Applications/brew list --caskProblem: Software installed on the old system through DMG, PKG, or the App Store is invisible to Homebrew.
Solution: During collection, scan and compare it with , mark manually installed applications, and handle them separately during restoration.
/Applications/brew list --cask原则
Principles
- 先有 Time Machine 全量备份再开始:这是出错时唯一的兜底,也是还原的数据来源
- Homebrew 由用户手动安装:需要输密码(sudo),引导用户在终端执行,装好再继续
- 两阶段分离:采集和还原是独立的步骤,通过 JSON 文件衔接
- 敏感数据先问后采:私钥/凭据采不采由用户决定;采了就提醒外泄风险
- 绝不覆盖已有文件:所有 rsync/cp 都带 或
--ignore-existing-n - 先小后大:按目录大小排序复制,方便快速验证
- 先做计划再动手:还原前输出清单摘要,让用户确认
- 记录差异:还原后输出差异报告,列出需要手动处理的项目
- 逐个安装 casks:避免 的回滚问题
brew bundle - 验证每一步:安装后 确认,复制后
brew list验证大小du -sh - 跳过缓存:Library/Application Support 中的缓存数据不恢复
- Make a full Time Machine backup before starting: It is the only fallback in case of failure and the data source for restoration
- Have the user install Homebrew manually: It requires a password through sudo, so guide the user to run the command in a terminal and continue only after installation is complete
- Separate the two phases: Collection and restoration are independent steps connected through a JSON file
- Ask before collecting sensitive data: The user decides whether private keys and credentials should be collected; if they are collected, warn the user about the risk of disclosure
- Never overwrite existing files: Every rsync and cp operation includes or
--ignore-existing-n - Start small and work up: Copy directories in ascending order of size to make validation easier
- Make a plan before taking action: Before restoration, output a manifest summary and ask the user for confirmation
- Record discrepancies: After restoration, output a discrepancy report listing items that require manual handling
- Install casks one by one: Avoid the rollback problem caused by
brew bundle - Verify every step: Confirm installations with and verify copied sizes with
brew listdu -sh - Skip caches: Do not restore cache data under Library/Application Support