ProcessBuilder 没有问题(至少不是源于您的用例)。来自ProcessBuilder documentation:
启动进程
要执行与 ProcessBuilder 相关的所有外部命令,可以使用四组方法之一。这些方法中的每一种都具有各种重载和变化,以实现对 I/O 的进一步控制。这些方法是:
- run:最通用的方法,立即返回一个scala.sys.process.Process,外部命令并发执行。
- !:阻塞直到所有外部命令退出,并返回执行链中最后一个的退出代码。
- !!:阻塞,直到所有外部命令退出,并返回一个带有生成输出的字符串。
- lineStream:像run一样立即返回,生成的输出通过Stream[String]提供。 获取该 Stream 的下一个元素可能会阻塞,直到它可用为止。如果返回码不为零,此方法将引发异常——如果不需要,请使用 lineStream_!方法。
文档明确指出lineStream 可能会阻塞,直到下一行可用。由于tail -f 的本质是无限行lineBreak,程序将阻塞等待下一行出现。
对于以下假设我有一个文件:/Users/user/tmp/sample.txt,它的内容是:
boom
bar
cat
为什么lineStream_! 没有错
import scala.language.postfixOps
import scala.sys.process._
object ProcessBuilder extends App {
val myStream: Stream[String] = ("tail /Users/user/tmp/sample.txt" lineStream_!)
println("I'm after tail!")
myStream.filter(_ != null).foreach(println)
println("Finished")
System.exit(0)
}
输出:
I'm after tail!
boom
bar
cat
Finished
所以您看到lineStream_! 立即返回。因为命令的性质是有限的。
如何从产生无限输出的命令中立即返回:
让我们用tail -f 试试这个。您需要对流程进行更多控制。同样,正如文档所述:
如果希望完全控制输入和输出,那么 scala.sys.process.ProcessIO 可以与 run 一起使用。
举个例子:
import java.io.{BufferedReader, InputStreamReader}
import scala.language.postfixOps
import scala.sys.process._
object ProcessBuilder extends App {
var reader: BufferedReader = _
try {
var myStream: Stream[String] = Stream.empty
val processIO = new ProcessIO(
(os: java.io.OutputStream) => ??? /* Send things to the process here */,
(in: java.io.InputStream) => {
reader = new BufferedReader(new InputStreamReader(in))
myStream = Stream.continually(reader.readLine()).takeWhile(_ != "ff")
},
(in: java.io.InputStream) => ???,
true
)
"tail -f /Users/user/tmp/sample.txt".run(processIO)
println("I'm after the tail command...")
Thread.sleep(2000)
println("Such computation performed while tail was active!")
Thread.sleep(2000)
println("Such computation performed while tail was active again!")
println(
s"Captured these lines while computing: ${myStream.print(System.lineSeparator())}")
Thread.sleep(2000)
println("Another computation!")
} finally {
Option(reader).foreach(_.close())
}
println("Finished")
System.exit(0)
}
输出:
I'm after the tail command...
Such computation performed while tail was active!
Such computation performed while tail was active again!
boom
bar
cat
它仍然会立即返回,现在它只是挂在那里等待更多输入。如果我从tmp 目录执行echo 'fff' >> sample.txt,程序输出:
Another computation!
Finished
您现在可以在发出tail -f 命令后执行您想要的任何计算,并且可以根据您传递给takeWhile 方法(或关闭输入流的其他方法)的条件来终止它。
有关ProcessIO 的更多详细信息,请查看documentation here。