Spec-Zone.ru › Nim

std/osproc

SourceEdit

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

См. также:

  • модуль os
  • модуль streams
  • модуль memfiles

Импорты

strutils, os, strtabs, streams, cpuinfo, streamwrapper, since, winlean

Типы

Process = ref ProcessObj
Представляет процесс операционной системы. Source Edit
ProcessOption = enum
  poEchoCmd,                ## Echo the command before execution.
  poUsePath, ## Asks system to search for executable using PATH environment
              ## variable.
              ## On Windows, this is the default.
  poEvalCommand, ## Pass `command` directly to the shell, without quoting.
                  ## Use it only if `command` comes from trusted source.
  poStdErrToStdOut,         ## Merge stdout and stderr to the stdout stream.
  poParentStreams,          ## Use the parent's streams.
  poInteractive, ## Optimize the buffer handling for responsiveness for
                  ## UI applications. Currently this only affects
                  ## Windows: Named pipes are used so that you can peek
                  ## at the process' output streams.
  poDaemon                   ## Windows: The program creates no Window.
                             ## Unix: Start the program as a daemon. This is still
                             ## work in progress!
Параметры, которые можно передать процедуре startProcess proc. Source Edit

Процедуры

proc close(p: Process) {....gcsafe, extern: "nosp$1", raises: [IOError, OSError],
                         tags: [WriteIOEffect], forbids: [].}
Когда процесс завершил выполнение, очищает связанные дескрипторы.
Предупреждение: Если процесс не завершил выполнение, это принудительно завершит процесс. Это может привести к появлению процессов-зомби и утечкам pty.
Исходный код Изменить
proc countProcessors(): int {....gcsafe, extern: "nosp$1", raises: [], tags: [],
                              forbids: [].}
Возвращает количество процессоров/ядер в машине. Возвращает 0, если количество не может быть определено. Реализовано с помощью вызова cpuinfo.countProcessors. Исходный код Изменить
proc errorHandle(p: Process): FileHandle {....gcsafe, extern: "nosp$1", raises: [],
    tags: [], forbids: [].}
Возвращает дескриптор файла ошибок p для чтения.
Предупреждение: Возвращённый FileHandle не следует закрывать вручную, так как он закрывается при закрытии процесса p.

См. также:

  • процедура inputHandle
  • процедура outputHandle
Исходный код Изменить
proc errorStream(p: Process): Stream {....gcsafe, extern: "nosp$1", tags: [],
                                       raises: [], forbids: [].}

Возвращает поток ошибок p для чтения.

Вы не можете выполнять операции peek/write/setOption с этим потоком. Используйте процедуру peekableErrorStream, если вам нужно просмотреть поток.

Предупреждение: Возвращённый Stream не следует закрывать вручную, так как он закрывается при закрытии процесса p.

См. также:

  • процедура inputStream
  • процедура outputStream
Исходный код Изменить
proc execCmd(command: string): int {....gcsafe, extern: "nosp$1", tags: [
    ExecIOEffect, ReadIOEffect, RootEffect], raises: [OSError], forbids: [].}

Выполняет command и возвращает его код ошибки.

Стандартные потоки ввода, вывода и ошибок наследуются от вызывающего процесса. Эта операция также часто называется system.

См. также:

  • процедура execCmdEx
  • процедура startProcess
  • процедура execProcess

Пример:

let errC = execCmd("nim c -r mytestfile.nim")
Исходный код Изменить
proc execCmdEx(command: string;
               options: set[ProcessOption] = {poStdErrToStdOut, poUsePath};
               env: StringTableRef = nil; workingDir = ""; input = ""): tuple[
    output: string, exitCode: int] {....raises: [OSError, IOError], tags: [
    ExecIOEffect, ReadIOEffect, RootEffect], gcsafe, forbids: [].}

Удобная процедура для запуска command, и возвращает его output и exitCode. env и workingDir параметры ведут себя аналогично параметрам startProcess. Если input.len > 0, он передаётся как stdin.

Примечание: это может заблокировать выполнение, если input.len превышает максимальный размер буфера канала вашей ОС.

См. также:

  • процедура execCmd
  • процедура startProcess
  • процедура execProcess

Пример:

var result = execCmdEx("nim r --hints:off -", options = {}, input = "echo 3*4")
import std/[strutils, strtabs]
stripLineEnd(result[0]) ## portable way to remove trailing newline, if any
doAssert result == ("12", 0)
doAssert execCmdEx("ls --nonexistent").exitCode != 0
when defined(posix):
  assert execCmdEx("echo $FO", env = newStringTable({"FO": "B"})) == ("B\n", 0)
  assert execCmdEx("echo $PWD", workingDir = "/") == ("/\n", 0)
Исходный код Изменить
proc execProcess(command: string; workingDir: string = "";
                 args: openArray[string] = []; env: StringTableRef = nil;
    options: set[ProcessOption] = {poStdErrToStdOut, poUsePath, poEvalCommand}): string {.
    ...gcsafe, extern: "nosp$1", raises: [OSError, IOError],
    tags: [ExecIOEffect, ReadIOEffect, RootEffect], forbids: [].}
Удобная процедура, которая выполняет command с startProcess и возвращает её вывод как строку.
Предупреждение: Эта функция по умолчанию использует poEvalCommand для обеспечения обратной совместимости. Убедитесь, что явно передаёте опции.

См. также:

  • процедура startProcess
  • процедура execProcesses
  • процедура execCmd

Пример:

let outp = execProcess("nim", args=["c", "-r", "mytestfile.nim"], options={poUsePath})
let outp_shell = execProcess("nim c -r mytestfile.nim")
# Note: outp may have an interleave of text from the nim compile
# and any output from mytestfile when it runs
Исходный код Изменить
proc execProcesses(cmds: openArray[string];
                   options = {poStdErrToStdOut, poParentStreams};
                   n = countProcessors(); beforeRunEvent: proc (idx: int) = nil;
                   afterRunEvent: proc (idx: int; p: Process) = nil): int {.
    ...gcsafe, extern: "nosp$1", raises: [ValueError, OSError, IOError],
    tags: [ExecIOEffect, TimeEffect, ReadEnvEffect, RootEffect],
    effectsOf: [beforeRunEvent, afterRunEvent], ...forbids: [].}

Выполняет команды cmds параллельно. Создаёт n процессов, которые выполняются параллельно.

Возвращает наибольшее (по модулю) возвращаемое значение всех процессов. Выполняет beforeRunEvent перед запуском каждой команды.

Исходный код Изменить
proc hasData(p: Process): bool {....raises: [], tags: [], forbids: [].}
Исходный код Изменить
proc inputHandle(p: Process): FileHandle {....gcsafe, raises: [], extern: "nosp$1",
    tags: [], forbids: [].}
Возвращает дескриптор файла ввода p для записи.
Предупреждение: Возвращённый FileHandle не следует закрывать вручную, так как он закрывается при закрытии процесса p.

См. также:

  • процедура outputHandle
  • процедура errorHandle
Исходный код Изменить
proc inputStream(p: Process): Stream {....gcsafe, extern: "nosp$1", tags: [],
                                       raises: [], forbids: [].}
Возвращает поток ввода p для записи.
Предупреждение: Возвращённый Stream не следует закрывать вручную, так как он закрывается при закрытии процесса p.

См. также:

  • процедура outputStream
  • процедура errorStream
Исходный код Изменить
proc kill(p: Process) {....gcsafe, extern: "nosp$1", tags: [], raises: [OSError],
                        forbids: [].}

Завершает процесс p.

На операционных системах Posix процедура отправляет SIGKILL процессу. На Windows kill является просто псевдонимом для terminate().

См. также:

  • процедура suspend
  • процедура resume
  • процедура terminate
  • posix_utils.sendSignal(pid: Pid, signal: int)
Исходный код Изменить
proc outputHandle(p: Process): FileHandle {....gcsafe, extern: "nosp$1",
    raises: [], tags: [], forbids: [].}
Возвращает дескриптор файла вывода p для чтения.
Предупреждение: Возвращённый FileHandle не следует закрывать вручную, так как он закрывается при закрытии процесса p.

См. также:

  • процедура inputHandle
  • процедура errorHandle
Исходный код Изменить
proc outputStream(p: Process): Stream {....gcsafe, extern: "nosp$1",
                                        raises: [IOError, OSError], tags: [],
                                        forbids: [].}

Возвращает поток вывода p для чтения.

Вы не можете выполнять операции peek/write/setOption с этим потоком. Используйте процедуру peekableOutputStream, если вам нужно просмотреть поток.

Предупреждение: Возвращённый Stream не следует закрывать вручную, так как он закрывается при закрытии процесса p.

См. также:

  • процедура inputStream
  • процедура errorStream
Исходный код Изменить
END_OF_DOCUMENT_MARKER
proc peekableErrorStream(p: Process): Stream {....gcsafe, extern: "nosp$1",
    tags: [], raises: [], forbids: [].}

Возвращает поток ошибок p для чтения из него.

Вы можете выполнить операцию peek для возвращаемого потока.

Предупреждение: Возвращаемый Stream не следует закрывать вручную, так как он закрывается при закрытии процесса p.

См. также:

  • процедура errorStream
  • процедура peekableOutputStream
Исходный код Редактировать
proc peekableOutputStream(p: Process): Stream {....gcsafe, extern: "nosp$1",
    tags: [], raises: [], forbids: [].}

Возвращает поток вывода p для чтения из него.

Вы можете выполнить операцию peek для возвращаемого потока.

Предупреждение: Возвращаемый Stream не следует закрывать вручную, так как он закрывается при закрытии процесса p.

См. также:

  • процедура outputStream
  • процедура peekableErrorStream
Исходный код Редактировать
proc peekExitCode(p: Process): int {....gcsafe, extern: "nosp$1",
                                     raises: [OSError], tags: [], forbids: [].}

Возвращает -1, если процесс всё ещё выполняется. В противном случае возвращает код выхода процесса.

В системах POSIX, если процесс завершился из-за сигнала, будет возвращено значение 128 + номер сигнала.

Исходный код Редактировать
proc processID(p: Process): int {....gcsafe, extern: "nosp$1", raises: [],
                                  tags: [], forbids: [].}

Возвращает идентификатор процесса p.

См. также:

  • процедура os.getCurrentProcessId
Исходный код Редактировать
proc readLines(p: Process): (seq[string], int) {.
    ...raises: [OSError, IOError, ValueError], tags: [ReadIOEffect, TimeEffect],
    forbids: [].}

Удобная функция для работы с startProcess для чтения данных из фонового процесса.

См. также:

  • итератор lines

Пример:

const opts = {poUsePath, poDaemon, poStdErrToStdOut}
var ps: seq[Process]
for prog in ["a", "b"]: # run 2 progs in parallel
  ps.add startProcess("nim", "", ["r", prog], nil, opts)
for p in ps:
  let (lines, exCode) = p.readLines
  if exCode != 0:
    for line in lines: echo line
  p.close
Исходный код Редактировать
proc resume(p: Process) {....gcsafe, extern: "nosp$1", tags: [], raises: [],
                          forbids: [].}

Возобновляет процесс p.

См. также:

  • процедура suspend
  • процедура terminate
  • процедура kill
Исходный код Редактировать
proc running(p: Process): bool {....gcsafe, extern: "nosp$1", raises: [OSError],
                                 tags: [], forbids: [].}
Возвращает true, если процесс p всё ещё выполняется. Возвращает результат немедленно. Исходный код Редактировать
proc startProcess(command: string; workingDir: string = "";
                  args: openArray[string] = []; env: StringTableRef = nil;
                  options: set[ProcessOption] = {poStdErrToStdOut}): owned(
    Process) {....gcsafe, extern: "nosp$1", raises: [OSError, IOError],
               tags: [ExecIOEffect, ReadEnvEffect, RootEffect], forbids: [].}

Запускает процесс. Command — исполняемый файл, workingDir — рабочая директория процесса. Если workingDir == "", используется текущая директория (по умолчанию). args — аргументы командной строки, передаваемые процессу. Во многих операционных системах первый аргумент командной строки — имя исполняемого файла. args не должен содержать этот аргумент! env — окружение, которое будет передано процессу. Если env == nil (по умолчанию), окружение наследуется от родительского процесса. options — дополнительные флаги, которые могут быть переданы startProcess . См. документацию ProcessOption для значения этих флагов.

После завершения работы необходимо закрыть процесс.

Обратите внимание, что вы не можете передавать любые args если вы используете опцию poEvalCommand, которая вызывает оболочку системы для запуска указанного command. В этом случае вы должны вручную конкатенировать содержимое args с command , тщательно экранируя/цитируя любые специальные символы, так как это будет передано неизменно оболочке системы. Каждая система/оболочка может иметь разные правила экранирования, поэтому постарайтесь избегать такого вызова оболочки, если это возможно, так как это приводит к непереносимому программному обеспечению.

Значение возврата: новый созданный объект процесса. Никогда не возвращается Nil, но OSError генерируется в случае ошибки.

См. также:

  • процедура execProcesses
  • процедура execProcess
  • процедура execCmd
Исходный код Редактировать
proc suspend(p: Process) {....gcsafe, extern: "nosp$1", tags: [], raises: [],
                           forbids: [].}

Приостанавливает процесс p.

См. также:

  • процедура resume
  • процедура terminate
  • процедура kill
Исходный код Редактировать
proc terminate(p: Process) {....gcsafe, extern: "nosp$1", tags: [],
                             raises: [OSError], forbids: [].}

Останавливает процесс p.

В системах POSIX процедура отправляет SIGTERM процессу. В Windows вызывается функция Win32 API TerminateProcess() для остановки процесса.

См. также:

  • процедура suspend
  • процедура resume
  • процедура kill
  • posix_utils.sendSignal(pid: Pid, signal: int)
Исходный код Редактировать
proc waitForExit(p: Process; timeout: int = -1): int {....gcsafe, extern: "nosp$1",
    raises: [OSError, ValueError], tags: [TimeEffect], forbids: [].}
Ожидает завершения процесса и возвращает код ошибки p.
Предупреждение: Будьте осторожны при использовании waitForExit для процессов, созданных без poParentStreams, поскольку они могут заполнять буферы вывода, вызывая тупик.

В системах POSIX, если процесс завершился из-за сигнала, будет возвращено значение 128 + номер сигнала.

Предупреждение: При работе с параметрами timeout помните, что значение обычно выражается в миллисекундах, и убедитесь, что используется правильная единица времени, чтобы избежать неожиданного поведения.
Исходный код Редактировать

Итераторы

iterator lines(p: Process; keepNewLines = false): string {.
    ...raises: [OSError, IOError, ValueError], tags: [ReadIOEffect, TimeEffect],
    forbids: [].}

Удобный итератор для работы с startProcess для чтения данных из фонового процесса.

См. также:

  • процедура readLines

Пример:

const opts = {poUsePath, poDaemon, poStdErrToStdOut}
var ps: seq[Process]
for prog in ["a", "b"]: # run 2 progs in parallel
  ps.add startProcess("nim", "", ["r", prog], nil, opts)
for p in ps:
  var i = 0
  for line in p.lines:
    echo line
    i.inc
    if i > 100: break
  p.close
Исходный код Редактировать

© 2006–2024 Andreas Rumpf
Licensed under the MIT License.
https://nim-lang.org/docs/osproc.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API