Как работает «scala.sys.process» из Scala 2.9? - PullRequest
59 голосов
/ 16 мая 2011

Я только что посмотрел на новые пакеты scala.sys и scala.sys.process, чтобы узнать, есть ли здесь что-то полезное.Тем не менее, я в полной растерянности.

Кто-нибудь получил пример того, как на самом деле запустить процесс?

И, что для меня наиболее интересно: Можете ли вы отключить процессы?

Отдельный процесс будет продолжать выполняться после завершения родительского процесса и является одним из слабых мест Ant.

ОБНОВЛЕНИЕ:

Кажется, чтонекоторая путаница, что такое отделение.Есть реальный живой пример из моего текущего проекта.Один раз с z-Shell и один раз с TakeCommand:

Z-Shell:

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 ]

76 голосов
/ 16 мая 2011

Первый импорт:

import scala.sys.process.Process

, затем создайте ProcessBuilder

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

Тогда у вас есть два варианта:

  1. запустить и заблокировать допроцесс завершается

    val exitCode = pb.!
    
  2. запустить процесс в фоновом режиме (отсоединен) и получить Process экземпляр

    val p = pb.run
    

    Затем вы можете получить код выхода изпроцесс с (если процесс все еще выполняется, он блокируется до его завершения)

    val exitCode = p.exitValue
    

Если вы хотите обрабатывать ввод и вывод процесса, вы можете использовать ProcessIO:

import scala.sys.process.ProcessIO
val pio = new ProcessIO(_ => (),
                        stdout => scala.io.Source.fromInputStream(stdout)
                          .getLines.foreach(println),
                        _ => ())
pb.run(pio)
24 голосов
/ 16 мая 2011

Я почти уверен, что отдельные процессы работают просто отлично, учитывая, что вам нужно явно ждать, пока он завершится, и вам нужно использовать потоки, чтобы присматривать за 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)
}
8 голосов
/ 16 мая 2011

Процесс был импортирован из SBT.Вот подробное руководство по использованию библиотеки процессов в том виде, в каком она отображается в SBT .

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

7 голосов
/ 16 мая 2011

У кого-нибудь есть пример того, как на самом деле запустить процесс?

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

И что для меня наиболее интересно: можете ли вы отключить процессы?

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

Большая часть того, что вы будете делать, связана с sys.process.ProcessBuilder, чертой.Познакомьтесь с этим.

Существуют последствия, которые делают использование менее многословным, и они доступны через объект пакета sys.process.Импортируйте его содержимое, как показано в примерах.Также взгляните на его скаладок.

6 голосов
/ 18 мая 2011

Следующая функция позволит легко использовать здесь документы:

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
"""}

Был бы вызов, если бы кто-нибудь дал мне подсказку, как сделать его более похожим на оболочку:

"command" #<<< """
Here Document data
""" !
3 голосов
/ 17 мая 2011

Процесс документирования немного лучше был вторым в моем списке, вероятно, два месяца.Вы можете вывести мой список из того факта, что я никогда не попал в него.В отличие от большинства вещей, которые я не делаю, я бы сказал, что именно это я и сделаю, поэтому я очень сожалею, что он остается таким же недокументированным, каким он был, когда прибыл.Меч, готовь себя!Я падаю на тебя!

2 голосов
/ 29 ноября 2011

Если я до сих пор понимаю диалог, то один аспект исходного вопроса еще не получен:

  1. как «отсоединить» порожденный процесс, чтобы он продолжал выполняться независимо от родительского скрипта scala

Основная трудность заключается в том, что все классы, участвующие в порождении процесса, должны выполняться на JVM, и они неизбежно завершаются при выходе из JVM.Однако обходной путь заключается в косвенном достижении цели путем использования оболочки для «отсоединения» от вашего имени.Следующий скрипт scala, который запускает редактор gvim, похоже, работает как нужно:

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

Предполагается, что scala находится в PATH, и он (неизбежно) также оставляет выполнение родительского процесса JVM.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...