Jenkins Groovy脚本如何等待make_debug.sh执行完成并输出结果?
Jenkins流水线执行Shell脚本并捕获输出的问题解决
问题背景
原Jenkins声明式流水线脚本如下:
#!/usr/bin/env groovy def deploymentPaths = '[]' pipeline{ agent { label 'jenkins-agent' } stages{ stage('Build debug'){ steps{ sh './make_debug.sh' } } } }
为等待脚本执行完成并捕获输出,修改后的脚本如下:
#!/usr/bin/env groovy def deploymentPaths = '[]' pipeline{ agent { label 'jenkins-agent' } stages{ stage('Build debug'){ steps{ def sout = new StringBuilder(), serr = new StringBuilder() def proc = './make_debug.sh'.execute() proc.consumeProcessOutput(sout, serr) proc.waitForOrKill(10000) println "out> $sout\nerr> $serr" } } } }
运行后出现如下错误:
WorkflowScript: 13: Expected a step @ line 13, column 7. def sout = new StringBuilder(), serr = new StringBuilder() ^ WorkflowScript: 13: Expected a step @ line 13, column 39. def sout = new StringBuilder(), serr = new StringBuilder() ^ WorkflowScript: 14: Expected a step @ line 14, column 7. def proc = './make_debug.sh'.execute() ^ WorkflowScript: 15: Method calls on objects not allowed outside "script" blocks. @ line 15, column 13. proc.consumeProcessOutput(sout, serr) ^ WorkflowScript: 16: Method calls on objects not allowed outside "script" blocks. @ line 16, column 13. proc.waitForOrKill(1000) ^ WorkflowScript: 12: Missing required parameter: "delegate" @ line 12, column 5. step{ ^ WorkflowScript: 15: Arguments to "error" must be explicitly named. @ line 15, column 13. proc.consumeProcessOutput(sout, serr) ^ WorkflowScript: 16: Expecting "class java.lang.String" but got "1000" of type class java.lang.Integer instead @ line 16, column 32. proc.waitForOrKill(1000)
错误原因分析
- 声明式流水线限制:声明式流水线的
steps块内只能使用Jenkins官方提供的流水线步骤(如sh、echo),不能直接编写原生Groovy代码(变量定义、对象方法调用等),必须用script块包裹这类逻辑。 - 参数类型不匹配:
waitForOrKill方法要求传入字符串类型的超时时间,而非整数,需要将数值转为字符串。
正确实现方案
方案一:用script块包裹Groovy代码
将Groovy逻辑放在script块中,同时修正waitForOrKill的参数类型:
#!/usr/bin/env groovy def deploymentPaths = '[]' pipeline{ agent { label 'jenkins-agent' } stages{ stage('Build debug'){ steps{ script { def sout = new StringBuilder(), serr = new StringBuilder() def proc = './make_debug.sh'.execute() proc.consumeProcessOutput(sout, serr) proc.waitForOrKill('10000') // 改为字符串类型的超时时间 println "out> $sout\nerr> $serr" } } } } }
方案二:使用Jenkins sh步骤内置参数(更简洁)
Jenkins的sh步骤支持returnStdout和returnStderr参数,可直接捕获输出,无需手动处理进程:
#!/usr/bin/env groovy def deploymentPaths = '[]' pipeline{ agent { label 'jenkins-agent' } stages{ stage('Build debug'){ steps{ script { // 一次执行同时捕获合并后的输出(标准输出+错误输出) def output = sh(script: './make_debug.sh 2>&1', returnStdout: true).trim() println "脚本输出:\n$output" // 若需分开捕获标准输出和错误输出,脚本会执行两次,需注意: // def stdout = sh(script: './make_debug.sh', returnStdout: true).trim() // def stderr = sh(script: './make_debug.sh', returnStderr: true).trim() // println "标准输出:\n$stdout" // println "错误输出:\n$stderr" } } } } }
补充:设置超时时间
如果需要为脚本执行设置超时限制,可以用timeout步骤包裹sh操作:
steps{ script { timeout(time: 10, unit: 'SECONDS') { def output = sh(script: './make_debug.sh 2>&1', returnStdout: true).trim() println "脚本输出:\n$output" } } }
内容的提问来源于stack exchange,提问作者W Nguyen
相关产品推荐
相关产品推荐

