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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6013415/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 03:00:49  来源:igfitidea点击:

How does the “scala.sys.process” from Scala 2.9 work?

scala

提问by Martin

I just had a look at the new scala.sysand scala.sys.processpackages to see if there is something helpful here. However, I am at a complete loss.

我刚刚查看了 newscala.sysscala.sys.processpackage,看看这里是否有一些有用的东西。然而,我完全不知所措。

Has anybody got an example on how to actually start a process?

有没有人有关于如何实际启动流程的示例?

And, which is most interesting for me: Can you detach processes?

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

A detached process will continue to run when the parent process ends and is one of the weak spots of Ant.

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

UPDATE:

更新:

There seem to be some confusion what detach is. Have a real live example from my current project. Once with z-Shell and once with TakeCommand:

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

Z-Shell:

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;

Take-Command:

采取命令:

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

In both cases it is fire and forget, the emulator is started and will continue to run even after the script has ended. Of course having to write the scripts twice is a waste. So I look into Scala now for unified process handling without cygwin or xml syntax.

在这两种情况下,它都是一劳永逸的,模拟器会启动,即使在脚本结束后也会继续运行。当然,必须编写两次脚本是一种浪费。所以我现在研究 Scala 以进行统一的流程处理,而无需 cygwin 或 xml 语法。

回答by michael.kebe

First import:

第一次导入:

import scala.sys.process.Process

then create a ProcessBuilder

然后创建一个 ProcessBuilder

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

Then you have two options:

那么你有两个选择:

  1. run and block until the process exits

    val exitCode = pb.!
    
  2. run the process in background (detached) and get a Processinstance

    val p = pb.run
    

    Then you can get the exitcode from the process with (If the process is still running it blocks until it exits)

    val exitCode = p.exitValue
    
  1. 运行并阻塞直到进程退出

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

    val p = pb.run
    

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

    val exitCode = p.exitValue
    

If you want to handle the input and output of the process you can use ProcessIO:

如果要处理流程的输入和输出,可以使用ProcessIO

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

回答by Alex Cruise

I'm pretty sure detached processes work just fine, considering that you have to explicitly wait for it to exit, and you need to use threads to babysit the stdout and stderr. This is pretty basic, but it's what I've been using:

我很确定分离的进程工作得很好,考虑到您必须明确等待它退出,并且您需要使用线程来照顾 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)
}

回答by Synesso

Process was imported from SBT. Here's a thorough guide on how to use the process library as it appears in SBT.

工艺是从 SBT 导入的。这是有关如何使用SBT 中出现的流程库的详尽指南。

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

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

回答by Daniel C. Sobral

Has anybody got an example on how to actually start a process?

有没有人有关于如何实际启动流程的示例?

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

And, which is most interesting for me: Can you detach processes?

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

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

Most of what you'll do is related to sys.process.ProcessBuilder, the trait. Get to know that.

你要做的大部分事情都与sys.process.ProcessBuilder特性有关。去了解一下。

There are implicits that make usage less verbose, and they are available through the package object sys.process. Import its contents, like shown in the examples. Also, take a look at its scaladoc as well.

有一些隐式可以使用法不那么冗长,它们可以通过包 object 获得sys.process。导入其内容,如示例中所示。另外,还可以看看它的 scaladoc。

回答by Martin

The following function will allow easy use if here documents:

如果这里记录了以下功能,则可以轻松使用:

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
}

Sadly I was not able to (did not have the time to) to make it an infix operation. Suggested calling convention is therefore:

遗憾的是,我无法(没有时间)使其成为中缀操作。因此,建议的调用约定是:

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

It would be call if anybody could give me a hint on how to make it a more shell like call:

如果有人能给我一个关于如何使它更像电话的提示,那就是电话:

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

回答by psp

Documenting process a little better was second on my list for probably two months. You can infer my list from the fact that I never got to it. Unlike most things I don't do, this is something I said I'd do, so I greatly regret that it remains as undocumented as it was when it arrived. Sword, ready yourself! I fall upon thee!

记录过程稍微好一点在我的列表中排在第二位,可能是两个月。你可以从我从未做过的事实中推断出我的清单。与大多数我不做的事情不同,这是我说过我会做的事情,所以我非常遗憾它仍然像它到达时一样没有记录。剑,准备好自己!我倒在你身上!

回答by PhilW

If I understand the dialog so far, one aspect of the original question is not yet answered:

如果我到目前为止理解了对话,那么原始问题的一个方面还没有得到回答:

  1. how to "detach" a spawned process so it continues to run independently of the parent scala script
  1. 如何“分离”一个生成的进程,以便它继续独立于父 scala 脚本运行

The primary difficulty is that all of the classes involved in spawning a process must run on the JVM, and they are unavoidably terminated when the JVM exits. However, a workaround is to indirectly achieve the goal by leveraging the shell to do the "detach" on your behalf. The following scala script, which launches the gvim editor, appears to work as desired:

主要的困难是所有涉及生成进程的类都必须在 JVM 上运行,并且在 JVM 退出时它们不可避免地被终止。但是,一种解决方法是通过利用 shell 代表您执行“分离”来间接实现目标。以下启动 gvim 编辑器的 Scala 脚本似乎可以正常工作:

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

It assumes that scala is in the PATH, and it does (unavoidably) leave a JVM parent process running as well.

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