Scala - 当外部进程退出时获得回调 [英] Scala - getting a callback when an external process exits

查看:46
本文介绍了Scala - 当外部进程退出时获得回调的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用 Scala 替换我的很多 perl.我经常做的一件事是调用由我公司其他团队提供给我的二进制文件(通常是编译的 C++,但也可能是 java、其他 perl 脚本、q 脚本等).

I'm looking to replace a lot of my perl with scala. One of the things I tend to do a lot is call binaries (usually compiled C++, but could be java, other perl scripts, q scripts, etc) provided to me by other teams at my company.

例如,要进行一些复杂的数学运算,我会启动一个外部二进制文件,然后将我的输入通过管道传输到它.然后我会监听它的 stdout 流以获取结果,并监听 stderr 流以获取诊断消息.在 perl 中,我会使用 POE::Wheel::Run 小部件来执行此操作.我在 Scala 中提出了类似的(而且更好)的东西,但我想让它更健壮.它是对 ProcessIO 对象的一个​​小包装.它看起来像这样:

For example, to do some complex math, I'd start one of the foreign binaries, then pipe my inputs to it. I'd then listen to its stdout stream for results, and stderr stream for diagnostic messages. In perl, I'd do this using a POE::Wheel::Run widget. I've come up with something analogous (and much nicer) in scala, but I'd like to make it more robust. It's a little wrapper around a ProcessIO object. It looks like this:

class Exe(command: String, out: String => Unit, err: String => Unit) {

    import scala.sys.process._
    import scala.io._
    import java.io._
    import scala.concurrent._

    val inputStream = new SyncVar[OutputStream];

    val process = Process(command).run(
        new ProcessIO(
            stdin => inputStream.put(stdin),
            stdout => Source.fromInputStream(stdout).getLines.foreach(out),
            stderr => Source.fromInputStream(stderr).getLines.foreach(err)));

    def write(s: String): Unit = synchronized {
        inputStream.get.write((s + "\n").getBytes)
    }

    def close(): Unit = {
        inputStream.get.close
    }
}

然后我会像这样使用它:

I'd then use it like this:

val exe = new Exe("tr [a-z] [A-Z]", 
                  out => println("o: " + out), 
                  err => println("e: " + err))
exe.write("lower")
exe.close()

打印出来的:

o: LOWER

这让我获得了 90% 的时间,但是在进程退出时获得回调会更好.它可能退出是因为我已经关闭了输入流并且它的内部循环停止了,它可能会自行退出,或者它可能因为我已经杀死了它而退出.在回调中,最好知道它为什么停止以及退出代码.

This gets me 90% there, but what would be nice would be to get a callback when the process exits. It may exit because I've closed the input stream and its internal loop stops, it may exit on its own, or it may exit because I've killed it. In the callback, it would be good to know why it stopped, and the exit code.

我对如何解决这个问题有点茫然,任何帮助将不胜感激(当然,欢迎对上述代码进行任何编辑 - 我有点菜鸟).

I'm at a bit of a loss as to how to go about this, any help would be appreciated (and any edits to the above code are, of course, welcome - I'm a bit of a noob).

我使用的是 2.9.0.1

I'm using 2.9.0.1

推荐答案

您可以等待调用 exitValue 的进程结束.您可以在一个单独的线程中执行此操作,在该线程中将发生回调.也许 Process 类可能会被这样拉皮条:

You can wait for the end of a process calling exitValue. You might do that in a separate thread, in which the callback will happen. Maybe class Process could be pimped thus:

import scala.concurrent.ops.spawn
implicit def ProcessWithCallback(p: Process) {
  def whenTerminatedDo(callback: Int => Unit) = spawn{
    val exitValue = p.exitValue; callback(p)
  }
}

然后您可以根据需要在 Exe 中使用它.

You could then use that in Exe as you like.

JVM 给定的Process 类被scala.sys.Process 包裹着,确实很实用,很难不阻塞线程

The Process class given by the JVM and wrapped by scala.sys.Process is really rather feable, it will be hard not to block a thread

这篇关于Scala - 当外部进程退出时获得回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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