在我的测试中,管道超时步骤将在挂起的进程到达catch块之前将其挂起,因此似乎无法运行“ jstack”(例如),因为为时已晚:
try{
timeout(time: 3, unit: 'SECONDS') {
sh "some slow/hanging java process"
}
} catch (org.jenkinsci.plugins.workflow.steps.FlowInterruptedException e) {
//check that the cause is org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution.ExceededTimeout
// then try to run jstack on all java processes on the machine.
// but that won't work because the offending process is already gone,
// "timeout" killed it...
}
概括地说,如何调试耗时太长的进程而又不终止进程?
我能想到的唯一解决方案确实很难看,就像这样:
def ok = false
def alarmTime = System.currentTimeMillis() + 50000 //just before timeout
parallel main: {
timeout(60000) {
//run java
ok = true
}
}, watcher: {
waitUntil {
ok || System.currentTimeMillis() > alarmTime
}
if (!ok) {
//perform debugging just before timeout fires.
}
}
但这在代码和输出中都很丑陋...
更新:我打开JENKINS-54415并提出了解决此问题的建议。
答案 0 :(得分:0)
您可以使用timeout command(coreutils的一部分)来完成此操作。
示例:
timeout --preserve-status --kill-after=30m --signal=3 20m <command>
这将在20分钟后打印线程堆栈跟踪转储,并在30分钟后终止该进程。
我通常将其包装在Jenkinsfile中的一个额外的超时块中,该超时块中的超时值稍高一些,以捕获不会退出的进程。 示例:
timeout(time: 35, unit: 'MINUTES') {
sh "timeout --preserve-status --kill-after=30m --signal=3 20m sbt test"
}