精简版
在 Jenkins 构建后的 groovy 脚本中,有没有办法让Computer.waitUntilOnline
函数在一段时间后超时?
背景
我们对嵌入式设备进行测试,我们的 jenkins slave 是连接到某些硬件设置的笔记本电脑。在某些情况下,我们需要一个 groovy post-build 脚本重新启动计算机,然后等待它再次上线。然而,有时这些机器不会再次上线,而我们的 groovy 脚本只是无限期地等待。
该waitUntilOnline
函数可以抛出 InterruptedException,但据我所知,您需要运行多个线程才能触发该异常。运行多个线程只是为了触发超时似乎是错误的处理方式。
我还找到了一些关于使用timeout
. 这是为 Jenkins Pipelines 设计的,所以我不确定我是否可以在构建后的 groovy 中使用它,而且我还没有让它工作。我尝试了各种组合,包括:
timeout(20)
{
computer.waitUntilOnline()
}
和
timeout(20)
{
waitUntil{
try {
computer.waitUntilOnline()
}catch (exception){
manager.listener.logger.println("caught exception!");
}
}
}
但似乎都抛出了这样的异常:
groovy.lang.MissingMethodException: No signature of method: Script1.timeout() is applicable for argument types: (java.lang.Integer, Script1$_rebootAndWait_closure1) values: [20, Script1$_rebootAndWait_closure1@7b6564fc]
任何建议表示赞赏。
编辑:我也尝试过@groovy.transform.TimedInterrupt
注释,正如这个问题中提到的,我得到了奇怪的结果。
当我运行这个简单的循环示例时,我得到了预期的结果:它为 i 打印了一些值。但是,如果我尝试将此与重新启动计算机相结合,如下所示:
import hudson.util.RemotingDiagnostics
def runCmd(computer, cmd)
{
def channel = computer.getChannel()
str = RemotingDiagnostics.executeGroovy( """
p = '$cmd'.execute()
p.waitFor()
p.in.text
""", channel )
}
@groovy.transform.TimedInterrupt( 3L )
def loopy()
{
int i = 0
try {
while( true ) {
i++
}
}
catch( e ) {
manager.listener.logger.println("i is "+i);
}
}
def rebootAndWait(computer)
{
manager.listener.logger.println("about to loopy : " +computer.name);
cmd = 'shutdown /r /t 10 /c "Restarting after Jenkins test completed"'
// cmd = "cmd.exe /c echo loopy test > c:\\\\Users\\\\frederikvs\\\\fvs_test.txt"
runCmd(computer, cmd)
// eventually we want to wait here for the computer to come back online, but for now we'll just have loopy
loopy();
}
rebootAndWait(manager.build.getBuiltOn().toComputer())
我得到了奇怪的结果:有时我得到 i 的一些值的预期输出,有时我得到一个未捕获的异常:
java.util.concurrent.TimeoutException: Execution timed out after 3 units. Start time: Fri Aug 17 10:48:07 CEST 2018
at sun.reflect.GeneratedConstructorAccessor5665.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:83)
at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:105)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:60)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:235)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:247)
at Script1.loopy(Script1.groovy)
at Script1.rebootAndWait(Script1.groovy:47)
at Script1$rebootAndWait.callCurrent(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:52)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:154)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:166)
at Script1.run(Script1.groovy:51)
at groovy.lang.GroovyShell.evaluate(GroovyShell.java:585)
at groovy.lang.GroovyShell.evaluate(GroovyShell.java:623)
at groovy.lang.GroovyShell.evaluate(GroovyShell.java:594)
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SecureGroovyScript.evaluate(SecureGroovyScript.java:343)
at org.jvnet.hudson.plugins.groovypostbuild.GroovyPostbuildRecorder.perform(GroovyPostbuildRecorder.java:380)
at hudson.tasks.BuildStepMonitor$1.perform(BuildStepMonitor.java:20)
at hudson.model.AbstractBuild$AbstractBuildExecution.perform(AbstractBuild.java:744)
at hudson.model.AbstractBuild$AbstractBuildExecution.performAllBuildSteps(AbstractBuild.java:690)
at hudson.model.Build$BuildExecution.post2(Build.java:186)
at hudson.model.AbstractBuild$AbstractBuildExecution.post(AbstractBuild.java:635)
at hudson.model.Run.execute(Run.java:1819)
at hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:43)
at hudson.model.ResourceController.execute(ResourceController.java:97)
at hudson.model.Executor.run(Executor.java:429)
这是踢球者:我是否获得 i 的值或异常,似乎取决于先前的运行。
如果我用 reboot 命令运行它几次,我总是会得到异常。如果我用 echo 命令(当前已注释掉)运行它几次,我总是得到打印 i 的预期结果。但是,如果我使用 reboot 命令运行它,然后将其切换到 echo 命令并运行几次,第一次使用 echo 它会给出异常,之后它会给出 i 的值。如果我从 echo 命令切换到 reboot 命令,第一次运行 reboot 也会很好(打印 i 的值),然后它会开始给出异常。
我不太明白上一次运行如何影响当前运行的超时......
再次感谢任何输入!