Come interrompere un lavoro zombi inarrestabile su Jenkins senza riavviare il server?


178

Il nostro server Jenkins ha un lavoro in esecuzione da tre giorni, ma non sta facendo nulla. Fare clic sulla piccola X nell'angolo non fa nulla e neanche il registro di output della console mostra nulla. Ho controllato i nostri server di compilazione e il lavoro in realtà non sembra essere in esecuzione.

C'è un modo per dire a Jenkins che il lavoro è "fatto", modificando un file o un blocco o qualcosa del genere? Dal momento che abbiamo molti lavori non vogliamo davvero riavviare il server.


1
Sembra che con le versioni recenti di Jenkins la soluzione non sia quella contrassegnata come accettata. (ma quello del '16)
NicolasW,

Risposte:


213

Vai su "Gestisci Jenkins"> "Script Console" per eseguire uno script sul tuo server per interrompere il thread sospeso.

Puoi ottenere tutti i thread live con Thread.getAllStackTraces()e interrompere quello che è sospeso.

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

AGGIORNARE:

La soluzione di cui sopra che utilizza i thread potrebbe non funzionare su versioni Jenkins più recenti. Per interrompere pipeline congelate fare riferimento a questa soluzione (di alexandru-bantiuc ) invece ed eseguire:

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

48
Ha funzionato alla grande! Per chiunque legga, puoi visualizzare i nomi dei thread eseguendo prima quanto sopra, con il metodo che chiamat -> println(t.getName());
Phil

2
Ancora non funziona anche con lo script Above, sta ottenendo gli script ma non uccidendo lo stesso.
Raghav S

2
sei in grado di stampare il nome del thread specifico dopo aver abbinato il nome in t.getName()=="SOME NAME"?
Zahra,

3
Neanche questo mi aiuta: il thread non reagisce all'interrupt ().
Zitrax,

2
per me l'interruzione non era abbastanza, dovevo chiamare t.stopinvece:Thread.getAllStackTraces().keySet().each() { t -> if (t.getName()=="YOUR THREAD NAME" ) { println(“Found, stopping now… “); t.stop(); } }
venerdì

258

Ho avuto anche lo stesso problema e risolto tramite la console Jenkins.

Vai su "Gestisci Jenkins"> "Script Console" ed esegui uno script:

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

Dovrai semplicemente specificare il tuo JobName e JobNumber.


Ho avuto questo con un lavoro Pipeline che ha iniziato altri lavori. Il server si è arrestato in modo anomalo, gli altri lavori erano spariti, ma il processo della pipeline era ancora uno zombi. Per prima cosa ho provato la risposta accettata, inutilmente. Ho dovuto eseguire il comando @ Alexandru più volte, ogni volta che vedevo spostarsi un po 'la barra di avanzamento del processo della pipeline. Alla fine il lavoro della pipeline era morto e per buone misure l'ho eliminato anche io.
Amedee Van Gasse,

18
Funziona benissimo anche per progetti multi-branch, ma la chiave è specificare JobName come Jenkins.instance.getItemByFullName ("<project-name> / <branch-name>")
evasilchenko

22
Questa risposta mi ha aiutato a risolvere il mio problema. La pipeline era uno zombi totale. Lo script sopra non ha funzionato e la pipeline era ancora in esecuzione anche dopo alcuni riavvii di jenkins. Ho letto un po 'di documentazione interna della classe e ho trovato un metodo delete () in modo che il mio script fosse simile al seguente: Jenkins.instance.getItemByFullName("JobName").getBuildByNumber(JobNumber).delete();Dopo aver eseguito questo e l'altro Jenkins si riavvia, la build degli zombi è finalmente scomparsa.
Szymon Sadło,

5
Non c'è metodo finishin AbstractBuild né FreeSyleBuild né MavenModulesetBuild
Jakub Bochenski

3
Ho un problema quando eseguo questo script, qualche 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

Nel caso in cui tu abbia una pipeline multibranch (e tu sei un amministratore Jenkins), usa nella console di script Jenkins questo script:

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

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

Se non sei sicuro di quale sia il nome completo (percorso) del lavoro, puoi utilizzare il seguente frammento per elencare il nome completo di tutti gli elementi:

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

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


nota a margine di questo: se stai usando SVN (e segui le convenzioni standard), il tuo <NOME DI FILIALE> sarà qualcosa come rami / my_branch
tvt173

25

Uso il plugin di monitoraggio per questo compito. Dopo l'installazione del plugin

  1. Vai a Gestisci Jenkins> Monitoraggio del master Hudson / Jenkins
  2. Espandi i dettagli dei thread, il piccolo link blu sul lato destro
  3. Cerca il nome del lavoro che è stato appeso

    Il nome della discussione inizierà così

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

  4. Fare clic sul pulsante rosso e rotondo a destra nella tabella della riga del lavoro desiderato


3
Dice che è stato ucciso, ma di nuovo quando aggiorniamo la pagina il thread sembra essere vivo
Raghav S

Interessante. Lo darò un'occhiata. Probabilmente dipende dalla build. Nel caso in cui siano stati avviati processi esterni, probabilmente con estensioni ANT o Maven, questo potrebbe non riuscire.
Cheffe,

Questa è la soluzione che ha funzionato per me. Sono appena entrato nell'elenco dei thread, ho fatto una ricerca per il nome del lavoro e fatto clic sul pulsante rosso. jenkinsServer / monitoring # thread
Gilberto Treviño

24

Una volta ho incontrato una build che non poteva essere fermata dalla "Script Console". Alla fine ho risolto il problema con questi passaggi:

ssh onto the jenkins server
cd to .jenkins/jobs/<job-name>/builds/
rm -rf <build-number>
restart jenkins

che in realtà ha aiutato nel mio caso: il lavoro non esisteva più al momento di ucciderlo tramite la console (processo di pipeline dinamico, ramo di funzionalità eliminato)
mkko

24

La prima soluzione proposta è piuttosto vicina. Se usi stop () invece di interrupt () uccide persino i thread in fuga, che girano all'infinito in uno script di sistema groovy. Questo ucciderà qualsiasi build, che viene eseguito per un lavoro. Ecco il codice:

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

4
IMO che dovrebbe essere la risposta accettata. Tutte le altre risposte non hanno funzionato per me, dato che la build era già in uno stato interrotto, ma che pendeva in un passaggio post build. Solo questa soluzione ha davvero fermato la costruzione
Kutzi il

1
L'uso containsqui è errato e pericoloso - se il nome del tuo lavoro è "Esegui test", ucciderà anche tutti i lavori denominati "Esegui test - Integrazione", "Esegui test - Unità", ecc. Chiunque lo utilizzi dovrà fare attenzione a non interrompere inaspettatamente lavori non correlati
Brandon,

14

Senza dover utilizzare la console script o plugin aggiuntivi, si può semplicemente interrompere una compilazione inserendo /stop, /termo /killdopo l'URL accumulo nel tuo browser.

Citando alla lettera dal link sopra:

I lavori della pipeline possono essere interrotti inviando una richiesta POST HTTP agli endpoint URL di una build.

  • <URL ID BUILD> / stop : interrompe una pipeline.
  • <BUILD ID URL> / term : termina forzatamente una build (dovrebbe essere utilizzata solo se stop non funziona.
  • <URL ID BUILD> / kill : interruzione definitiva di una pipeline. Questo è il modo più distruttivo per fermare una conduttura e dovrebbe essere usato solo come ultima risorsa.

13

Se si dispone di un processo di pipeline inarrestabile, provare quanto segue:

  1. Annullare il lavoro facendo clic sulla X rossa accanto alla barra di avanzamento della creazione
  2. Fai clic su "Pausa / riprendi" sulla build per mettere in pausa
  3. Fai di nuovo clic su "Pausa / riprendi" per riprendere la compilazione

Pausa / Riprendi processo pipeline

Jenkins realizzerà che il lavoro dovrebbe essere terminato e interrompe la compilazione


8
Non ho questa voce di menu.
papaiatis,

7

Build-timeout Plugin può tornare utile in questi casi. Ucciderà automaticamente il lavoro se impiega troppo tempo.


1
Sfortunatamente questa non è un'opzione per noi, perché abbiamo un paio di lavori che dovrebbero funzionare per giorni (non chiedere)
Blokkie,

7
Configurare i timeout di compilazione in base al lavoro.
Draco Ater,

1
No, abbiamo una build bloccata per oltre 3 ore con un timeout impostato su 95 minuti Non credo che il plug-in di timeout possa essere d'aiuto in quanto fa lo stesso clic su "Annulla" manualmente
Jakub Bochenski,

7

Immagino sia troppo tardi per rispondere, ma il mio aiuto alcune persone.

  1. Installa il plug-in di monitoraggio. ( http://wiki.jenkins-ci.org/display/JENKINS/Monitoring )
  2. Vai a jenkinsUrl / monitoring / nodes
  3. Vai alla sezione Discussioni in fondo
  4. Fai clic sul pulsante Dettagli a sinistra del master
  5. Ordina per Tempo utente (ms)
  6. Quindi guarda il nome del thread, avrai il nome e il numero della build
  7. Uccidilo

Non ho abbastanza reputazione per pubblicare scusate immagini.

Spero possa essere d'aiuto


1
Non aiuta, dice ucciso. ma di nuovo quando la pagina viene ricaricata sono in grado di vedere quel thread
Raghav S

Stai uccidendo il thread della build o un subthread della build? Qual è il nome di questa discussione? Immagino che tu non uccida quello buono. Se uccidi il thread della build, vedrai che la build è stata completata correttamente.
Simon,

2
Ho provato a uccidere il thread associato al numero di slave dello esecutore che aveva anche il nome del lavoro. Ho anche trovato molti altri thread associati a Handling GET e le informazioni contenute erano relative a Subversion. Anche uccidere entrambi non ha aiutato. Finalmente il riavvio mi ha aiutato. Un'altra osservazione è stata: Altri thread senza associazione SVN erano killable.
Raghav S,

Questa risposta è una copia della risposta di @cheffe, che è stata pubblicata un mese prima.
t0r0X,

6

La risposta migliore ha funzionato quasi per me, ma ho avuto un grosso problema: ho avuto un numero molto grande (~ 100) di lavori con zombi a causa di un riavvio di Jenkins particolarmente scaduto, quindi trovando manualmente il nome del lavoro e il numero di build di ciascuno e ogni lavoro di zombi e poi ucciderli manualmente era impossibile. Ecco come ho trovato e ucciso automaticamente i lavori di zombi:

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

Questo script scorre su tutte le build di tutti i lavori e li utilizza getResult().equals(null)per determinare se il lavoro è terminato o meno. Una build che è in coda ma non ancora avviata non verrà ripetuta (poiché quella build non sarà presente job.builds) e una build già completata restituirà qualcosa di diverso da nullfor build.getResult(). Anche un lavoro in esecuzione legittima avrà un risultato di compilazione null, quindi assicurati di non avere lavori in esecuzione che non desideri interrompere prima di eseguirlo.

I loop multipli nidificati sono principalmente necessari per scoprire ogni branch / PR per ogni repository in un progetto Multibranch Pipeline; se non stai usando Multibranch Pipelines puoi semplicemente fare il ciclo di tutti i tuoi lavori direttamente con qualcosa del genereJenkins.instance.getItems().each .


3
Ho leggermente migliorato la tua sceneggiatura. runningBuilds = Jenkins.instance.getView('All').getBuilds().findAll() { it.getResult().equals(null) } runningBuilds.each { branch->branch.doKill() }
Tobi

5

Ho esaminato la fonte di Jenkins e sembra che ciò che sto cercando di fare sia impossibile, perché l'interruzione di un lavoro sembra essere fatta tramite un interrupt di discussione. Non ho idea del perché il lavoro sia sospeso però ...

Modificare:

Possibili ragioni per lavori inarrestabili:

  • se Jenkins è bloccato in un ciclo infinito, non può mai essere interrotto.
  • se Jenkins sta eseguendo una I / O di rete o di file all'interno della VM Java (come una copia di file prolungata o un aggiornamento SVN), non può essere interrotto.

Questo in realtà non è impossibile. È possibile utilizzare la console di script jenkins per interrompere il thread che esegue il lavoro. Vedi la spiegazione qui: stackoverflow.com/a/26306081/1434041
Zahra,

3

Di solito uso jenkins-cli in questi casi. Puoi scaricare il barattolo da una pagina http://your-jenkins-host:PORT/cli. Quindi corri

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

Informazioni ausiliarie:

Puoi anche passare una serie di build come 350:400. Aiuto generale disponibile eseguendo

java -jar jenkins-cli.jar help

Guida dei comandi contesto delete-buildsda

java -jar jenkins-cli.jar delete-builds

3

La risposta di Alexandru Bantiuc ha funzionato bene per me per fermare la compilazione, ma i miei esecutori erano ancora impegnati. Sono stato in grado di cancellare lo stato di esecutore occupato usando quanto segue

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()
      }
    }
  }
}

3

Aveva lo stesso problema ma non c'era il thread dello stack. Abbiamo eliminato il lavoro utilizzando questo frammento nella console Jenkins. Sostituisci nome lavoro e crea numero con il tuo.

def jobname = "Main/FolderName/BuildDefinition"
def buildnum = 6
Jenkins.instance.getItemByFullName(jobname).getBuildByNumber(buildnum).delete(); 

1
Questo non funziona! Eliminerà solo la build dalla vista lasciando il processo in esecuzione e tutte le risorse bloccate
Jakub Bochenski

3

Di recente mi sono imbattuto in un nodo / agente che aveva un esecutore occupato per giorni da una build "X" di un lavoro della pipeline, sebbene quella pagina dei lavori affermasse che la build "X" non esisteva più (scartata dopo 10 build successive (!), Come configurato nel processo della pipeline). Verificato che su disco: la build "X" era davvero sparita.

La soluzione: era l'agente / nodo che ha erroneamente segnalato che l'esecutore occupato era occupato a eseguire la build "X". L'interruzione del thread di quell'esecutore lo ha immediatamente rilasciato.

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

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

Altre risposte considerate:

  • La risposta di @cheffe: non ha funzionato (vedere il punto successivo e aggiornare di seguito).
  • Le risposte con Thread.getAllStackTraces() : nessun thread corrispondente.
  • La risposta di @ levente-holló e tutte le risposte con getBuildByNumber() : non si applicava poiché la build non era più lì!
  • La risposta di @austinfromboston: questo si è avvicinato alle mie esigenze, ma avrebbe anche rovinato qualsiasi altra build in esecuzione al momento.

Aggiornamento:
ho riscontrato di nuovo una situazione simile, in cui un Executor è stato occupato per giorni da una costruzione di pipeline terminata (ancora esistente). Questo frammento di codice era l'unica soluzione funzionante.


Questo ha fatto il trucco per me, grazie! Le altre soluzioni non funzionavano poiché il numero di build era già stato eliminato (manteniamo solo le build lat 5, quindi job.getBuildByNumber (...) non ha restituito nulla).
L. Tischler,

2

Ho avuto lo stesso problema nell'ultima mezz'ora ...

Non è stato in grado di eliminare una build di zombi in esecuzione nella mia pipeline multi-branch. Anche il riavvio del server dall'interfaccia utente o persino dalla riga di comando tramite sudo service jenkins restart ha bloccato l'esecuzione ... La build non era bloccabile ... Ha sempre raccolto.

Versione utilizzata: Jenkins ver 2.150.2

Ero molto seccato, ma ... guardando nel registro della build ho trovato qualcosa di interessante alla fine del registro:

L'output del file di log di una build zombi e che mostra il riavvio non lo ha fermato

Le parti contrassegnate in rosso sono le "parti frustranti" ... Come puoi vedere, ho sempre voluto interrompere la compilazione dall'interfaccia utente, ma non ha funzionato ...

Ma c'è un collegamento ipertestuale con testo Click here to forcibly terminate running steps... (il primo verde) Ora ho premuto il collegamento ...) Dopo l'esecuzione del collegamento è Still pausedapparso un messaggio con un altro collegamentoClick here to forcibily kill entire build (secondo verde) Dopo aver premuto questo collegamento anche la build è stata finalmente difficile ucciso...

Quindi questo sembra funzionare senza alcun plug-in speciale (tranne lo stesso plug-in di build multibranch-pipeline).


Se hai indicato il link "Vai qui per uccidere forzatamente l'intera build", allora voterei perché funzionerebbe per me. Sfortunatamente questa soluzione non funziona perché Jenkins non riesce a mostrare gli ultimi registri perché il file di registro è di diversi GB.
mjaggard

Siamo spiacenti, al momento non ho più accesso a questi registri. Se riscontro nuovamente questo errore, aggiungerò un commento alla sua soluzione di aggiornamento. Ma che dire di fare un accesso alla tua macchina jenkins e semplicemente usare tailo un visualizzatore di log per ottenere il collegamento?
de-jcup,

3
Questo ha funzionato per me, grazie! @mjaggard: Il link è:<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

Ho avuto molti lavori zombi, quindi ho usato il seguente 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"))
}

1

Questo funziona per me ogni volta:

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

Grazie a funql.org


0

Ho avuto lo stesso problema accaduto due volte ora, l'unica correzione è stata riavviare il server Tomcat e riavviare la build.


0

Un'utilità che ho scritto chiamato jkillthread può essere utilizzata per interrompere qualsiasi thread in qualsiasi processo Java, purché sia ​​possibile accedere al computer che esegue il servizio con lo stesso account.


0

SOLUZIONE MOLTO SEMPLICE

Il motivo per cui stavo riscontrando questo problema era il httpcollegamento errato nella pagina invece httpsche quello avrebbe dovuto interrompere il lavoro. Tutto quello che devi fare è modificare l' onclickattributo nella pagina html, seguendo

  1. Aprire un registro della console del lavoro (pipeline) bloccato
  2. Fai clic su ciò che è disponibile per terminare il lavoro (icona x, "Fai clic qui per terminare forzatamente i passaggi in esecuzione" ecc.) Per visualizzare il link "Fai clic qui per terminare forzatamente l'intera build" ( NON sarà selezionabile)
  3. Apri la console del browser ( usa uno dei tre per Chrome: F12; ctrl + maiusc + i; menu-> più strumenti-> strumenti per sviluppatori )
  4. Individua il link "Fai clic qui per eliminare forzatamente l'intera build" manualmente o utilizzando il pulsante "seleziona un elemento nella pagina" della console
  5. Fare doppio clic su onclick per modificarne il valore
  6. Append sper httpaverehttps
  7. Premi Invio per inviare le modifiche
  8. Fai clic sul link "Fai clic qui per uccidere forzatamente l'intera build"

Usa screenshot per riferimento inserisci qui la descrizione dell'immagine


0

Utilizzando la console di script su 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)
    }
  }
}

0

Nessuna di queste soluzioni ha funzionato per me. Ho dovuto riavviare la macchina su cui era installato il server. Il lavoro non eseguibile è ora scomparso.


-1

Puoi semplicemente copiare il lavoro ed eliminare quello precedente. Se non importa che hai perso i vecchi registri di build.


-2

Ecco come ho risolto questo problema nella versione 2.100con Blue Ocean

  • Gli unici plugin che ho installato sono per bitbucket.
  • Ho solo un singolo nodo.

sshnella mia scatola di Jenkins
cd ~/.jenkins(dove tengo jenkins)
cd job/<job_name>/branches/<problem_branch_name>/builds
rm -rf <build_number>

Dopo questo, puoi facoltativamente cambiare il numero in nextBuildNumber(Ho fatto questo)

Infine, ho riavviato jenkins ( brew services restart jenkins) Questo passaggio sarà ovviamente diverso a seconda di come gestisci e installi Jenkins.


-3

Inserisci l'interfaccia utente dell'oceano blu. Prova a interrompere il lavoro da lì.


Cosa significa? Il mio server Jenkins non ha una tale interfaccia utente
Nico Haase,

Blue ocean è un plugin Jenkins molto comune, puoi leggerlo qui .
user3360767

Questo effettivamente interrompe il lavoro in un modo diverso rispetto alla classica interfaccia utente? Sembra dubbio.
StockB
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.