Jenkins管道:如何在超时时打印挂起进程的堆栈跟踪?

Jenkins管道:如何在超时时打印挂起进程的堆栈跟踪?,jenkins,groovy,jenkins-pipeline,Jenkins,Groovy,Jenkins Pipeline,在我的测试中,管道超时步骤将在挂起的进程到达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 caus

在我的测试中,管道超时步骤将在挂起的进程到达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.
  }
}
但这在代码和输出方面都很糟糕


更新:我打开了一个解决此问题的建议。

您可以使用(coreutils的一部分)来完成此操作

例如:

timeout --preserve-status --kill-after=30m --signal=3 20m <command>

此代码是在您的文件中还是在共享库中?您能提供更多的上下文吗。@AndrewGray这是一个Jenkins文件,我相信它在共享库中也会以同样的方式工作。我想让您看看超时步骤是如何杀死某些东西的,它真的很难看。确实感觉应该在Jenkins管道内部执行一些操作,以跟踪长时间运行的步骤并记录调用堆栈,当通过超时或任何其他方式中止管道时可以获得调用堆栈。问题中的代码已在使用
超时
。这甚至不是试图回答这个问题。
timeout(time: 35, unit: 'MINUTES') {
  sh "timeout --preserve-status --kill-after=30m --signal=3 20m sbt test"
}