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}"
Foi útil?

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á

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top