# osproc

Dark Mode

- Manual
- Standard library
- Index

Search:
Group by:

This module implements an advanced facility for executing OS processes and process communication.

See also:

- os module
- streams module
- memfiles module

# Imports

strutils, os, strtabs, streams, cpuinfo, winlean

# Types

    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!

  Options that can be passed to startProcess proc. Source Edit

    Process = ref ProcessObj

  Represents an operating system process. Source Edit

# Consts

    poDemon = poDaemon

  Nim versions before 0.20 used the wrong spelling ("demon"). Now `ProcessOption` uses the correct spelling ("daemon"), and this is needed just for backward compatibility. Source Edit

# Procs

    proc processID(p: Process): int {...}{.gcsafe, extern: "nosp$1", raises: [], tags: [].}

  Returns `p`'s process ID.

  See also:

  - os.getCurrentProcessId proc
  Source Edit

    proc inputHandle(p: Process): FileHandle {...}{.gcsafe, extern: "nosp$1", tags: [],
        raises: [].}

  Returns `p`'s input file handle for writing to.

  WARNING: The returned `FileHandle` should not be closed manually as it is closed when closing the Process `p`.

  See also:

  - outputHandle proc
  - errorHandle proc
  Source Edit

    proc outputHandle(p: Process): FileHandle {...}{.gcsafe, extern: "nosp$1", tags: [],
        raises: [].}

  Returns `p`'s output file handle for reading from.

  WARNING: The returned `FileHandle` should not be closed manually as it is closed when closing the Process `p`.

  See also:

  - inputHandle proc
  - errorHandle proc
  Source Edit

    proc errorHandle(p: Process): FileHandle {...}{.gcsafe, extern: "nosp$1", tags: [],
        raises: [].}

  Returns `p`'s error file handle for reading from.

  WARNING: The returned `FileHandle` should not be closed manually as it is closed when closing the Process `p`.

  See also:

  - inputHandle proc
  - outputHandle proc
  Source Edit

    proc countProcessors(): int {...}{.gcsafe, extern: "nosp$1", raises: [], tags: [].}

  Returns the number of the processors/cores the machine has. Returns 0 if it cannot be detected. It is implemented just calling `cpuinfo.countProcessors`. Source Edit

    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",
        tags: [ExecIOEffect, TimeEffect, ReadEnvEffect, RootEffect],
        raises: [Exception, OSError].}

  Executes the commands `cmds` in parallel. Creates `n` processes that execute in parallel.

  The highest (absolute) return value of all processes is returned. Runs `beforeRunEvent` before running each command.

  Source Edit

    proc execProcess(command: string; workingDir: string = "";
                     args: openArray[string] = []; env: StringTableRef = nil;
        options: set[ProcessOption] = {poStdErrToStdOut, poUsePath, poEvalCommand}): TaintedString {...}{.
        gcsafe, extern: "nosp$1", tags: [ExecIOEffect, ReadIOEffect, RootEffect],
        raises: [Exception, Defect, IOError, OSError].}

  A convenience procedure that executes `command` with `startProcess` and returns its output as a string.

  WARNING: This function uses `poEvalCommand` by default for backward compatibility. Make sure to pass options explicitly.

  See also:

  - startProcess proc
  - execProcesses proc
  - execCmd proc

  Example:

      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

  Source Edit

    proc startProcess(command: string; workingDir: string = "";
                      args: openArray[string] = []; env: StringTableRef = nil;
                      options: set[ProcessOption] = {poStdErrToStdOut}): owned(
        Process) {...}{.gcsafe, extern: "nosp$1",
                   tags: [ExecIOEffect, ReadEnvEffect, RootEffect],
                   raises: [OSError, Exception, ValueError].}

  Starts a process. `Command` is the executable file, `workingDir` is the process's working directory. If `workingDir == ""` the current directory is used (default). `args` are the command line arguments that are passed to the process. On many operating systems, the first command line argument is the name of the executable. `args` should not contain this argument! `env` is the environment that will be passed to the process. If `env == nil` (default) the environment is inherited of the parent process. `options` are additional flags that may be passed to `startProcess`. See the documentation of ProcessOption for the meaning of these flags.

  You need to close the process when done.

  Note that you can't pass any `args` if you use the option `poEvalCommand`, which invokes the system shell to run the specified `command`. In this situation you have to concatenate manually the contents of `args` to `command` carefully escaping/quoting any special characters, since it will be passed as is to the system shell. Each system/shell may feature different escaping rules, so try to avoid this kind of shell invocation if possible as it leads to non portable software.

  Return value: The newly created process object. Nil is never returned, but `OSError` is raised in case of an error.

  See also:

  - execProcesses proc
  - execProcess proc
  - execCmd proc
  Source Edit

    proc close(p: Process) {...}{.gcsafe, extern: "nosp$1", tags: [WriteIOEffect],
                             raises: [].}

  When the process has finished executing, cleanup related handles.

  WARNING: If the process has not finished executing, this will forcibly terminate the process. Doing so may result in zombie processes and pty leaks.

  Source Edit

    proc suspend(p: Process) {...}{.gcsafe, extern: "nosp$1", tags: [], raises: [].}

  Suspends the process `p`.

  See also:

  - resume proc
  - terminate proc
  - kill proc
  Source Edit

    proc resume(p: Process) {...}{.gcsafe, extern: "nosp$1", tags: [], raises: [].}

  Resumes the process `p`.

  See also:

  - suspend proc
  - terminate proc
  - kill proc
  Source Edit

    proc running(p: Process): bool {...}{.gcsafe, extern: "nosp$1", tags: [], raises: [].}

  Returns true iff the process `p` is still running. Returns immediately. Source Edit

    proc terminate(p: Process) {...}{.gcsafe, extern: "nosp$1", tags: [], raises: [].}

  Stop the process `p`.

  On Posix OSes the procedure sends `SIGTERM` to the process. On Windows the Win32 API function `TerminateProcess()` is called to stop the process.

  See also:

  - suspend proc
  - resume proc
  - kill proc
  Source Edit

    proc kill(p: Process) {...}{.gcsafe, extern: "nosp$1", tags: [], raises: [].}

  Kill the process `p`.

  On Posix OSes the procedure sends `SIGKILL` to the process. On Windows `kill` is simply an alias for terminate().

  See also:

  - suspend proc
  - resume proc
  - terminate proc
  Source Edit

    proc waitForExit(p: Process; timeout: int = -1): int {...}{.gcsafe, extern: "nosp$1",
        tags: [], raises: [].}

  Waits for the process to finish and returns `p`'s error code.

  WARNING: Be careful when using `waitForExit` for processes created without `poParentStreams` because they may fill output buffers, causing deadlock.

  On posix, if the process has exited because of a signal, 128 + signal number will be returned.

  Source Edit

    proc peekExitCode(p: Process): int {...}{.gcsafe, extern: "nosp$1", tags: [],
                                         raises: [].}

  Return `-1` if the process is still running. Otherwise the process' exit code.

  On posix, if the process has exited because of a signal, 128 + signal number will be returned.

  Source Edit

    proc inputStream(p: Process): Stream {...}{.gcsafe, extern: "nosp$1", tags: [],
                                           raises: [].}

  Returns `p`'s input stream for writing to.

  WARNING: The returned `Stream` should not be closed manually as it is closed when closing the Process `p`.

  See also:

  - outputStream proc
  - errorStream proc
  Source Edit

    proc outputStream(p: Process): Stream {...}{.gcsafe, extern: "nosp$1", tags: [],
                                            raises: [].}

  Returns `p`'s output stream for reading from.

  WARNING: The returned `Stream` should not be closed manually as it is closed when closing the Process `p`.

  See also:

  - inputStream proc
  - errorStream proc
  Source Edit

    proc errorStream(p: Process): Stream {...}{.gcsafe, extern: "nosp$1", tags: [],
                                           raises: [].}

  Returns `p`'s error stream for reading from.

  WARNING: The returned `Stream` should not be closed manually as it is closed when closing the Process `p`.

  See also:

  - inputStream proc
  - outputStream proc
  Source Edit

    proc execCmd(command: string): int {...}{.gcsafe, extern: "nosp$1", tags: [
        ExecIOEffect, ReadIOEffect, RootEffect], raises: [OSError].}

  Executes `command` and returns its error code.

  Standard input, output, error streams are inherited from the calling process. This operation is also often called system.

  See also:

  - execCmdEx proc
  - startProcess proc
  - execProcess proc

  Example:

      let errC = execCmd("nim c -r mytestfile.nim")

  Source Edit

    proc hasData(p: Process): bool {...}{.raises: [], tags: [].}

  Source Edit

    proc execCmdEx(command: string;
                   options: set[ProcessOption] = {poStdErrToStdOut, poUsePath}): tuple[
        output: TaintedString, exitCode: int] {...}{.
        tags: [ExecIOEffect, ReadIOEffect, RootEffect], gcsafe,
        raises: [OSError, Exception, ValueError, IOError, Defect].}

  A convenience proc that runs the `command`, grabs all its output and exit code and returns both.

  See also:

  - execCmd proc
  - startProcess proc
  - execProcess proc

  Example:

      let (outp, errC) = execCmdEx("nim c -r mytestfile.nim")

  Source Edit

# Exports

quoteShell, quoteShellWindows, quoteShellPosix