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