我正在使用Scala scala.sys.process
库。
我知道我可以使用!
捕获退出代码,使用!!
捕获输出但是如果我想同时捕获它们呢?
我已经看到了这个看起来很有希望的答案https://stackoverflow.com/a/6013932/416338,但我想知道是否有一个班轮而我错过了什么。
答案 0 :(得分:24)
我有以下实用程序方法来运行命令:
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)
}
如您所见,它捕获了stdout,stderr和结果代码。
答案 1 :(得分:20)
您可以使用ProcessIO
。我在Specs2测试中需要类似的东西,我必须根据stdin
(in
和out
上的输入检查退出值以及流程的输出。输入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)
}
}
我认为这可能会对你有所帮助。在示例中,我忽略了来自stderr
的内容。
答案 2 :(得分:12)
您可以指定捕获文本的输出流:
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
答案 3 :(得分:5)
BasicIO或ProcessLogger的单行使用很有吸引力。
scala> val sb = new StringBuffer
sb: StringBuffer =
scala> ("/bin/ls /tmp" run BasicIO(false, sb, None)).exitValue
res0: Int = 0
scala> sb
res1: StringBuffer = ...
或
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 = ...
根据捕获的含义,除非退出代码非零,否则您可能对输出感兴趣。在这种情况下,处理异常。
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
答案 4 :(得分:2)
“Alex Cruise”在您的链接中提供的回复相当简洁,但性能较差。
您可以扩展sys.process.ProcessLogger来管理
var out = List[String]()
var err = List[String]()
内部,使用out.reverse和err.reverse结果的getter。
答案 5 :(得分:0)
这是一个非常简单的Scala包装器,可让您检索stdout,stderr和退出代码。
import scala.sys.process._
case class ProcessInfo(stdout: String, stderr: String, exitCode: Int)
object CommandRunner {
def runCommandAndGetOutput(command: String): ProcessInfo = {
val stdout = new StringBuilder
val stderr = new StringBuilder
val status = command ! ProcessLogger(stdout append _, stderr append _)
ProcessInfo(stdout.toString(), stderr.toString(), status)
}
}