GitLab执行CI脚本时报了这样的错误:
bash
Running with gitlab-runner 19.3.1 (a27f5034)
on Test-Machine abc123xyz, system ID: s_xxxxxxxxxxxx
Resolving secrets
Preparing the "shell" executor
00:00
Using Shell (powershell) executor...
Preparing environment
00:00
Running on Test-Machine...
Getting source from Git repository
00:02
At line:274 char:29
+ ${CI_COMMIT_REF_PROTECTED}="true"
+ ~~~~~
Unexpected token 'true"
${env:CI_COMMIT_REF_PROTECTED}=${CI_COMMIT_REF_PROTECTED}
${CI_COMMIT_TIMESTAMP}="2026-10-10T21:40:55+08:00"
${env:CI_COMMIT_TIMESTAMP}=${CI_COMMIT_TIMESTAMP}
${CI_COMMIT_AUTHOR}="user' in expression or statement.
At line:278 char:34
+ ${CI_COMMIT_AUTHOR}="user <user@example.com>"
+ ~
The '<' operator is reserved for future use.
At line:332 char:104
+ ... \builds\abc123xyz\0\user\automationtest\.git\index.lock"
+ ~
The string is missing the terminator: ".
At line:1 char:3
+ & {
+ ~
Missing closing '}' in statement block or type definition.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedToken
Gitaly correlation ID: 01MXXXXXXXXXXXXXXXXXXXXXX
Cleaning up project directory and file based variables
00:01
At line:272 char:29
+ ${CI_COMMIT_REF_PROTECTED}="true"
+ ~~~~~
Unexpected token 'true"
${env:CI_COMMIT_REF_PROTECTED}=${CI_COMMIT_REF_PROTECTED}
${CI_COMMIT_TIMESTAMP}="2026-10-10T21:40:55+08:00"
${env:CI_COMMIT_TIMESTAMP}=${CI_COMMIT_TIMESTAMP}
${CI_COMMIT_AUTHOR}="user' in expression or statement.
At line:276 char:34
+ ${CI_COMMIT_AUTHOR}="user <user@example.com>"
+ ~
The '<' operator is reserved for future use.
At line:336 char:110
+ ... \builds\abc123xyz\0\user\automationtest.tmp\gitlab_runner_env"
+ ~
The string is missing the terminator: ".
At line:1 char:3
+ & {
+ ~
Missing closing '}' in statement block or type definition.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedToken
At line:1 char:1
+ }
+ ~
Unexpected token '}' in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedToken
ERROR: Job failed: exit status 1
公司服务器用的powershell版本是5.1,这里面有个坑,CI_COMMIT_AUTHOR 自动获取的值包含了邮箱:xxx<xxx@wwww.com>。
在 PowerShell 中,< 和 > 是保留的重定向符号。当 GitLab Runner 自动把这个变量转换成 PowerShell 脚本注入时,由于内部引号或转义处理不当,导致 PowerShell 把 < 当成了语法错误,并且把整段字符串的引号截断了(The string is missing the terminator: ")。
连锁解析崩溃:
因为前面某一个环境变量(如包含空格、单双引号、尖括号的 Author 或 Commit Message)破坏了 PowerShell 的字符串闭合,导致后面生成的 PowerShell 临时环境脚本直接语法报错(ParserError),最终引发整个 Job 失败。
pwsh (powershell7)可以解决这个问题,但是我不想升级,所以采用了另外的方法:
在全局 variables 里面显式声明并覆盖 CI_COMMIT_AUTHOR:
bash
variables:
CI_COMMIT_AUTHOR: "xxx"
因为GitLab CI 允许在 YAML 的 variables 中直接重写默认的内置环境变量。通过把带有尖括号 <...> 的邮箱地址去掉,只保留纯文本名字 xxx,就能彻底避开 PowerShell 对 < 符号的语法审查和引号截断错误。
再具体说下CI_COMMIT_AUTHOR,它是GitLab的内置属性,是 GitLab 在每次触发 Pipeline 时自动生成并注入的系统变量,用来记录当前触发这次提交(Commit)的作者信息。它的默认格式是:作者名字 <邮箱地址>。
通过在全局 variables 中显式声明后,实际上是给 GitLab 发了一条指令:"不要使用系统默认那个带尖括号和邮箱的复杂字符串来初始化这个环境变量,请直接用我给你的这个纯文本(没有特殊符号)来代替它!"这样一来,Runner 注入到 PowerShell 里的语句就变成了干净的 $env:CI_COMMIT_AUTHOR="xxx",从而完美避开了 PowerShell 的语法拦截。