2. 源码下载与同步失败

领域定位:AOSP源码下载是整个编译流程的起点,repo sync失败会直接阻断工作流。本章围绕“现象识别→数据采集→原因定位→修复动作→复测→预防”展开,提供一套可复现的排查决策体系。

2.1 现象识别

repo sync失败通常表现为以下几种典型错误形式。将控制台输出的关键词与下方表格对照,可快速缩小问题范围。

错误关键词典型日志片段初步指向
RPC failed; curl 56
error: RPC failed; curl 56 OpenSSL SSL_read: Connection reset by peer, errno 104
fatal: early EOF
fatal: The remote end hung up unexpectedly
网络不稳 / 代理中断
fatal: unable to access
fatal: unable to access 'https://android.googlesource.com/platform/manifest':
Could not resolve host: android.googlesource.com
DNS解析失败 / 代理未配置
Downloading manifest... 卡死
Downloading manifest...
(长时间无输出,或重复重试)
代理配置错误 / 防火墙拦截
.git/index.lock
fatal: Unable to create '/path/to/repo/.git/index.lock': File exists.
Another git process seems to be running in this repository
残留锁文件 / 并发冲突
fetch-pack: unexpected disconnect
fetch-pack: unexpected disconnect while reading sideband packet
fatal: fetch-pack: invalid index-pack output
服务器限流 / 缓存损坏

经验规则:若错误信息中包含“curl”、“SSL”、“timeout”等网络层关键词,优先排查代理和网络连通性;若包含“index.lock”、“pack”、“unexpected”,优先清理缓存和锁文件。

2.2 数据采集

在进行修复前,必须系统化收集三组数据:

  1. 环境变量与配置:查看HTTP_PROXY、HTTPS_PROXY、NO_PROXY、GIT_SSL_NO_VERIFY是否设置,以及~/.gitconfig中的http.proxy。
  2. 网络诊断数据:记录ping android.googlesource.com的延迟、curl -v https://android.googlesource.com/git-repo的响应码与证书链。
  3. 日志与临时文件:收集.repo/project.list、.repo/manifests.git下的状态,以及repo sync退出码(0成功,非0失败)。

注意:误认为“超时只是偶发现象”而忽略采集,会反复陷入“重试→再失败”循环。建议每次失败后立即执行以下命令保存完整现场:

rm -f .repo/.sync_done   # 清除同步完成标记
echo "=== ENV ===" > /tmp/repo_fail_env.txt
env | grep -i proxy >> /tmp/repo_fail_env.txt
echo "=== GITCONFIG ===" >> /tmp/repo_fail_env.txt
cat ~/.gitconfig 2>/dev/null >> /tmp/repo_fail_env.txt
repo sync -v -j4 2>&1 | tee /tmp/repo_sync_fail.log

2.3 原因定位:故障树分析

使用下方故障树(SVG)进行系统性原因定位。根据树形结构,逐级检查叶子节点对应的确认命令。

repo sync失败故障树 repo sync 失败 网络连通问题 代理配置错误 缓存/锁文件 服务器端限制 DNS解析 SSL/TLS 代理地址错误 .git/index.lock 并发限流 ping / dig / nslookup curl -v 验证代理 rm .repo/**/index.lock 叶子节点对应 具体验证命令

2.4 修复动作

根据故障树定位到的节点,执行对应的修复方案。以下按优先级排序:

2.4.1 网络代理配置

若unable to access或Could not resolve host,执行:

  1. 确认代理地址:echo $http_proxy,常见格式为http://127.0.0.1:10809或socks5://127.0.0.1:1080。
  2. 统一设置环境变量:
export HTTP_PROXY=http://127.0.0.1:10809
export HTTPS_PROXY=http://127.0.0.1:10809
export NO_PROXY=localhost,127.0.0.1,.googlesource.com,.googleusercontent.com
  1. Git 特定代理配置:
git config --global http.proxy http://127.0.0.1:10809
git config --global https.proxy http://127.0.0.1:10809

注意:不要将.googlesource.com放入NO_PROXY,但可放localhost避免代理回环。若使用SOCKS5,Git需额外配置:

git config --global http.proxy socks5://127.0.0.1:1080

2.4.2 缓存清理与重试策略

当出现index.lock、fetch-pack: unexpected disconnect、early EOF时:

步骤命令说明
1
find .repo -name "index.lock" -delete
删除所有残留锁文件
2
repo sync -c --force-sync --no-tags -j4
强制同步,不拉取tag标签(减少数据传输)
3
repo sync -c --force-sync --no-tags -j1
如果上面仍失败,降为单线程,避免并发冲突
4
repo sync -c --force-sync --no-tags --prune -j2
配合--prune删除不存在的分支引用
5
rm -rf .repo/project-objects/* ; rm -rf .repo/projects/*
极端情况:清空项目缓存(慎用,会重新clone)

2.4.3 更换镜像源

国内用户建议使用中科大或清华AOSP镜像。修改.repo/manifests.git/config中的url或使用--mirror方式:

repo init -u https://mirrors.ustc.edu.cn/aosp/platform/manifest -b android-14.0.0_r15
# 或者清华镜像
repo init -u https://mirrors.tuna.tsinghua.edu.cn/aosp/platform/manifest -b android-14.0.0_r15

2.5 复测

修复后执行以下验证清单,确认同步彻底成功:

  1. 执行repo sync -c -j4 --no-tags 2>&1 | tail -20,观察最后的Syncing work tree: 100% (nnn/nnn)。
  2. 检查.repo/manifest.xml是否存在且可读。
  3. 随机挑选2~3个子项目执行git log --oneline -1,确认版本号与期望Tag一致。
  4. 运行cd .repo && du -sh确认总大小符合预期(AOSP约30~80GB)。

成功标志:repo sync退出码为0,且终端输出Sync done in xxx seconds。若仍失败,回到故障树再次定位。

2.6 预防

长期保持AOSP仓库健康,建议实施以下策略:

  • 固定Manifest版本:使用repo init -b <固定tag>,避免master分支频繁变化。
  • 周期性清理:每月执行一次repo sync -c --force-sync --no-tags --prune压缩存储。
  • 代理池轮换:若使用免费代理,配置多个代理地址,通过http.proxyOverride或环境变量切换。
  • 本地缓存服务器:搭建git daemon或Gerrit内部镜像,团队共享第一份repo sync结果。
  • 监控脚本:在CI/CD前加入repo sync --dry-run用于预检查网络可用性。

最佳实践:将以下脚本加入.bashrc,每次repo sync前自动执行环境验证:

function reposync_check() {
  echo "Checking proxy: $http_proxy"
  curl -s --connect-timeout 3 -o /dev/null -w "%{http_code}" https://android.googlesource.com || echo "WARN: Googlesource unreachable"
  find .repo -name "index.lock" -size 0 -delete &>/dev/null
  echo "Lock files cleaned"
}
alias reposync='reposync_check && repo sync -c --force-sync --no-tags -j4'