如何在Groovy脚本中传递Docker命令的退出状态?
问题
我需要从生成的Shell脚本中运行Docker命令,并将该Docker命令的退出状态返回至Groovy阶段,多次尝试后仍未成功。以下是我的代码:
def statusCode def script_shell_code script_shell_code = """ #!/bin/bash -x pwd docker run --rm \ my_docker.aws.us-east-1.amazonaws.com/${dockerImage} \ /bin/bash -c 'tar -czf; exit_code=\$?; echo code \$exit_code; exit \$exit_code' exit_code2=\$?; echo code \$exit_code2; exit \$exit_code2 """ steps.echo script_shell_code println("script_shell_code: ${script_shell_code}") statusCode = steps.sh(returnStatus:true, script: script_shell_code) steps.echo "script return status: ${statusCode}"
输出结果如下:
+ pwd /home/ubuntu/.jenkins/workspace/myworkspace1 + docker run --rm my_docker.aws.us-east-1.amazonaws.com/linux_release:tagv14 /bin/bash -c tar -czf; exit_code=0; echo code ; exit tar: option requires an argument -- 'f' Try 'tar --help' or 'tar --usage' for more information. code + exit_code2=0 + echo code 0 code 0 + exit 0 script return status110: 0
失败的tar命令本应返回状态码64,但该状态码丢失,最终获取到的状态码为0。如何让statusCode获取到真实的错误值64?
解决方案
核心问题分析
你的Shell脚本存在两个关键问题:
- 命令拆分导致逻辑失效:
docker run后的容器内命令被宿主机Shell错误拆分,实际变成了三个独立命令:docker run ... /bin/bash -c tar -czf、exit_code=0、echo code ; exit。这使得exit_code2捕获的是docker run本身的退出码(只要容器启动成功就返回0),而非容器内tar命令的失败码。 - 多余的中间变量干扰:额外定义的
exit_code2覆盖了docker run返回的真实容器退出码,最终返回了错误的0。
修复后的代码
Groovy部分
def statusCode def script_shell_code script_shell_code = """ #!/bin/bash -x pwd # 执行docker命令并直接传递其退出码 docker run --rm \ my_docker.aws.us-east-1.amazonaws.com/${dockerImage} \ /bin/bash -c 'tar -czf; exit_code=\$?; echo code \$exit_code; exit \$exit_code' # 直接返回docker命令的退出码给Groovy exit \$? """ steps.echo script_shell_code println("script_shell_code: ${script_shell_code}") statusCode = steps.sh(returnStatus:true, script: script_shell_code) steps.echo "script return status: ${statusCode}"
关键修改说明
- 移除冗余的
exit_code2逻辑:直接用exit $?返回docker run的退出码,而docker run默认会将容器内主进程的退出码(也就是tar命令的64)作为自身的退出码返回。 - 确保容器内命令完整性:容器内的
/bin/bash -c参数用单引号包裹,保证内部命令逻辑在容器内完整执行,不会被宿主机Shell拆分。
额外优化(可选)
如果需要更明确地指定容器内进程的退出码传递,可以添加--exit-code-from参数(默认就是主进程,所以非必须):
docker run --rm --exit-code-from main \ my_docker.aws.us-east-1.amazonaws.com/${dockerImage} \ /bin/bash -c 'tar -czf; exit_code=$?; echo code $exit_code; exit $exit_code' exit $?
内容的提问来源于stack exchange,提问作者Anton K
相关产品推荐
相关产品推荐

