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}"
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
"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()
// 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()
}
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 ).
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.
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]
command = "ls *"
def execute_state=sh(returnStdout: true, script: command)
mais si la commande échoue, le processus se termine