Pergunta
Groovy adiciona o método execute
para String
para fazer executar conchas bastante fácil;
println "ls".execute().text
mas se um erro acontece, então não há saída resultante. Existe uma maneira fácil de obter tanto o erro padrão e fora padrão (que não seja a criação de um monte de código para;? Criar dois tópicos para ler ambos os InputStreams, em seguida, usando um fluxo de pai para esperar por eles para completar em seguida, converter as cordas voltar ao texto?)
Seria bom ter algo como;
def x = shellDo("ls /tmp/NoFile")
println "out: ${x.out} err:${x.err}"
Solução
Ok, resolvido isso sozinho;
def sout = new StringBuilder(), serr = new StringBuilder()
def proc = 'ls /badDir'.execute()
proc.consumeProcessOutput(sout, serr)
proc.waitForOrKill(1000)
println "out> $sout err> $serr"
exibe:
out> err> ls: cannot access /badDir: No such file or directory
Outras dicas
"ls".execute()
retorna um objeto Process
é por isso que obras "ls".execute().text
. Você deve ser capaz de apenas ler o fluxo de erro para determinar se houve algum erro.
Existe um método extra em Process
que lhe permitem passar um StringBuffer
para recuperar o texto:. consumeProcessErrorStream(StringBuffer error)
Exemplo:
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()
}
Para adicionar uma informação mais importante acima de respostas fornecidas -
Para um processo
def proc = command.execute();
sempre tentar usar
def outputStream = new StringBuffer();
proc.waitForProcessOutput(outputStream, System.err)
//proc.waitForProcessOutput(System.out, System.err)
em vez de
def output = proc.in.text;
para capturar as saídas depois de executar comandos em Groovy como o último é uma chamada de bloqueio ( SO pergunta para a razão ).
Eu acho isso mais idiomática:
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"
Como outro post menciona, estes estão bloqueando chamadas, mas desde que nós queremos trabalhar com a saída, isso pode ser necessário.
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)
mas se a falha de comando do processo terminará