¿Cómo detener un trabajo zombie imparable en Jenkins sin reiniciar el servidor?

178

Nuestro servidor Jenkins tiene un trabajo que se ha estado ejecutando durante tres días, pero no está haciendo nada. Hacer clic en la pequeña X en la esquina no hace nada, y el registro de salida de la consola tampoco muestra nada. He revisado nuestros servidores de compilación y el trabajo no parece estar ejecutándose en absoluto.

¿Hay alguna manera de decirle a Jenkins que el trabajo está "hecho", editando algún archivo o bloqueo o algo así? Como tenemos muchos trabajos, realmente no queremos reiniciar el servidor.

blokkie
fuente
1
Parece que con versiones recientes de Jenkins, la solución no es la marcada como aceptada. (pero el del '16)
NicolasW

Respuestas:

213

Vaya a "Manage Jenkins"> "Script Console" para ejecutar un script en su servidor para interrumpir el hilo colgante.

Puede obtener todos los hilos en vivo Thread.getAllStackTraces()e interrumpir el que está colgando.

Thread.getAllStackTraces().keySet().each() {
  t -> if (t.getName()=="YOUR THREAD NAME" ) {   t.interrupt();  }
}

ACTUALIZAR:

La solución anterior que utiliza subprocesos puede no funcionar en las versiones más recientes de Jenkins. Para interrumpir las tuberías congeladas, consulte esta solución (por alexandru-bantiuc ) y ejecute:

Jenkins.instance.getItemByFullName("JobName")
                .getBuildByNumber(JobNumber)
                .finish(
                        hudson.model.Result.ABORTED,
                        new java.io.IOException("Aborting build")
                );
Zahra
fuente
48
Funcionó genial! Para cualquiera que lea, puede ver los nombres de los hilos ejecutando primero lo anterior, con el método llamandot -> println(t.getName());
Phil
2
Todavía no funciona con el script Above también, está obteniendo los scripts pero no matando lo mismo.
Raghav S
2
¿Puede imprimir el nombre del hilo específico después de hacer coincidir el nombre t.getName()=="SOME NAME"?
Zahra
3
Esto tampoco me ayuda: el hilo no reacciona a la interrupción ().
Zitrax
2
para mí la interrupción no fue suficiente, necesitaba llamar en su t.stoplugar:Thread.getAllStackTraces().keySet().each() { t -> if (t.getName()=="YOUR THREAD NAME" ) { println(“Found, stopping now… “); t.stop(); } }
viernes
258

También tuve el mismo problema y lo solucioné a través de la consola Jenkins.

Vaya a "Administrar Jenkins"> "Consola de script" y ejecute un script:

 Jenkins .instance.getItemByFullName("JobName")
        .getBuildByNumber(JobNumber)
        .finish(hudson.model.Result.ABORTED, new java.io.IOException("Aborting build")); 

Solo tendrá que especificar su JobName y JobNumber.

Alexandru Bantiuc
fuente
Tuve esto con un trabajo de Pipeline que comenzó otros trabajos. El servidor se bloqueó, los otros trabajos se habían ido, pero el trabajo de la tubería todavía era un zombi. Primero probé la respuesta aceptada, en vano. Tuve que ejecutar el comando de @ Alexandru varias veces, cada vez que vi que la barra de progreso del trabajo de la tubería se movía un poco. Finalmente, el trabajo de la tubería había muerto y, por buenas medidas, también lo eliminé.
Amedee Van Gasse
18
Esto también funciona muy bien para proyectos de varias sucursales, pero la clave es especificar el JobName como Jenkins.instance.getItemByFullName ("<project-name> / <branch-name>")
evasilchenko
22
Esta respuesta me ayudó a resolver mi problema. La tubería era un zombie total. El script anterior no funcionó y la canalización aún se estaba ejecutando incluso después de algunos reinicios de jenkins. Leí algo de documentación interna de la clase y encontré un método delete (), así que mi script se veía así: Jenkins.instance.getItemByFullName("JobName").getBuildByNumber(JobNumber).delete();después de ejecutar esto y otro, jenkins reiniciar, la construcción zombie finalmente desapareció.
Szymon Sadło
55
No hay ningún método finishen AbstractBuild ni FreeSyleBuild ni MavenModulesetBuild
Jakub Bochenski el
3
Tengo un problema al ejecutar este script, ¿alguna idea? groovy.lang.MissingMethodException: No signature of method: hudson.model.FreeStyleBuild.finish() is applicable for argument types: (hudson.model.Result, java.io.IOException) values: [ABORTED, java.io.IOException: Aborting build] Possible solutions: find(), findAll(), find(groovy.lang.Closure) at
Tien Dung Tran
31

En caso de que tenga un trabajo Multibranch Pipeline (y usted es un administrador de Jenkins), use en la consola de Jenkins Script este script:

Jenkins.instance
.getItemByFullName("<JOB NAME>")
.getBranch("<BRANCH NAME>")
.getBuildByNumber(<BUILD NUMBER>)
.finish(hudson.model.Result.ABORTED, new java.io.IOException("Aborting build"));

De https://issues.jenkins-ci.org/browse/JENKINS-43020

Si no está seguro de cuál es el nombre completo (ruta) del trabajo, puede usar el siguiente fragmento para enumerar el nombre completo de todos los elementos:

  Jenkins.instance.getAllItems(AbstractItem.class).each {
    println(it.fullName)
  };

Desde https://support.cloudbees.com/hc/en-us/articles/226941767-Groovy-to-list-all-jobs

Markus Schulte
fuente
Nota al margen: si está utilizando SVN (y sigue las convenciones estándar), su <NOMBRE DE RAMA> será algo así como sucursales / my_branch
tvt173
25

Yo uso el complemento de monitoreo para esta tarea. Después de la instalación del complemento

  1. Vaya a Administrar Jenkins> Monitoreo del maestro Hudson / Jenkins
  2. Expanda los Detalles de hilos, el pequeño enlace azul en el lado derecho
  3. Busque el nombre del trabajo que está colgado

    El nombre del hilo comenzará así

    Executor #2 for master : executing <your-job-name> #<build-number>

  4. Haga clic en el botón rojo redondo a la derecha de la tabla de la línea que tiene su trabajo deseado

cheffe
fuente
3
Se dice que murió, pero de nuevo cuando actualice la página del hilo parece estar vivo
Raghav S
Interesante. Voy a echar un vistazo a esto. Probablemente depende de la construcción. En caso de que haya iniciado procesos externos, probablemente por extensiones ANT o Maven, esto podría fallar.
cheffe
Esta es la solución que funcionó para mí. Acabo de entrar en la lista de hilos, busqué el nombre del trabajo e hice clic en el botón rojo. jenkins Servidor / monitoreo # hilos
Gilberto Treviño
24

Una vez encontré una versión que no podía ser detenida por la "Consola de Script" Finalmente resolví el problema con estos pasos:

ssh onto the jenkins server
cd to .jenkins/jobs/<job-name>/builds/
rm -rf <build-number>
restart jenkins
mugi
fuente
eso realmente ayudó en mi caso: el trabajo ya no existía al momento de eliminarlo a través de la consola (trabajo de canalización dinámica, rama de función eliminada)
mkko
24

La primera solución propuesta está bastante cerca. Si usa stop () en lugar de interrupt (), incluso mata los hilos fuera de control, que se ejecutan sin fin en un script de sistema maravilloso. Esto matará cualquier compilación que se ejecute para un trabajo. Aquí está el código:

Thread.getAllStackTraces().keySet().each() {
    if (it.name.contains('YOUR JOBNAME')) {  
      println "Stopping $it.name"
      it.stop()
    }
}
funql.org
fuente
44
OMI que debería ser la respuesta aceptada. Todas las otras respuestas no funcionaron para mí, ya que la compilación ya estaba en un estado interrumpido, pero eso se quedó en algún paso posterior a la compilación. Solo esta solución realmente detuvo la construcción
Kutzi
1
El uso containsaquí es incorrecto y peligroso: si el nombre de su trabajo es "Ejecutar pruebas", también eliminará cualquier trabajo llamado "Ejecutar pruebas - Integración", "Ejecutar pruebas - Unidad", etc. Cualquier persona que use esto deberá tener cuidado de no hacerlo. terminar trabajos no relacionados inesperadamente
Brandon
14

Sin tener que utilizar la consola de comandos o plugins adicionales, simplemente puede abortar una acumulación mediante la introducción de /stop, /termo /killdespués de la URL de construcción en su navegador.

Citando textualmente desde el enlace de arriba:

Los trabajos de canalización se pueden detener enviando una solicitud HTTP POST a los puntos finales de URL de una compilación.

  • <BUILD ID URL> / stop - aborta una canalización.
  • <URL DE IDENTIFICACIÓN DE CONSTRUCCIÓN> / term : finaliza por la fuerza una compilación (solo debe usarse si stop no funciona.
  • <BUILD ID URL> / kill - mata con fuerza una tubería. Esta es la forma más destructiva de detener una tubería y solo debe usarse como último recurso.
Dibakar Aditya
fuente
13

Si tiene un trabajo de tubería imparable, intente lo siguiente:

  1. Anule el trabajo haciendo clic en la X roja junto a la barra de progreso de la compilación
  2. Haga clic en "Pausar / reanudar" en la compilación para pausar
  3. Haga clic en "Pausar / reanudar" nuevamente para reanudar la compilación

Pausar / Reanudar trabajo de canalización

Jenkins se dará cuenta de que el trabajo debe finalizar y detiene la compilación

Levente Holló
fuente
8
No tengo este elemento del menú.
papaiatis el
7

El complemento Build-timeout puede ser útil para tales casos. Eliminará el trabajo automáticamente si tarda demasiado.

Draco Ater
fuente
1
Por desgracia, eso no es una opción para nosotros, ya que tenemos un par de puestos de trabajo que se supone que una duración de días (no preguntar)
blokkie
77
Configura los tiempos de espera de compilación por trabajo.
Draco Ater
1
No, tenemos una compilación bloqueada durante más de 3 horas con un tiempo de espera establecido en 95 minutos. No creo que el complemento de tiempo de espera pueda ayudar, ya que está haciendo lo mismo que hacer clic en "Abortar" manualmente
Jakub Bochenski
7

Supongo que es demasiado tarde para responder, pero ayudo a algunas personas.

  1. Instale el complemento de monitoreo. ( http://wiki.jenkins-ci.org/display/JENKINS/Monitoring )
  2. Vaya a jenkinsUrl / tracking / nodos
  3. Vaya a la sección Hilos en la parte inferior.
  4. Haga clic en el botón de detalles a la izquierda del maestro
  5. Ordenar por tiempo de usuario (ms)
  6. Luego mire el nombre del hilo, tendrá el nombre y el número de la compilación
  7. Mátalo

No tengo suficiente reputación para publicar imágenes, lo siento.

Espero que pueda ayudar

Simón
fuente
1
No ayuda, dice asesinado. pero de nuevo cuando la página se recarga, puedo ver ese hilo
Raghav S
¿Estás matando el hilo de la construcción o un subproceso de la construcción? ¿Cuál es el nombre de este hilo? Supongo que no matas al bueno. Si elimina el hilo de la compilación, verá que la compilación finalizó con éxito.
Simon,
2
Traté de matar el hilo que está asociado con el número de ejecutor del esclavo que también tenía el nombre del trabajo. También encontré varios otros hilos asociados con Handling GET y la información contenida era con respecto a Subversion. Matar a ambos tampoco ayudó. Finalmente reiniciar me ayudó. Una observación más fue: Otros subprocesos sin asociación SVN fueron eliminables.
Raghav S
Esta respuesta es una copia de @cheffe answer, que se publicó un mes antes.
t0r0X
6

La respuesta principal casi funcionó para mí, pero tuve un problema importante: tuve un número muy grande (~ 100) de trabajos de zombies debido a un reinicio de Jenkins particularmente mal programado, por lo que encontrar manualmente el nombre del trabajo y el número de compilación de cada uno y cada trabajo zombie y luego matarlos manualmente no era factible. Así es como encontré y maté automáticamente los trabajos de zombies:

Jenkins.instance.getItemByFullName(multibranchPipelineProjectName).getItems().each { repository->
  repository.getItems().each { branch->
    branch.builds.each { build->
      if (build.getResult().equals(null)) {
        build.doKill()
      }
    }
  }
}

Este script recorre todas las compilaciones de todos los trabajos y lo utiliza getResult().equals(null)para determinar si el trabajo ha finalizado o no. Una compilación que está en la cola pero que aún no se inició no se repetirá (ya que esa compilación no estará en job.builds), y una compilación que ya está terminada devolverá algo más que nullpara build.getResult(). Un trabajo en ejecución legítimo también tendrá un resultado de compilación null, así que asegúrese de no tener trabajos en ejecución que no desee eliminar antes de ejecutar esto.

Los múltiples bucles anidados son principalmente necesarios para descubrir cada rama / PR para cada repositorio en un proyecto de tubería multibranch; Si no está utilizando tuberías de múltiples ramas, simplemente puede recorrer todos sus trabajos directamente con algo como Jenkins.instance.getItems().each.

jayhendren
fuente
3
He mejorado ligeramente tu guión. runningBuilds = Jenkins.instance.getView('All').getBuilds().findAll() { it.getResult().equals(null) } runningBuilds.each { branch->branch.doKill() }
Tobi
5

Miré la fuente de Jenkins y parece que lo que estoy tratando de hacer es imposible, porque la detención de un trabajo parece hacerse a través de una interrupción de Thread. Sin embargo, no tengo idea de por qué el trabajo está colgando ...

Editar:

Posibles razones para trabajos imparables:

  • Si Jenkins está atrapado en un bucle infinito, nunca se puede abortar.
  • si Jenkins está haciendo una red o E / S de archivo dentro de la máquina virtual Java (como una copia de archivo larga o una actualización SVN), no se puede cancelar.
blokkie
fuente
Esto en realidad no es imposible. Puede usar la consola de script jenkins para interrumpir el hilo que ejecuta su trabajo. Vea la explicación aquí: stackoverflow.com/a/26306081/1434041
Zahra
3

Usualmente uso jenkins-cli en tales casos. Puedes descargar el jar desde una página http://your-jenkins-host:PORT/cli. Entonces corre

java -jar jenkins-cli.jar delete-builds name_of_job_to_delete hanging_job_number

Información auxiliar:

También puede pasar una variedad de compilaciones como 350:400. Ayuda general disponible ejecutando

java -jar jenkins-cli.jar help

Ayuda de comando de contexto para delete-buildspor

java -jar jenkins-cli.jar delete-builds
Krzysztof Jabłoński
fuente
3

La respuesta de Alexandru Bantiuc funcionó bien para que detuviera la construcción, pero mis ejecutores seguían apareciendo ocupados. Pude borrar el estado de ejecutor ocupado usando lo siguiente

server_name_pattern = /your-servers-[1-5]/
jenkins.model.Jenkins.instance.getComputers().each { computer ->
  if (computer.getName().find(server_name_pattern)) {
    println computer.getName()
    execList = computer.getExecutors()      
    for( exec in execList ) {
      busyState = exec.isBusy() ? ' busy' : ' idle'
      println '--' + exec.getDisplayName() + busyState
      if (exec.isBusy()) {
        exec.interrupt()
      }
    }
  }
}
austinfromboston
fuente
3

Tuve este mismo problema pero no había hilo de pila. Eliminamos el trabajo usando este fragmento en la consola de Jenkins. Reemplace el nombre del trabajo y construya el número con el suyo.

def jobname = "Main/FolderName/BuildDefinition"
def buildnum = 6
Jenkins.instance.getItemByFullName(jobname).getBuildByNumber(buildnum).delete(); 
Kenneth King
fuente
1
¡Esto no funciona! Será solamente eliminar la acumulación de la vista dejando el proceso en ejecución y todos los recursos bloqueado
Jakub Bochenski
3

Recientemente me encontré con un nodo / agente que tenía un ejecutor ocupado durante días por una compilación "X" de un trabajo de canalización, aunque esa página de trabajos afirmaba que la compilación "X" ya no existía (descartada después de 10 compilaciones posteriores (!), Como configurado en el trabajo de canalización). Verificó eso en el disco: la compilación "X" realmente había desaparecido.

La solución: fue el agente / nodo el que informó erróneamente que el ejecutor ocupado estaba ocupado ejecutando la compilación "X". Interrumpir el hilo de ese ejecutor lo ha liberado inmediatamente.

def executor = Jenkins.instance.getNode('NODENAME').computer.executors.find {
    it.isBusy() && it.name.contains('JOBNAME')
}

println executor?.name
if (executor?.isBusy()) executor.interrupt()

Otras respuestas consideradas:

  • La respuesta de @cheffe: no funcionó (vea el siguiente punto y actualice a continuación).
  • Las respuestas con Thread.getAllStackTraces() : sin hilo coincidente.
  • La respuesta de @ levente-holló y todas las respuestas con getBuildByNumber() : no se aplicaron ya que la compilación ya no estaba allí.
  • La respuesta de @austinfromboston: eso estuvo cerca de mis necesidades, pero también habría destruido cualquier otra versión que se esté ejecutando en este momento.

Actualización:
Experimenté nuevamente una situación similar, donde un Ejecutor estuvo ocupado durante días por una construcción de tubería terminada (aún existente). Este fragmento de código fue la única solución de trabajo.

t0r0X
fuente
Esto me sirvió, ¡gracias! Las otras soluciones no funcionaban ya que el número de compilación ya se había descartado (solo conservamos las compilaciones lat 5, por lo que job.getBuildByNumber (...) no devolvió nada).
L. Tischler
2

Tuve el mismo problema en la última media hora ...

No pude eliminar una construcción zombie que se ejecuta en mi canalización de varias sucursales. Incluso el servidor se reinicia por la interfaz de usuario o incluso desde la línea de comandos a través de sudo service jenkins restart bloquear la ejecución ... La compilación no se podía detener ... Siempre reapareció.

Versión utilizada: Jenkins ver 2.150.2

Estaba muy molesto, pero ... al mirar el registro de la construcción, encontré algo interesante al final del registro:

La salida del archivo de registro de una construcción zombie y mostrar reinicio no lo detuvo

Las partes marcadas en rojo son las "partes frustrantes" ... Como puede ver, siempre quise Abortar la construcción desde la interfaz de usuario, pero no funcionó ...

Pero hay un hipervínculo con texto Click here to forcibly terminate running steps... (primero verde) Ahora presioné el enlace ...) Después de la ejecución del enlace, Still pausedapareció un mensaje sobre otro enlaceClick here to forcibily kill entire build (segundo verde) Después de presionar este enlace también la construcción finalmente fue difícil delicado...

Entonces, esto parece funcionar sin ningún complemento especial (excepto el complemento de compilación multibranch-pipeline).

de-jcup
fuente
Si le diera el enlace que dice "Haga clic aquí para matar por la fuerza la construcción completa", votaría porque eso funcionaría para mí. Desafortunadamente, esta solución no lo hace porque Jenkins no muestra los registros más recientes porque el archivo de registro tiene varios GB.
mjaggard 01 de
Lo sentimos, actualmente ya no tengo acceso a estos registros. Si vuelvo a tener este error, agregaré un comentario sobre su / solución de actualización. Pero, ¿qué hay de hacer un inicio de sesión en su máquina jenkins y simplemente usar tailo un visor de registros para obtener el enlace?
de-jcup
3
Esto funcionó para mí, gracias! @mjaggard: El enlace es:<a href="#" onclick="new Ajax.Request('[server]/jenkins/job/[pipeline_name]/[job_number]/kill'); return false">Click here to forcibly kill entire build</a>
kaveish
1

Tenía muchos trabajos de zombis, así que usé el siguiente script:

for(int x = 1000; x < 1813; x = x + 1) {
    Jenkins .instance.getItemByFullName("JOBNAME/BRANCH")
    .getBuildByNumber(x)
    .finish(hudson.model.Result.ABORTED, new java.io.IOException("Aborting build"))
}
Stéphane
fuente
1

Esto funciona para mí cada vez:

Thread.getAllStackTraces().keySet().each() {
if (it.name.contains('YOUR JOBNAME')) {  
  println "Stopping $it.name"
  it.stop()
}

Gracias a funql.org

Aviel Yosef
fuente
0

Me ha sucedido el mismo problema dos veces, la única solución ha sido reiniciar el servidor Tomcat y reiniciar la compilación.

Ernie
fuente
0

Una utilidad que escribí llamada jkillthread se puede usar para detener cualquier subproceso en cualquier proceso de Java, siempre que pueda iniciar sesión en la máquina que ejecuta el servicio con la misma cuenta.

Jesse Glick
fuente
0

SOLUCION MUY SIMPLE

La razón por la que veía este problema era un httpenlace incorrecto en la página, en lugar de httpseso debería detener el trabajo. Todo lo que necesita hacer es editar el onclickatributo en la página html, siguiendo

  1. Abra un registro de consola del trabajo (canalización) que se bloqueó
  2. Haga clic en lo que esté disponible para eliminar el trabajo (icono x, "Haga clic aquí para finalizar por la fuerza los pasos en ejecución", etc.) para obtener el enlace "Haga clic aquí para eliminar por completo la construcción completa" ( NO se podrá hacer clic en este momento)
  3. Abra la consola del navegador ( use cualquiera de los tres para Chrome: F12; ctrl + shift + i; menú-> más herramientas-> herramientas de desarrollador )
  4. Localice el enlace "Haga clic aquí para matar a la fuerza la construcción completa" manualmente o usando el botón "seleccionar un elemento en la página" de la consola
  5. Haga doble clic en el onclickatributo para editar su valor.
  6. Anexar sa httptenerhttps
  7. Presione enter para enviar los cambios
  8. Haga clic en el enlace "Haga clic aquí para matar por la fuerza la construcción completa"

Use la captura de pantalla como referencia ingrese la descripción de la imagen aquí

Sergey Pleshakov
fuente
0

Usando la consola de Script en https: // my-jenkins / script

import hudson.model.Job
import org.jenkinsci.plugins.workflow.job.WorkflowRun

Collection<Job> jobs = Jenkins.instance.getItem('My-Folder').getAllJobs()
for (int i = 0; i < jobs.size(); i++) {
  def job = jobs[i]
  for (int j = 0; j < job.builds.size(); j++) {
    WorkflowRun build = job.builds[j]
    if (build.isBuilding()) {
      println("Stopping $job ${build.number}")
      build.setResult(Result.FAILURE)
    }
  }
}
Poulad
fuente
0

Ninguna de estas soluciones funcionó para mí. Tuve que reiniciar la máquina en la que estaba instalado el servidor. El trabajo imposible de matar ya no existe.

Marc Laliberté
fuente
-1

Simplemente puede copiar el trabajo y eliminar el anterior. Si no importa que haya perdido los viejos registros de compilación.

GUOHUI QIAN
fuente
-2

Así es como solucioné este problema en la versión 2.100con Blue Ocean

  • Los únicos complementos que he instalado son para bitbucket.
  • Solo tengo un solo nodo.

sshen mi caja de Jenkins
cd ~/.jenkins(donde guardo Jenkins )
cd job/<job_name>/branches/<problem_branch_name>/builds
rm -rf <build_number>

Después de esto, puede cambiar opcionalmente el número en nextBuildNumber(Hice esto)

Finalmente, reinicié jenkins ( brew services restart jenkins) Este paso obviamente será diferente dependiendo de cómo administre e instale Jenkins.

Tom Bates
fuente
-3

Ingrese a la interfaz de usuario del océano azul. Intenta detener el trabajo desde allí.

usuario3360767
fuente
Qué significa eso? Mi servidor Jenkins no tiene esa interfaz de usuario
Nico Haase
Blue Ocean es un complemento de Jenkins muy común, puedes leer sobre esto aquí .
user3360767
¿Esto realmente aborta el trabajo de una manera diferente a la interfaz de usuario clásica? Parece dudoso
StockB