Comment arrêter un travail zombie imparable sur Jenkins sans redémarrer le serveur?

178

Notre serveur Jenkins a un travail en cours depuis trois jours, mais ne fait rien. Cliquer sur le petit X dans le coin ne fait rien, et le journal de sortie de la console n'affiche rien non plus. J'ai vérifié nos serveurs de build et le travail ne semble pas du tout en cours d'exécution.

Existe-t-il un moyen de dire à jenkins que le travail est "terminé", en éditant un fichier ou un verrou ou quelque chose? Comme nous avons beaucoup de travaux, nous ne voulons pas vraiment redémarrer le serveur.

blokkie
la source
1
Il semble qu'avec les versions récentes de Jenkins, la solution n'est pas celle marquée comme acceptée. (mais celui de '16)
NicolasW

Réponses:

213

Allez dans "Gérer Jenkins"> "Console de script" pour exécuter un script sur votre serveur pour interrompre le fil suspendu.

Vous pouvez obtenir tous les threads en direct avec Thread.getAllStackTraces()et interrompre celui qui est suspendu.

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

METTRE À JOUR:

La solution ci-dessus utilisant des threads peut ne pas fonctionner sur les versions plus récentes de Jenkins. Pour interrompre les pipelines gelés, reportez-vous à cette solution (par alexandru-bantiuc ) et exécutez:

Jenkins.instance.getItemByFullName("JobName")
                .getBuildByNumber(JobNumber)
                .finish(
                        hudson.model.Result.ABORTED,
                        new java.io.IOException("Aborting build")
                );
Zahra
la source
48
A très bien fonctionné! Pour tous ceux qui lisent, vous pouvez afficher les noms des threads en exécutant d'abord ce qui précède, avec la méthode appelantt -> println(t.getName());
Phil
2
Cela ne fonctionne toujours pas avec le script ci-dessus, il obtient les scripts mais ne tue pas le même.
Raghav S
2
pouvez-vous imprimer le nom du fil spécifique après avoir fait correspondre le nom dans t.getName()=="SOME NAME"?
Zahra
3
Cela ne m'aide pas non plus - le thread ne réagit pas à l'interruption ().
Zitrax
2
pour moi interrompre n'était pas suffisant, je devais appeler à la t.stopplace:Thread.getAllStackTraces().keySet().each() { t -> if (t.getName()=="YOUR THREAD NAME" ) { println(“Found, stopping now… “); t.stop(); } }
vendredi
258

J'ai également eu le même problème et je l'ai résolu via Jenkins Console.

Allez dans «Gérer Jenkins»> «Console de script» et exécutez un script:

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

Vous aurez juste à spécifier votre JobName et JobNumber.

Alexandru Bantiuc
la source
J'ai eu cela avec un travail de Pipeline qui a commencé d'autres emplois. Le serveur s'est écrasé, les autres travaux ont disparu, mais le travail du pipeline était toujours un zombie. J'ai d'abord essayé la réponse acceptée, en vain. J'ai dû exécuter la commande @ Alexandru plusieurs fois, chaque fois que je voyais la barre de progression du travail de pipeline bouger un peu. Finalement, le travail de pipeline était mort et pour de bonnes mesures je l'ai supprimé aussi.
Amedee Van Gasse
18
Cela fonctionne également très bien pour les projets multi-branches, mais la clé est de spécifier le JobName comme Jenkins.instance.getItemByFullName ("<project-name> / <branch-name>")
evasilchenko
22
Cette réponse m'a aidé à résoudre mon problème. Le pipeline était un zombie total. Le script ci-dessus n'a pas fonctionné et le pipeline était toujours en cours d'exécution même après quelques redémarrages de Jenkins. J'ai lu une documentation de classe interne et j'ai trouvé une méthode delete () donc mon script ressemblait à ceci: Jenkins.instance.getItemByFullName("JobName").getBuildByNumber(JobNumber).delete();Après avoir exécuté ceci et un autre redémarrage de Jenkins, la construction de zombie était enfin partie.
Szymon Sadło
5
Il n'y a pas de méthode finishdans AbstractBuild ni FreeSyleBuild ni MavenModulesetBuild
Jakub Bochenski
3
J'ai un problème lors de l'exécution de ce script, une idée? 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

Dans le cas où vous avez un travail de pipeline multibranch (et que vous êtes un administrateur Jenkins), utilisez ce script dans la console de script Jenkins :

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

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

Si vous n'êtes pas sûr du nom complet (chemin) de la tâche, vous pouvez utiliser l'extrait de code suivant pour répertorier le nom complet de tous les éléments:

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

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

Markus Schulte
la source
remarque à ce sujet: si vous utilisez SVN (et que vous suivez les conventions standard), votre <BRANCH NAME> sera quelque chose comme branches / my_branch
tvt173
25

J'utilise le plugin de surveillance pour cette tâche. Après l'installation du plugin

  1. Allez dans Gérer Jenkins> Surveillance du maître Hudson / Jenkins
  2. Développez les détails de Threads, le petit lien bleu sur le côté droit
  3. Recherchez le nom de la tâche bloquée

    Le nom du fil commencera comme ceci

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

  4. Cliquez sur le bouton rond rouge à l'extrême droite dans le tableau de la ligne de la tâche souhaitée

cheffe
la source
3
Il dit comme tué, mais encore une fois, lorsque nous actualisons la page, le fil semble être vivant
Raghav S
Intéressant. Je vais y jeter un œil. Cela dépend probablement de la construction. Si vous avez démarré des processus externes, probablement par des extensions ANT ou Maven, cela peut échouer.
cheffe
C'est la solution qui a fonctionné pour moi. Je viens d'entrer dans la liste des fils, j'ai recherché le nom du travail et j'ai cliqué sur le bouton rouge. jenkinsServer / monitoring # threads
Gilberto Treviño
24

Une fois que j'ai rencontré une construction qui ne pouvait pas être arrêtée par la "console de script". Enfin, j'ai résolu le problème avec ces étapes:

ssh onto the jenkins server
cd to .jenkins/jobs/<job-name>/builds/
rm -rf <build-number>
restart jenkins
Mugi
la source
cela a vraiment aidé dans mon cas: le travail n'existait plus au moment de le tuer via la console (travail de pipeline dynamique, branche de fonctionnalité supprimée)
mkko
24

La première solution proposée est assez proche. Si vous utilisez stop () au lieu d'interruption (), cela tue même les threads emballés, qui s'exécutent à l'infini dans un script système groovy. Cela tuera toute construction exécutée pour un travail. Voici le code:

Thread.getAllStackTraces().keySet().each() {
    if (it.name.contains('YOUR JOBNAME')) {  
      println "Stopping $it.name"
      it.stop()
    }
}
funql.org
la source
4
OMI qui devrait être la réponse acceptée. Toutes les autres réponses n'ont pas fonctionné pour moi, car la construction était déjà dans un état interrompu, mais cela était suspendu dans une étape de post-construction. Seule cette solution a vraiment arrêté la construction
Kutzi
1
L'utilisation containsici est incorrecte et dangereuse - si le nom de votre tâche est "Exécuter les tests", elle supprimera également toutes les tâches nommées "Exécuter les tests - Intégration", "Exécuter les tests - Unité", etc. Toute personne utilisant ceci devra faire attention à ne pas mettre fin de manière inattendue à des emplois indépendants
Brandon
14

Sans avoir à utiliser la console de script ou plugins supplémentaires, vous pouvez simplement faire avorter une construction en entrant /stop, /termou/kill après l'URL de construction dans votre navigateur.

Citant textuellement à partir du lien ci-dessus:

Les tâches de pipeline peuvent être arrêtées en envoyant une requête HTTP POST aux points de terminaison d'URL d'une génération.

  • <URL de l'ID BUILD> / stop - abandonne un pipeline.
  • <URL ID BUILD> / terme - met fin de force à une construction (ne doit être utilisé que si stop ne fonctionne pas.
  • <BUILD ID URL> / kill - arrête dur un pipeline. C'est le moyen le plus destructeur d'arrêter un pipeline et ne doit être utilisé qu'en dernier recours.
Dibakar Aditya
la source
13

Si vous avez un travail de pipeline imparable, essayez ce qui suit:

  1. Annulez le travail en cliquant sur le X rouge à côté de la barre de progression de la construction
  2. Cliquez sur "Pause / Reprendre" sur la compilation pour mettre en pause
  3. Cliquez à nouveau sur "Pause / Reprendre" pour reprendre la construction

Mettre en pause / reprendre le travail de pipeline

Jenkins se rendra compte que le travail doit être terminé et arrête la construction

Levente Holló
la source
8
Je n'ai pas cet élément de menu.
papaiatis
7

Le plugin Build-timeout peut être utile dans de tels cas. Cela supprimera automatiquement le travail si cela prend trop de temps.

Draco Ater
la source
1
Malheureusement, ce n'est pas une option pour nous, car nous avons quelques emplois qui sont censés durer des jours (ne demandez pas)
blokkie
7
Vous configurez les délais de génération par tâche.
Draco Ater
1
Non, nous avons une compilation bloquée pendant plus de 3 heures avec un délai d'expiration de 95 minutes. Je ne pense pas que le plugin timeout puisse aider car il fait la même chose que de cliquer sur "Abandonner" manuellement
Jakub Bochenski
7

Je suppose qu'il est trop tard pour répondre mais mon aide à certaines personnes.

  1. Installez le plugin de surveillance. ( http://wiki.jenkins-ci.org/display/JENKINS/Monitoring )
  2. Accédez à jenkinsUrl / monitoring / nodes
  3. Accédez à la section Threads en bas
  4. Cliquez sur le bouton Détails à gauche du master
  5. Trier par temps utilisateur (ms)
  6. Regardez ensuite le nom du thread, vous aurez le nom et le numéro de la construction
  7. Tue le

Je n'ai pas assez de réputation pour publier des images désolé.

J'espère que ça peut aider

Simon
la source
1
Ne pas aider, il dit tué. mais encore une fois, lorsque la page se recharge, je peux voir ce fil de discussion
Raghav S
Êtes-vous en train de tuer le thread de la construction ou un sous-thread de la construction? Quel est le nom de ce fil? Je suppose que vous ne tuez pas le bon. Si vous tuez le thread de la construction, vous verrez la construction terminée avec succès.
Simon
2
J'ai essayé de tuer le fil qui est associé au numéro d'exécuteur de l'esclave qui avait également le nom du travail. J'ai également trouvé plusieurs autres threads associés à Handling GET et les informations contenues concernaient Subversion. Tuer les deux n'a pas non plus aidé. Enfin redémarrer m'a aidé. Une autre observation était, d'autres threads sans association SVN étaient tuables.
Raghav S
Cette réponse est une copie de la réponse @cheffe, qui a été publiée un mois plus tôt.
t0r0X
6

La meilleure réponse a presque fonctionné pour moi, mais j'avais un problème majeur: j'avais un très grand nombre (~ 100) de tâches zombies en raison d'un redémarrage de Jenkins particulièrement mal chronométré, donc trouver manuellement le nom du travail et le numéro de build de chacun et chaque travail de zombie, puis les tuer manuellement était irréalisable. Voici comment j'ai automatiquement trouvé et tué les emplois zombies:

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

Ce script effectue une boucle sur toutes les générations de tous les travaux et utilise getResult().equals(null)pour déterminer si le travail est terminé ou non. Une build qui est dans la file d'attente mais pas encore démarrée ne sera pas répétée (puisque cette build ne sera pas incluse job.builds), et une build qui est déjà terminée renverra autre chose que nullfor build.getResult(). Une tâche en cours d'exécution légitime aura également un résultat de construction null, alors assurez-vous que vous n'avez pas de tâches en cours d'exécution que vous ne voulez pas tuer avant de l'exécuter.

Les multiples boucles imbriquées sont principalement nécessaires pour découvrir chaque branche / PR pour chaque référentiel dans un projet Multibranch Pipeline; si vous n'utilisez pas de pipelines multibranches, vous pouvez simplement parcourir tous vos travaux directement avec quelque chose comme Jenkins.instance.getItems().each.

Jayhendren
la source
3
J'ai légèrement amélioré votre script. runningBuilds = Jenkins.instance.getView('All').getBuilds().findAll() { it.getResult().equals(null) } runningBuilds.each { branch->branch.doKill() }
Tobi
5

J'ai regardé la source Jenkins et il semble que ce que j'essaie de faire est impossible, car l'arrêt d'un travail semble se faire via une interruption de thread. Je n'ai aucune idée de la raison pour laquelle le travail est suspendu.

Éditer:

Raisons possibles des tâches imparables:

  • si Jenkins est bloqué dans une boucle infinie, il ne peut jamais être abandonné.
  • si Jenkins effectue une E / S réseau ou fichier dans la machine virtuelle Java (comme une longue copie de fichier ou une mise à jour SVN), il ne peut pas être abandonné.
blokkie
la source
Ce n'est en fait pas impossible. Vous pouvez utiliser la console de script jenkins pour interrompre le thread qui exécute votre travail. Voir l'explication ici: stackoverflow.com/a/26306081/1434041
Zahra
3

J'utilise habituellement jenkins-cli dans de tels cas. Vous pouvez télécharger le pot à partir d'une page http://your-jenkins-host:PORT/cli. Puis cours

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

Infos auxiliaires:

Vous pouvez également passer une gamme de builds comme 350:400. Aide générale disponible en exécutant

java -jar jenkins-cli.jar help

Aide des commandes contextuelles pour delete-buildspar

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

La réponse d'Alexandru Bantiuc a bien fonctionné pour que j'arrête la construction, mais mes exécuteurs testamentaires étaient toujours aussi occupés. J'ai pu effacer le statut de l'exécuteur occupé en utilisant ce qui suit

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
la source
3

Eu ce même problème mais il n'y avait pas de thread de pile. Nous avons supprimé le travail en utilisant cet extrait de code dans la console Jenkins. Remplacez jobname et buil dnumber par le vôtre.

def jobname = "Main/FolderName/BuildDefinition"
def buildnum = 6
Jenkins.instance.getItemByFullName(jobname).getBuildByNumber(buildnum).delete(); 
Kenneth King
la source
1
Cela ne fonctionne pas! Il supprimera uniquement la construction de la vue, laissant le processus en cours d'exécution et toutes les ressources verrouillées
Jakub Bochenski
3

Récemment, je suis tombé sur un nœud / agent qui avait un exécuteur occupé pendant des jours par une construction "X" d'un travail de pipeline, bien que cette page d'emplois déclarée que la construction "X" n'existait plus (abandonnée après 10 versions suivantes (!), Comme configuré dans le travail de pipeline). Vérifié que sur le disque: la construction "X" était vraiment partie.

La solution: c'est l'agent / le nœud qui a signalé à tort que l'exécuteur occupé était occupé à exécuter la construction "X". L'interruption du thread de cet exécuteur l'a immédiatement libéré.

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

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

Autres réponses envisagées:

  • La réponse de @cheffe: n'a pas fonctionné (voir point suivant et mise à jour ci-dessous).
  • Les réponses avec Thread.getAllStackTraces() : aucun fil correspondant.
  • La réponse de @ levente-holló et toutes les réponses avec getBuildByNumber() : ne s'appliquaient pas car la construction n'était plus vraiment là!
  • La réponse de @austinfromboston: cela s'est rapproché de mes besoins, mais cela aurait également détruit toutes les autres versions en cours d'exécution pour le moment.

Mise à jour:
J'ai de nouveau vécu une situation similaire, où un exécuteur était occupé pendant des jours par une construction de pipeline terminée (toujours existante). Cet extrait de code était la seule solution fonctionnelle.

t0r0X
la source
Cela a fait l'affaire pour moi, merci! Les autres solutions ne fonctionnaient pas car le numéro de build était déjà jeté (nous gardons juste les builds lat 5, donc job.getBuildByNumber (...) n'a rien retourné).
L. Tischler
2

J'ai eu le même problème au cours de la dernière demi-heure ...

Impossible de supprimer une version zombie exécutée dans mon pipeline multi-branches. Même le serveur redémarre par l'interface utilisateur ou même à partir de la ligne de commande via sudo service jenkins restart a bloqué l'exécution ... La construction n'était pas arrêtable ... Elle a toujours été récoltée.

Version utilisée: Jenkins ver 2.150.2

J'étais très ennuyé, mais ... en regardant dans le journal de la construction, j'ai trouvé quelque chose d'intéressant à la fin du journal:

La sortie du fichier journal d'une construction zombie et l'affichage du redémarrage ne l'ont pas arrêtée

Les parties marquées en rouge sont les "parties frustrantes" ... Comme vous pouvez le voir, j'ai toujours voulu abandonner la construction depuis l'interface utilisateur mais cela n'a pas fonctionné ...

Mais il y a un lien hypertexte avec du texte Click here to forcibly terminate running steps... (premier vert) Maintenant, j'ai appuyé sur le lien ...) Après l'exécution du lien, un message sur Still pausedest apparu avec un autre lienClick here to forcibily kill entire build (deuxième vert) Après avoir appuyé sur ce lien, la construction était finalement difficile tué...

Cela semble donc fonctionner sans plugins spéciaux (à l'exception du plugin de construction multibranch-pipeline lui-même).

de-jcup
la source
Si vous donniez le lien vers lequel «Cliquez ici pour tuer de force toute la construction», je voterais pour parce que cela fonctionnerait pour moi. Malheureusement, cette solution ne fonctionne pas car Jenkins ne parvient pas à afficher les derniers journaux car le fichier journal fait plusieurs Go.
mjaggard
Désolé, je n'ai actuellement plus accès à ces journaux. Si j'ai à nouveau cet échec, j'ajouterai un commentaire sur sa solution / mise à jour. Mais qu'en est-il de faire une connexion sur votre machine jenkins et d'utiliser simplement tailou une visionneuse de journal pour obtenir le lien?
de-jcup
3
Cela a fonctionné pour moi, merci! @mjaggard: Le lien est:<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

J'avais beaucoup de tâches zombi, j'ai donc utilisé le script suivant:

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
la source
1

Cela fonctionne pour moi à chaque fois:

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

Merci à funql.org

Aviel Yosef
la source
0

J'ai eu le même problème deux fois maintenant, le seul canapé correct a été de redémarrer le serveur tomcat et de redémarrer la construction.

Ernie
la source
0

Un utilitaire que j'ai écrit appelé jkillthread peut être utilisé pour arrêter n'importe quel thread dans n'importe quel processus Java, à condition que vous puissiez vous connecter à la machine exécutant le service sous le même compte.

Jesse Glick
la source
0

SOLUTION TRÈS SIMPLE

La raison pour laquelle je voyais ce problème était un httplien incorrect sur la page au lieu de httpscela devrait arrêter le travail. Tout ce que vous avez à faire est de modifier l' onclickattribut dans la page html, en suivant

  1. Ouvrez un journal de console du travail (pipeline) qui s'est bloqué
  2. Cliquez sur ce qui est disponible pour tuer le travail (icône x, "Cliquez ici pour forcer l'arrêt des étapes en cours", etc.) pour obtenir le lien "Cliquez ici pour tuer de force toute la construction" visible (il ne sera PAS cliquable pour le moment)
  3. Ouvrez la console du navigateur ( utilisez l'un des trois pour chrome: F12; ctrl + shift + i; menu-> plus d'outils-> outils de développement )
  4. Recherchez manuellement le lien "Cliquez ici pour tuer de force toute la construction" ou utilisez le bouton "Sélectionnez un élément dans la page" de la console
  5. Double-cliquez sur onclick attribut pour modifier sa valeur
  6. Append sà httpavoirhttps
  7. Appuyez sur Entrée pour soumettre les modifications
  8. Cliquez sur le lien «Cliquez ici pour tuer de force toute la construction»

Utilisez une capture d'écran pour référence entrez la description de l'image ici

Sergey Pleshakov
la source
0

Utilisation de la console de script sur 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
la source
0

Aucune de ces solutions n'a fonctionné pour moi. J'ai dû redémarrer la machine sur laquelle le serveur était installé. Le travail impossible à tuer est maintenant terminé.

Marc Laliberté
la source
-1

Vous pouvez simplement copier le travail et supprimer l'ancien. Si cela n'a pas d'importance que vous ayez perdu les anciens journaux de construction.

GUOHUI QIAN
la source
-2

Voici comment j'ai résolu ce problème dans la version 2.100avec Blue Ocean

  • Les seuls plugins que j'ai installés sont pour bitbucket.
  • Je n'ai qu'un seul nœud.

sshdans ma boîte Jenkins
cd ~/.jenkins(où je garde jenkins)
cd job/<job_name>/branches/<problem_branch_name>/builds
rm -rf <build_number>

Après cela, vous pouvez éventuellement changer le nombre dans nextBuildNumber(j'ai fait ceci)

Enfin, j'ai redémarré jenkins ( brew services restart jenkins) Cette étape sera évidemment différente selon la façon dont vous gérez et installez Jenkins.

Tom Bates
la source
-3

Entrez dans l'interface utilisateur blue-ocean. Essayez d'arrêter le travail à partir de là.

user3360767
la source
Qu'est-ce que ça veut dire? Mon serveur Jenkins n'a pas une telle interface utilisateur
Nico Haase
Blue ocean est un plugin Jenkins très courant, vous pouvez en savoir plus ici .
user3360767
Cela annule-t-il réellement le travail d'une manière différente de celle de l'interface utilisateur classique? Cela semble douteux.
StockB