scala - significado - señalizacion en edificios residenciales
Proceso Scala-Código estándar de salida y salida de captura (5)
Estoy trabajando con la biblioteca Scala scala.sys.process
.
Sé que puedo capturar el código de salida con !
y la salida con !!
pero ¿y si quiero capturar ambos?
He visto esta respuesta https://stackoverflow.com/a/6013932/416338 que parece prometedora, pero me pregunto si hay un trazador de líneas y me falta algo.
El uso de una sola línea de BasicIO o ProcessLogger es atractivo.
scala> val sb = new StringBuffer
sb: StringBuffer =
scala> ("/bin/ls /tmp" run BasicIO(false, sb, None)).exitValue
res0: Int = 0
scala> sb
res1: StringBuffer = ...
o
scala> import collection.mutable.ListBuffer
import collection.mutable.ListBuffer
scala> val b = ListBuffer[String]()
b: scala.collection.mutable.ListBuffer[String] = ListBuffer()
scala> ("/bin/ls /tmp" run ProcessLogger(b append _)).exitValue
res4: Int = 0
scala> b mkString "/n"
res5: String = ...
Dependiendo de lo que quiera decir con captura, quizás le interese la salida a menos que el código de salida sea distinto de cero. En ese caso, maneje la excepción.
scala> val re = "Nonzero exit value: (//d+)".r.unanchored
re: scala.util.matching.UnanchoredRegex = Nonzero exit value: (/d+)
scala> Try ("./bomb.sh" !!) match {
| case Failure(f) => f.getMessage match {
| case re(x) => println(s"Bad exit $x")
| }
| case Success(s) => println(s)
| }
warning: there were 1 feature warning(s); re-run with -feature for details
Bad exit 3
La respuesta proporcionada por ''Alex Cruise'' en su enlace es bastante concisa, salvo que el rendimiento sea más bajo.
Puede extender sys.process.ProcessLogger para administrar el
var out = List[String]()
var err = List[String]()
internamente, con getters para los resultados out.reverse y err.reverse.
Puede especificar una secuencia de salida que capte el texto:
import sys.process._
val os = new java.io.ByteArrayOutputStream
val code = ("volname" #> os).!
os.close()
val opt = if (code == 0) Some(os.toString("UTF-8")) else None
Puedes usar ProcessIO
. Necesitaba algo así en una Prueba de Specs2, donde tuve que verificar el valor de salida y la salida de un proceso dependiendo de la entrada en stdin
( stdin
y out
son de tipo String
):
"the operation" should {
f"return ''$out'' on input ''$in''" in {
var res = ""
val io = new ProcessIO(
stdin => { stdin.write(in.getBytes)
stdin.close() },
stdout => { res = convertStreamToString(stdout)
stdout.close() },
stderr => { stderr.close() })
val proc = f"$operation $file".run(io)
proc.exitValue() must be_==(0)
res must be_==(out)
}
}
Pensé que eso podría ayudarte. En el ejemplo, ignoro lo que viene de stderr
.
Tengo el siguiente método de utilidad para ejecutar comandos:
import sys.process._
def runCommand(cmd: Seq[String]): (Int, String, String) = {
val stdoutStream = new ByteArrayOutputStream
val stderrStream = new ByteArrayOutputStream
val stdoutWriter = new PrintWriter(stdoutStream)
val stderrWriter = new PrintWriter(stderrStream)
val exitValue = cmd.!(ProcessLogger(stdoutWriter.println, stderrWriter.println))
stdoutWriter.close()
stderrWriter.close()
(exitValue, stdoutStream.toString, stderrStream.toString)
}
Como puede ver, captura stdout, stderr y código de resultado.