Pregunta

Groovy agrega el método execute a String para hacer que la ejecución de shells sea bastante fácil;

println "ls".execute().text

pero si ocurre un error, entonces no hay salida resultante. ¿Hay una manera fácil de eliminar tanto el error estándar como el estándar? (aparte de crear un montón de código para crear dos hilos para leer ambas secuencias de entrada y luego usar una ruta principal para esperar a que completa y luego convierte las cadenas de nuevo a texto?)

Sería bueno tener algo como;

 def x = shellDo("ls /tmp/NoFile")
 println "out: ${x.out} err:${x.err}"
¿Fue útil?

Solución

Ok, lo resolví yo mismo;

def sout = new StringBuilder(), serr = new StringBuilder()
def proc = 'ls /badDir'.execute()
proc.consumeProcessOutput(sout, serr)
proc.waitForOrKill(1000)
println "out> $sout err> $serr"

muestra:

fuera > err > ls: no se puede acceder a / badDir: no existe tal archivo o directorio

Otros consejos

" ls " .execute () devuelve un objeto Process , por lo que " ls " .execute (). text funciona . Debería poder leer la secuencia de errores para determinar si hubo errores.

Hay un método adicional en Process que le permite pasar un StringBuffer para recuperar el texto: consumeProcessErrorStream (error de StringBuffer) .

Ejemplo:

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 agregar una información más importante a las respuestas proporcionadas anteriormente -

Para un proceso

def proc = command.execute();

siempre trate de usar

def outputStream = new StringBuffer();
proc.waitForProcessOutput(outputStream, System.err)
//proc.waitForProcessOutput(System.out, System.err)

en lugar de

def output = proc.in.text;

para capturar las salidas después de ejecutar comandos en groovy ya que esta última es una llamada de bloqueo ( SO question for reason ).

Me parece más idiomático:

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 menciona otra publicación, estas son llamadas de bloqueo, pero dado que queremos trabajar con la salida, esto puede ser necesario.

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)

pero si el comando falla, el proceso terminará

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top