Jenkins Pipeline: Как распечатать трассировку стека зависшего процесса по таймауту? - PullRequest
0 голосов
/ 27 августа 2018

В моем тестировании шаг конвейерного тайм-аута уничтожит зависший процесс до того, как он достигнет вашего блока 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 с предложением исправить это.

1 Ответ

0 голосов
/ 03 мая 2019

Это можно сделать с помощью команды timeout (часть 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"
}
...