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}"
È stato utile?

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top