使用自定义Docker镜像时GitLab CI/CD流水线报'do'语法错误
问题描述
使用包含Terraform、Terragrunt和AWS CLI的自定义Docker镜像运行GitLab CI/CD流水线时,第一阶段失败,报错如下:
Executing "step_script" stage of the job script 00:01 Using docker image sha256:e1589e57615ab7e4c9ffe424070fef53c53c17a040de2c5ee858fff319753f2a for registry.gitlab.com/image-path:terragrunt-latest with digest registry.gitlab.com/image-path@sha256:0d5c661e1dce3f543af65966daa947a9e3878316b95464cbb3c3187d19e01d40 ... sh: 7: Syntax error: "do" unexpected Cleaning up project directory and file based variables 00:01 ERROR: Job failed: exit code 2
已完成操作
- 基于Ubuntu 22.04构建自定义镜像,安装Terraform、Terragrunt、AWS CLI等工具后推送至GitLab容器仓库:
docker build -t registry.gitlab.com/my-project/my-repo:latest . docker push registry.gitlab.com/my-project/my-repo:latest - 在
.gitlab-ci.yml中配置使用该自定义镜像。
额外信息
GitLab Runner版本为17.7.0~pre.103.g896916a8,执行器为docker+machine,基础镜像为Ubuntu 22.04。
问题
导致该语法错误的原因是什么?GitLab CI运行入口脚本是否存在问题?该如何进一步调试?
解答
错误原因分析
sh: 7: Syntax error: "do" unexpected这类报错核心是shell环境不兼容或脚本语法不符合规范,常见场景包括:
- 默认shell为Dash而非Bash:Ubuntu 22.04中
sh默认指向轻量级shell Dash,它不支持部分Bash专属语法(比如无分隔符的多行循环写法、扩展变量等)。如果流水线脚本依赖Bash特性,用Dash执行就会触发语法错误。 - 脚本语法不规范:流水线脚本第7行的循环写法不符合POSIX Shell标准,比如
for循环后未加;就直接换行写do,例如:# Dash不支持的错误写法 for item in $(ls) do echo $item done # 兼容POSIX的正确写法 for item in $(ls); do echo $item done - Docker镜像未配置默认Bash:如果自定义镜像未通过
SHELL指令指定默认shell为Bash,GitLab Runner会默认用sh执行脚本,触发兼容性问题。
GitLab CI入口脚本是否有问题?
大概率不是GitLab CI入口脚本的问题,而是你的流水线脚本或镜像shell配置的问题。GitLab CI的入口脚本兼容标准POSIX语法,仅当脚本依赖Bash特性但未指定shell时才会出错。
调试与解决步骤
- 定位报错脚本行:在GitLab流水线日志中展开
step_script的完整内容,找到第7行的具体命令,确认是否存在语法问题。 - 本地镜像测试:拉取自定义镜像,本地模拟CI环境执行脚本,复现错误:
docker run -it registry.gitlab.com/my-project/my-repo:latest sh # 粘贴流水线第7行及后续脚本,观察是否触发相同报错 - 显式指定Bash执行:在
.gitlab-ci.yml的job中强制使用Bash:
或者直接用Bash包裹单条脚本:your_job_name: image: registry.gitlab.com/my-project/my-repo:latest variables: SHELL: "/bin/bash" script: - # 你的流水线脚本内容script: - bash -c "your-script-with-bash-syntax" - 修改Dockerfile配置默认shell:在Dockerfile中添加指令,确保镜像默认使用Bash:
SHELL ["/bin/bash", "-c"] - 修正脚本语法:如果是脚本本身的语法问题,将循环等语句调整为POSIX兼容格式,比如在
for和do之间添加;分隔符。
内容的提问来源于stack exchange,提问作者Sidhartha
相关产品推荐
相关产品推荐

