ProcessBuilder 没有问题(至少不是源于您的用例)。从ProcessBuilder 文档:
启动进程
要执行与 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
它仍然会立即返回,现在它只是挂在那里等待更多输入。如果我echo 'fff' >> sample.txt
从tmp
目录中执行,程序输出:
Another computation!
Finished
现在,您可以在发出tail -f
命令后执行您想要的任何计算,并且可以根据您传递给takeWhile
方法(或关闭输入流的其他方法)的条件来终止它。
有关在此处ProcessIO
查看文档的更多详细信息。