如何发出产生无限输出并立即返回的命令 [英] How to issue a command that produces infinite output and return immediately

查看:66
本文介绍了如何发出产生无限输出并立即返回的命令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我编写以下代码时(用菊石但我认为这无关紧要)

When I write the following code (in ammonite but i don't think it matters)

("tail -f toTail.txt" lineStream) foreach(println(_)),程序按预期给我最后一行但随后挂起,即使我在文件,什么都没有出来.

("tail -f toTail.txt" lineStream) foreach(println(_)), the program give me the last line as intend but then hang, and even if i write more in the file, nothing come out.

API如何支持无界输出的进程?

How does the API support process that have unbounded output ?

我试着写 val myStream = ("tail -f toTail.txt" lineStream_!)但它仍然不返回写掉

I try to write val myStream = ("tail -f toTail.txt" lineStream_!) but it still does not return write away

这是 Scala 文档所说的:

Here is what the scala doc says:

lineStream:像 run 一样立即返回,生成的输出通过 Stream[String] 提供.获取该 Stream 的下一个元素可能会阻塞,直到它变得可用.

lineStream: returns immediately like run, and the output being generated is provided through a Stream[String]. Getting the next element of that Stream may block until it becomes available.

因此我不明白为什么它会阻塞

Hence i don't understand why it blocks

顺便说一下,我与 Ammonite API 的行为完全相同

By the way i am having exactly the same behavior with the Ammonite API

如果再次输入 %%("tail", "-f", "toTail.txt") 方法只是挂起并且不会立即返回.

If type %%("tail", "-f", "toTail.txt") once again the method just hang and does not return immediately.

推荐答案

ProcessBuilder 没有问题(至少不是源于您的用例的问题).来自 ProcessBuilder 文档:

There is no issue with the ProcessBuilder (at least not one that stems from your use case). From the ProcessBuilder documentation:

启动进程

要执行与 ProcessBuilder 关联的所有外部命令,可以使用四组方法之一.这些方法中的每一种都有各种重载和变体,以便进一步控制 I/O.这些方法是:

To execute all external commands associated with a ProcessBuilder, one may use one of four groups of methods. Each of these methods have various overloads and variations to enable further control over the I/O. These methods are:

  • run:最通用的方法,它立即返回一个scala.sys.process.Process,外部命令并发执行.
  • !:阻塞直到所有外部命令退出,并返回执行链中最后一个的退出代码.
  • !!:阻塞直到所有外部命令退出,并返回一个带有生成输出的字符串.
  • lineStream:像 run 一样立即返回,生成的输出通过 Stream[String] 提供.获取该流的下一个元素可能会阻塞,直到它变得可用.如果返回码不为零,则此方法将引发异常——如果不需要,请使用 lineStream_!方法.
  • run: the most general method, it returns a scala.sys.process.Process immediately, and the external command executes concurrently.
  • !: blocks until all external commands exit, and returns the exit code of the last one in the chain of execution.
  • !!: blocks until all external commands exit, and returns a String with the output generated.
  • lineStream: returns immediately like run, and the output being generated is provided through a Stream[String]. Getting the next element of that Stream may block until it becomes available. This method will throw an exception if the return code is different than zero -- if this is not desired, use the lineStream_! method.

文档明确指出 lineStream 可能会阻塞,直到下一行可用.由于 tail -f 的性质是无限的行 lineBreak 程序将阻塞等待下一行出现.

The documentation clearly states that lineStream might block until the next line becomes available. Since the nature of tail -f is an infinite stream of lines lineBreak the program will block waiting for the next line to appear.

以下假设我有一个文件:/Users/user/tmp/sample.txt,它的内容是:

For the following assume I have a file: /Users/user/tmp/sample.txt and it's contents are:

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_! 立即返回.因为命令的性质是有限的.

So you see that the lineStream_! returned immediately. Because the nature of the command is finite.

让我们用 tail -f 试试这个.您需要对流程进行更多控制.同样,正如文档所述:

Let's try this with tail -f. You need more control over your process. Again, as the documentation states:

如果希望完全控制输入和输出,则可以将 scala.sys.process.ProcessIO 与 run 一起使用.

If one desires full control over input and output, then a scala.sys.process.ProcessIO can be used with 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' >>tmp目录下的sample.txt,程序输出:

It still returns immediately and now it just hangs there waiting for more input. If I do echo 'fff' >> sample.txt from the tmp directory, the program outputs:

Another computation!
Finished

您现在可以在发出 tail -f 命令后执行任何您想要的计算,并且可以根据您传递给 takeWhile 的条件终止它方法(或其他关闭输入流的方法).

You now have the power to perform any computation you want after issuing a tail -f command and the power to terminate it depending on the condition you pass to the takeWhile method (or other methods that close the input stream).

有关 ProcessIO 的更多详细信息,请查看 此处的文档.

For more details on ProcessIO check the documentation here.

这篇关于如何发出产生无限输出并立即返回的命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆