Groovy exécute des commandes shell

Groovy ajoute la méthode execute à String pour rendre l'exécution des coquilles assez facile;

println "ls".execute().text

mais si une erreur se produit, alors il n'y a pas de résultat. Est-il un moyen facile d'obtenir à la fois l'erreur standard et standard? (autre que la création d'un tas de code pour; créer deux threads pour lire les deux inputstreams, puis en utilisant un flux parent pour attendre qu'ils se complètent puis convertir les chaînes de nouveau au texte?)

Il serait agréable d'avoir quelque chose comme;

 def x = shellDo("ls /tmp/NoFile")
 println "out: ${x.out} err:${x.err}"
119
demandé sur cdeszaq 2008-10-01 22:54:39

7 réponses

Ok, résolu moi-même;

def sout = new StringBuilder(), serr = new StringBuilder()
def proc = 'ls /badDir'.execute()
proc.consumeProcessOutput(sout, serr)
proc.waitForOrKill(1000)
println "out> $sout err> $serr"

affiche:

out> err> ls: cannot access /badDir: No such file or directory

136
répondu Bob Herrmann 2016-06-07 15:00:55

"ls".execute() retourne un Process objet ce qui explique que "ls".execute().text fonctionne. Vous devriez être en mesure de lire le flux d'erreur pour déterminer s'il y avait des erreurs.

il y a une méthode supplémentaire sur Process qui vous permet de passer un StringBuffer pour récupérer le texte: consumeProcessErrorStream(StringBuffer error) .

exemple:

def proc = "ls".execute()
def b = new StringBuffer()
proc.consumeProcessErrorStream(b)

println proc.text
println b.toString()
35
répondu Joshua 2016-06-07 14:34:02
// a wrapper closure around executing a string                                  
// can take either a string or a list of strings (for arguments with spaces)    
// prints all output, complains and halts on error                              
def runCommand = { strList ->
  assert ( strList instanceof String ||
           ( strList instanceof List && strList.each{ it instanceof String } ) \
)
  def proc = strList.execute()
  proc.in.eachLine { line -> println line }
  proc.out.close()
  proc.waitFor()

  print "[INFO] ( "
  if(strList instanceof List) {
    strList.each { print "${it} " }
  } else {
    print strList
  }
  println " )"

  if (proc.exitValue()) {
    println "gave the following error: "
    println "[ERROR] ${proc.getErrorStream()}"
  }
  assert !proc.exitValue()
}
23
répondu mholm815 2012-09-04 20:06:40

pour ajouter une information plus importante aux réponses fournies ci-dessus -

pour un procédé

def proc = command.execute();

toujours essayer d'utiliser

def outputStream = new StringBuffer();
proc.waitForProcessOutput(outputStream, System.err)
//proc.waitForProcessOutput(System.out, System.err)

plutôt que

def output = proc.in.text;

pour capturer les sorties après avoir exécuté des commandes dans groovy car ce dernier est un appel de blocage ( ainsi question pour raison ).

18
répondu Aniket Thakur 2017-05-23 12:02:49

je trouve cela plus idiomatique:

def proc = "ls foo.txt doesnotexist.txt".execute()
assert proc.in.text == "foo.txt\n"
assert proc.err.text == "ls: doesnotexist.txt: No such file or directory\n"

comme le mentionne un autre billet, ce sont des appels de blocage, mais puisque nous voulons travailler avec la sortie, cela peut être nécessaire.

9
répondu solstice333 2017-02-10 22:43:05
command = "ls *"

def execute_state=sh(returnStdout: true, script: command)

mais si la commande échoue le processus se terminera

5
répondu 舒何伟 2017-07-13 04:03:01
def exec = { encoding, execPath, execStr, execCommands ->

def outputCatcher = new ByteArrayOutputStream()
def errorCatcher = new ByteArrayOutputStream()

def proc = execStr.execute(null, new File(execPath))
def inputCatcher = proc.outputStream

execCommands.each { cm ->
    inputCatcher.write(cm.getBytes(encoding))
    inputCatcher.flush()
}

proc.consumeProcessOutput(outputCatcher, errorCatcher)
proc.waitFor()

return [new String(outputCatcher.toByteArray(), encoding), new String(errorCatcher.toByteArray(), encoding)]

}

def out = exec("cp866", "C:\Test", "cmd", ["cd..\n", "dir\n", "exit\n"])

println "OUT:\n" + out[0]
println "ERR:\n" + out[1]
4
répondu emles-kz 2016-09-22 03:31:17