CodeDeploy未正确从GitHub复制代码导致部署失败问题排查
问题根因
和GitHub关联配置无关,是appspec.yml生命周期配置、路径配置两个核心错误导致的,具体如下:
- 第一,钩子执行阶段完全选错了。CodeDeploy的标准执行顺序是:拉取代码解压到临时目录 → 执行
BeforeInstall钩子(这一步仅做环境准备,不会把代码拷贝到你配置的destination目标路径) → 把文件从临时目录拷贝到目标路径 → 执行AfterInstall钩子 → 执行ApplicationStart等后续钩子。你把启动pm2的逻辑放在BeforeInstall里,这时候新代码还根本没落到/home/ubuntu路径下,看日志里pwd输出为/opt/codedeploy-agent就是实锤——这时候脚本的工作目录是CodeDeploy代理的运行目录,和你的项目路径没关系。 - 第二,文件拷贝路径配置和你的预期不符。你当前
files段配置source: /、destination: /home/ubuntu,意思是把解压后的仓库根目录下所有文件直接平铺拷贝到/home/ubuntu下,不会自动创建my-service这层父目录。你之前以为文件会落到/home/ubuntu/my-service,是数周前手动部署时自己建的这个目录,CodeDeploy不会主动给你套这层目录。 - 第三,CodeDeploy默认是增量覆盖部署,不会主动清理目标路径下的旧文件,也不会同步删除本次部署版本里不存在的历史文件,你之前手动部署的残留内容会和新部署的文件混放,进一步加剧路径混乱。
修复步骤
- 调整钩子的执行阶段
把服务启动相关的逻辑从BeforeInstall移到AfterInstall阶段,BeforeInstall只保留安装依赖、系统工具这类不需要依赖项目文件的操作。 - 修正文件拷贝路径
如果你的GitHub仓库拉取解压后,根目录就是my-service文件夹(和你贴的目录结构一致),files段配置source: /my-service、destination: /home/ubuntu即可,拷贝完成后会自动生成完整的/home/ubuntu/my-service目录结构,里面包含pm2.dev.json、src、scripts等所有文件。
如果你的仓库根目录直接是README.md、src、pm2.dev.json这些文件(没有外层my-service文件夹),就把destination改成/home/ubuntu/my-service,CodeDeploy会自动创建不存在的目标目录。 - 优化部署脚本逻辑
你已经配置了runas: root,脚本里不需要再加sudo,避免触发环境变量问题;启动pm2前先切换到项目目录,同时清理掉旧的同名进程,避免重复部署产生多个冗余进程。
参考配置示例
修正后的appspec.yml:
version: 0.0 os: linux files: - source: /my-service destination: /home/ubuntu hooks: BeforeInstall: # 这个阶段只装全局依赖,不需要等项目文件到位 - location: scripts/install_deps.sh timeout: 300 runas: root AfterInstall: # 等文件全部拷贝完成后,再启动服务 - location: scripts/start_service.sh timeout: 300 runas: root
scripts/install_deps.sh内容:
# 安装全局pm2,已经是root用户不需要sudo npm install pm2 -g # 可选:安装项目生产依赖 cd /home/ubuntu/my-service && npm install --production
scripts/start_service.sh内容:
cd /home/ubuntu/my-service # 先删除已存在的旧进程,避免重复启动 pm2 delete my-service 2>/dev/null || true pm2 start pm2.dev.json pm2 save
如果不想拆分脚本,也可以把整个脚本移到AfterInstall阶段执行,注意把工作目录切对即可。部署时可以先在AfterInstall阶段加一行ls -l /home/ubuntu/my-service打日志,确认所有文件都正确拷贝后再启动服务,方便排查路径问题。
内容的提问来源于stack exchange,提问作者hotmeatballsoup
相关产品推荐
相关产品推荐

