GitLab Runner(Docker环境)执行‘yes | true’返回退出码1的问题排查
GitLab CI任务执行失败:exit status 1问题排查
先把遇到的场景放出来:
我在
.gitlab-ci.yml里配置了这样的任务:task: script: - yes | true - yes | someOtherCommandWhichNeedsYOrN执行后直接报错:
$ yes | true ERROR: Job failed: exit status 1
为啥会出现这个错误?
咱先拆解下这俩命令的脾气:
true命令特别简单,啥也不做直接返回成功(退出码0),而且它根本不会读取任何标准输入。yes命令则是一个劲儿往标准输出写y,直到被外力中断。
当你用管道把它们连起来时,true跑完就直接退出了,管道的输出端直接关闭。这时候yes还在傻乎乎地往管道里写内容,系统就会给yes发一个SIGPIPE信号(管道断裂信号),把它强制终止。而yes被这个信号干掉后,退出码不是0,GitLab CI又会严格检查每一条脚本命令的退出码——只要有一条非0,整个任务就直接标记失败了。
简单说就是:true不需要输入,yes白忙活还被干掉,导致CI任务炸了。
怎么调试和解决?
1. 先在本地复现问题
找个和你的GitLab Runner一样的Docker容器,手动执行yes | true,然后看退出码:
yes | true echo $? # 大概率会输出141,这就是SIGPIPE对应的退出码
看到141就实锤了:就是yes被管道断裂信号干掉导致的问题。
2. 最直接的解决:去掉多余的管道
既然true根本不需要输入,那直接写true就行,完全没必要用yes喂它。修改后的CI配置应该是这样:
task: script: - true - yes | someOtherCommandWhichNeedsYOrN
这样第一个命令正常返回0,后面的命令该用yes就用,完美解决。
3. 特殊场景的hack方案(不推荐)
如果某些特殊情况你必须保留yes | 不读输入的命令这种写法,可以让yes忽略SIGPIPE信号,或者在命令后面加个兜底的|| true:
# 方案1:让命令即使失败也返回0 yes | true || true # 方案2:临时忽略SIGPIPE信号 trap '' PIPE; yes | true; trap - PIPE
不过这种属于凑活的办法,优先推荐前面直接去掉多余管道的方式,更干净。
4. 查看CI完整日志
在GitLab的任务详情页,打开完整日志(有时候默认日志会截断细节),确认是不是yes进程的退出导致的失败,排除其他可能的问题。
内容的提问来源于stack exchange,提问作者Diolor
相关产品推荐
相关产品推荐

