Scala 2.9的“scala.sys.process”如何工作?

时间:2011-05-16 05:14:07

标签: scala

我刚刚查看了新的scala.sysscala.sys.process软件包,看看这里是否有帮助。但是,我完全失去了。

有没有人举例说明如何实际启动流程?

而且,对我来说最有趣的是:你能分离过程吗?

父进程结束时,分离进程将继续运行,并且是Ant的弱点之一。

更新

分离是什么似乎有些混乱。从我当前的项目中获得真实的实例。一次使用z-Shell,一次使用TakeCommand:

Z-外壳:

if ! ztcp localhost 5554; then
    echo "[ZSH] Start emulator"
    emulator                        \
    -avd    Nexus-One               \
    -no-boot-anim                   \
    1>~/Library/Logs/${PROJECT_NAME}-${0:t:r}.out   \
    2>~/Library/Logs/${PROJECT_NAME}-${0:t:r}.err   &
    disown
else
    ztcp -c "${REPLY}"
fi;

收命令:

IFF %@Connect[localhost 5554] lt 0 THEN
   ECHO [TCC] Start emulator
   DETACH emulator -avd Nexus-One -no-boot-anim
ENDIFF

在这两种情况下都是火灾和忘记,模拟器已启动并且即使在脚本结束后也将继续运行。当然,必须两次编写脚本是浪费。所以我现在考虑使用Scala进行统一的进程处理,而不使用cygwin或xml语法。

7 个答案:

答案 0 :(得分:76)

首先导入:

import scala.sys.process.Process

然后创建一个ProcessBuilder

val pb = Process("""ipconfig.exe""")

然后你有两个选择:

  1. 运行并阻止,直到进程退出

    val exitCode = pb.!
    
  2. 在后台运行该进程(已分离)并获取Process实例

    val p = pb.run
    

    然后你可以从进程中获取exitcode(如果进程仍在运行,则阻塞直到它退出)

    val exitCode = p.exitValue
    
  3. 如果您想处理流程的输入和输出,可以使用ProcessIO

    import scala.sys.process.ProcessIO
    val pio = new ProcessIO(_ => (),
                            stdout => scala.io.Source.fromInputStream(stdout)
                              .getLines.foreach(println),
                            _ => ())
    pb.run(pio)
    

答案 1 :(得分:24)

我非常确定分离进程工作得很好,考虑到你必须明确等待它退出,你需要使用线程来管理stdout和stderr。这是非常基本的,但这是我一直在使用的:

/** Run a command, collecting the stdout, stderr and exit status */
def run(in: String): (List[String], List[String], Int) = {
  val qb = Process(in)
  var out = List[String]()
  var err = List[String]()

  val exit = qb ! ProcessLogger((s) => out ::= s, (s) => err ::= s)

  (out.reverse, err.reverse, exit)
}

答案 2 :(得分:8)

流程从SBT导入。以下是有关如何使用SBT 中显示的流程库的详尽指南。

https://github.com/harrah/xsbt/wiki/Process

答案 3 :(得分:7)

  

有没有人得到如何做的例子   实际上是开始一个过程吗?

import sys.process._ // Package object with implicits!
"ls"!
  

而且,这对我来说最有趣:   你可以分离流程吗?

"/path/to/script.sh".run()

你要做的大部分工作都与sys.process.ProcessBuilder有关。了解这一点。

有些含义使得使用更简洁,并且可以通过包对象sys.process获得。导入其内容,如示例中所示。另外,看看它的scaladoc。

答案 4 :(得分:6)

以下功能将允许在此处使用文档:

def #<<< (command: String) (hereDoc: String) =
{
    val process = Process (command)
    val io = new ProcessIO (
        in  => {in.write (hereDoc getBytes "UTF-8"); in.close},
        out => {scala.io.Source.fromInputStream(out).getLines.foreach(println)},
        err => {scala.io.Source.fromInputStream(err).getLines.foreach(println)})
    process run io
}

可悲的是,我无法(没时间)将其作为中缀操作。因此,建议的召集惯例是:

#<<< ("command") {"""
Here Document data
"""}

如果有人能给我一个关于如何让它变得更像shell的暗示,那将是一个电话:

"command" #<<< """
Here Document data
""" !

答案 5 :(得分:3)

记录过程好一点,在我的名单上排名第二,大概两个月。你可以从我从未得到它的事实推断我的列表。不像我不做的大多数事情,这是我说过我会做的事情,所以我非常遗憾它仍然没有像它到达时那样无证。剑,准备好了!我落在你身上!

答案 6 :(得分:2)

如果我理解对话框到目前为止,原始问题的一个方面尚未得到解答:

  1. 如何“分离”生成的进程,使其继续独立于父scala脚本运行
  2. 主要的困难是产生进程所涉及的所有类必须在JVM上运行,并且当JVM退出时它们不可避免地被终止。但是,解决方法是通过利用shell代表您进行“分离”来间接实现目标。以下用于启动gvim编辑器的scala脚本似乎可以正常工作:

    val cmd = List(
       "scala",
       "-e",
       """import scala.sys.process._ ; "gvim".run ; System.exit(0);"""
    )
    val proc = cmd.run
    

    它假设scala在PATH中,并且(不可避免地)确实会使JVM父进程运行。