Domanda
Groovy aggiunge il metodo execute
a String
per rendere l'esecuzione delle shell abbastanza semplice;
println "ls".execute().text
ma se si verifica un errore, non viene generato alcun risultato. Esiste un modo semplice per ottenere sia l'errore standard sia lo standard? (oltre a creare un gruppo di codice per; creare due thread per leggere entrambi i flussi di input, quindi utilizzare un flusso padre per attendere che completa quindi riconvertire le stringhe in testo?)
Sarebbe bello avere qualcosa del genere;
def x = shellDo("ls /tmp/NoFile")
println "out: ${x.out} err:${x.err}"
Soluzione
Ok, l'ho risolto da solo;
def sout = new StringBuilder(), serr = new StringBuilder()
def proc = 'ls /badDir'.execute()
proc.consumeProcessOutput(sout, serr)
proc.waitForOrKill(1000)
println "out> $sout err> $serr"
display:
out > errare > ls: impossibile accedere a / badDir: nessun file o directory
Altri suggerimenti
" ls " .execute ()
restituisce un oggetto Process
, motivo per cui " ls " .execute (). text
funziona . Dovresti essere in grado di leggere il flusso di errori per determinare se si sono verificati errori.
Esiste un metodo aggiuntivo su Process
che consente di passare un StringBuffer
per recuperare il testo: consumeProcessErrorStream (errore StringBuffer)
.
Esempio:
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()
}
Per aggiungere un'altra informazione importante alle risposte fornite sopra -
Per un processo
def proc = command.execute();
prova sempre a usare
def outputStream = new StringBuffer();
proc.waitForProcessOutput(outputStream, System.err)
//proc.waitForProcessOutput(System.out, System.err)
anziché
def output = proc.in.text;
catturare gli output dopo aver eseguito i comandi in groovy poiché quest'ultimo è una chiamata bloccante ( SO domanda per ragione ).
Lo trovo più idiomatico:
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"
Come menziona un altro post, si tratta di bloccare le chiamate, ma poiché vogliamo lavorare con l'output, questo potrebbe essere necessario.
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)
ma se il comando fallisce il processo verrà terminato