1
votes

Existe-t-il un moyen de diffuser la sortie d'une longue commande Groovy execute () vers la console plutôt que d'attendre qu'elle se termine?

J'exécute une commande shell via un script système Groovy. C'est un processus de longue haleine, environ 30 minutes, et il est assez détaillé. Mais comme écrit, cela attend que la commande se termine avant d'imprimer stdout ou stderr. Existe-t-il un moyen pour que la sortie soit envoyée à la console pendant l'exécution du script (comme ce serait le cas dans une session de terminal).

def cmd = "/home/adam/test.sh"
StringBuffer sout = new StringBuffer()
StringBuffer serr = new StringBuffer()
def process = cmd.execute()
process.waitForProcessOutput sout, serr
sout.each 
   println "Line ${it}"
}

Mise à jour: c'est le code que j'essaye en fonction de la réponse. Il n'imprime rien tant que le processus n'est pas terminé ou n'est pas arrêté.

def sout = new StringBuffer(), serr = new StringBuffer()
def proc = "/some/long/running/command".execute()

proc.consumeProcessOutput(sout, serr)
println "STDOUT\n $sout"
println "STDERR\n $serr"


0 commentaires

3 Réponses :


1
votes

C'est la solution que j'ai trouvée.

proc.in.eachLine { line -> println line }
proc.out.close()
proc.waitFor()


0 commentaires

4
votes

11 commentaires

WaitForProcessOutput () n'attend-il pas la fin du processus avant que la sortie ne soit disponible?


Non, il sort immédiatement mais se bloque jusqu'à ce que le processus soit terminé. Ainsi, vous obtiendrez toujours la sortie complète.


Je suppose que la partie qui me manque alors, c'est comment imprimer la sortie que le processus est en cours d'exécution. Étant donné le code suivant, il n'imprime rien jusqu'à ce que je tue le script "test.sh", qui est juste et sans fin d'impression en boucle de la date, et en veille pendant 30 secondes. def cmd = "/home/adam/test.sh" StringBuffer sout = new StringBuffer () StringBuffer serr = new StringBuffer () def process = cmd.execute () process.waitForProcessOutput sout, serr sout.each {println "Line $ { il}" }


J'ai changé le code. Il peut y avoir eu une erreur dans le précédent. J'ai essayé le nouveau moi-même. Il sort chaque ligne ping retourne et se termine une fois le processus terminé.


Pourriez-vous partager la ou les déclarations que vous utilisez pour imprimer le flux?


J'ai fait. Ce que fait le code, c'est qu'il lie la sortie du processus à la sortie du système. Ainsi, quelle que soit la sortie produite par le processus, elle est dirigée vers stdout et stderr.


Je vois, merci pour toutes les réponses Michael. J'exécute ceci comme un "script Groovy système d'exécution" et il ne produit rien. Étrange, je me serais attendu à ce qu'il accède à la sortie de la console pendant la construction.


J'ai mis à jour l'exemple pour être un script Groovy pleinement fonctionnel. Comme je l'ai dit, cela fonctionne très bien pour moi.


Je pense que la raison pour laquelle nos tests n'ont pas les mêmes résultats est que j'utilise une étape de construction "Exécuter le script Groovy du système", qui utilise le moteur Groovy interne, vous appelez Groovy en externe comme une étape de construction de script shell.


Oh, je ne savais pas que votre question concernait Jenkins. Pourquoi n'utilisez-vous pas sh ? AFAIK cela fera exactement ce que vous voulez. Voir jenkins.io/doc/ pipeline / étapes / workflow-durable-task-step /…


Ouais, désolé, je n'ai pas été plus clair à ce sujet. Et la raison pour laquelle j'utilisais une étape de construction de script Groovy système par rapport à un pipeline était parce que je peux facilement effectuer des étapes post-construction, alors qu'avec un pipeline, je dois les coder. Dans tous les cas, je me suis amélioré dans le codage des étapes de post dans les pipelines, et je vais le faire de cette façon. Merci encore :)



1
votes

Après une longue recherche, je n'ai pas pu trouver la solution exacte. Cela a fonctionné pour moi:

public int Execute(def command, File dir) {
          println("command: ${command}")
          Process process = command.execute(null, dir)
          def out = new StringBuffer()
          def err = new StringBuffer()
          process.consumeProcessOutput(out, err)
          while(1) {
              err.eachLine {line, count ->
                  println("${line}")
                  err.setLength(0)
              }
              out.eachLine { line, count ->
                  println("${line}")
                  out.setLength(0)
              }
              if(! process.isAlive()) {
                  break
                  }
              }
         return process.exitValue()
         }


0 commentaires