web-dev-qa-db-fra.com

Groovy exécute des commandes Shell

Groovy ajoute la méthode execute à String pour faciliter l’exécution de shells;

println "ls".execute().text

mais si une erreur se produit, alors il n'y a pas de sortie résultante. Existe-t-il un moyen simple d’obtenir à la fois l’erreur standard et l’erreur standard? (sauf créer un tas de code pour; créer deux threads pour lire les deux flux d’entrée, puis utiliser un flux parent pour les attendre compléter puis reconvertir les chaînes en texte?)

Ce serait bien d'avoir quelque chose comme;

 def x = shellDo("ls /tmp/NoFile")
 println "out: ${x.out} err:${x.err}"
147
Bob Herrmann

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

163
Bob Herrmann

"ls".execute() renvoie un objet Process, raison pour laquelle "ls".execute().text fonctionne. Vous devriez pouvoir simplement lire le flux d’erreurs pour déterminer s’il ya eu des erreurs.

Il existe 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()
39
Joshua
// 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()
}
27
mholm815

Pour ajouter une autre information importante aux réponses ci-dessus -

Pour un processus

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;

capturer les sorties après exécution de commandes en groovy car ce dernier est un appel bloquant ( question SO pour raison ).

19
Aniket Thakur

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 une autre publication, il s’agit d’appels bloquants, mais comme nous souhaitons utiliser la sortie, cela peut être nécessaire.

15
solstice333
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]
5
emles-kz
command = "ls *"

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

mais si la commande échoue, le processus se termine

0
舒何伟