child_process

Types

A builder for configuring and spawning child processes.

Use from_file() or from_name() to create a builder, then chain configuration methods like arg(), env(), and cwd() before calling run() or spawn().

Example

child_process.from_name("node")
|> child_process.arg("server.js")
|> child_process.env("PORT", "3000")
|> child_process.cwd("/app")
|> child_process.run(stdio.capture(True))
pub type Builder =
  @internal Builder

The result of running a process to completion. Contains the exit status code and captured output.

pub type Output {
  Output(status_code: Int, output: String)
}

Constructors

  • Output(status_code: Int, output: String)

    The status code and captured output from the process.

    Exit codes:

    • 0 typically indicates success
    • -1 indicates the process was killed (via kill())
    • -2 indicates the process failed to start (only on JavaScript target)
    • Other non-zero values are process-specific error codes

    When no output was configured to be captured, output will be empty.

A handle to a running child process.

Use the process control functions like write(), stop(), and kill() to interact with the process.

pub type Process =
  @internal Process

An error that occurred when trying to start a process.

pub type StartError {
  OutOfMemory
  OsProcessLimitReached
  OsFileLimitReached
  CommandTooLong
  NotEnoughFileDescriptors
  FileNotFound(String)
  FileNotExecutable(String)
  RuntimeLimitReached
}

Constructors

  • OutOfMemory

    The operating system does not have enough memory to spawn this process.

  • OsProcessLimitReached

    The operating system process table is full.

  • OsFileLimitReached

    The operating system file descriptor table is full.

  • CommandTooLong

    The command is too long.

  • NotEnoughFileDescriptors

    The runtime process has too many open file descriptors.

  • FileNotFound(String)

    The executable file was not found at the specified path.

  • FileNotExecutable(String)

    The file exists but is not executable.

  • RuntimeLimitReached

    A runtime resource limit prevented the process from starting.

An error that occurred while sending data to the process.

pub type WriteError {
  WriteAborted
  ProcessExited
}

Constructors

  • WriteAborted

    The process can’t be written to right now or writing was cancelled.

  • ProcessExited

    The process you tried to write to already exited.

Values

pub fn arg(builder: Builder, argument: String) -> Builder

Add a command-line argument to the process.

pub fn arg2(
  builder: Builder,
  argument: String,
  value: String,
) -> Builder

Add 2 command-line arguments to the process. Useful when adding option/argument pairs!

pub fn args(builder: Builder, args: List(String)) -> Builder

Add multiple command-line arguments to the process.

pub fn close(process: Process) -> Nil

Close the process’s stdin stream.

pub fn cwd(builder: Builder, directory: String) -> Builder

Set the working directory for the process.

pub fn describe_start_error(error: StartError) -> String

Convert a StartError into a human-readable string.

pub fn describe_write_error(error: WriteError) -> String

Convert a WriteError into a human-readable string.

pub fn env(
  builder: Builder,
  key: String,
  value: String,
) -> Builder

Set an environment variable for the process.

Environment variables set here are merged with the parent process’s environment, not replaced.

pub fn envs(
  builder: Builder,
  environment: List(#(String, String)),
) -> Builder

Set multiple environment variables for the process.

Environment variables set here are merged with the parent process’s environment, not replaced.

pub fn exec(
  run command: String,
  with arguments: List(String),
  in directory: String,
) -> Result(Output, StartError)

Execute a command with arguments in a specific directory.

Example

exec(run: "git", with: ["status"], in: "/path/to/repo")
pub fn factory(
  stdio stdio: stdio.Stdio,
) -> factory_supervisor.Builder(Builder, Process)

Create a factory supervisor builder for dynamically spawning supervised processes.

The stdio configuration determines how each child’s I/O is handled.

Example

import gleam/otp/factory_supervisor

let assert Ok(factory) =
  child_process.factory(stdio: stdio.ignore())
  |> factory_supervisor.start()

let worker_config =
  child_process.new("node")
  |> child_process.arg("worker.js")

factory_supervisor.start_child(factory, worker_config)
pub fn find_executable(name: String) -> Result(String, Nil)

Find an executable by name in the system PATH. Returns the absolute path to the executable if found.

Example

find_executable("git")
// -> Ok("/usr/bin/git")
pub fn from_file(executable_path: String) -> Builder

Create a new process builder with the given executable path.

Example

from_file("/usr/bin/git")
|> arg("status")
|> run(stdio.capture(True))
pub fn from_name(executable_name: String) -> Builder

Create a new process builder, searching for the executable in PATH.

Example

from_name("git")
|> arg("status")
|> run(stdio.capture(True))
pub fn is_running(process: Process) -> Bool

Returns True if the process is still running.

pub fn kill(process: Process) -> Nil

Forcefully kill the process (SIGKILL on Unix, taskkill /F on Windows).

The process is terminated immediately without cleanup. Use stop() first to give the process a chance to exit gracefully.

pub fn open(target: String) -> Result(Nil, StartError)

Open a URL or file with the system’s default application.

Returns immediately on all platforms. The opened application runs fully detached from the Erlang VM.

Example

child_process.open("https://gleam.run")
// -> Ok(Nil)

child_process.open("/path/to/document.pdf")
// -> Ok(Nil)
pub fn os_process_id(process: Process) -> Result(Int, Nil)

Get the operating system process ID.

pub fn port(process: Process) -> port.Port

Recover the Erlang port from a process.

pub fn reveal(path: String) -> Result(Nil, StartError)

Reveal a file in the system’s file manager (Finder, Explorer, etc).

Example

child_process.reveal("/path/to/file.txt")
// -> Ok(Nil)
pub fn run(
  builder: Builder,
  mode mode: stdio.Mode,
) -> Result(Output, StartError)

Run the process synchronously and wait for it to complete.

When mode is capture(_), output is captured and returned in Output.output. When mode is null() or inherit(), output is empty.

Example

child_process.from_file("/bin/echo")
|> child_process.arg("hello")
|> child_process.run(stdio.capture(True))
pub fn shell(cmd: String) -> Result(String, StartError)

Execute a shell command string using the system shell. On Windows, uses cmd.exe. On Unix-like systems, uses /bin/sh.

Example

shell("echo Hello, World!")
pub fn spawn(
  builder: Builder,
  stdio stdio: stdio.Stdio,
) -> Result(Process, StartError)

Spawn the process asynchronously with a stdio handler.

The stdio configuration determines both the I/O mode (how the port is configured) and the callbacks (how data is consumed). The handler is applied immediately after spawning.

On Erlang, this spawns an extra process that manages the port.

Example

let assert Ok(proc) =
  child_process.from_name("node")
  |> child_process.arg("server.js")
  |> child_process.spawn(stdio.lines(fn(line) { io.println(line) }))

Note: On JavaScript, Node delivers errors asynchronously, so this implementation makes various checks beforehand to be reasonably sure that the call will succeed.

pub fn spawn_raw(
  builder: Builder,
  mode mode: stdio.Mode,
) -> Result(Process, StartError)

Spawn the process asynchronously without attaching an extra process or event listeners.

On Erlang, the port is opened in the calling process. Port messages arrive in the caller’s mailbox and can be received via stdio.select().

Example

let assert Ok(proc) =
  child_process.from_file("my_program")
  |> child_process.spawn_raw(stdio.capture(True))

let selector =
  process.new_selector()
  |> stdio.select(proc, HandleData, HandleExit)

Note: On JavaScript, Node delivers errors asynchronously, so this implementation makes various checks beforehand to be reasonably sure that the call will succeed.

pub fn stop(process: Process) -> Nil

Stop the process gracefully (SIGTERM on Unix, taskkill on Windows).

The process has the opportunity to perform cleanup before exiting. If the process doesn’t exit on its own, you may need to call kill() to forcefully terminate it.

pub fn supervised(
  builder: Builder,
  stdio stdio: stdio.Stdio,
) -> supervision.ChildSpecification(Process)

Create a child specification for use with OTP supervisors.

The stdio configuration determines both how I/O is handled and how data is consumed. The intermediate process created by the handler is what the supervisor monitors.

When the supervisor shuts down, the intermediate process receives a shutdown signal and sends SIGTERM to the OS process.

Example

import gleam/otp/static_supervisor as supervisor

supervisor.new(supervisor.OneForOne)
|> supervisor.add(
  child_process.new("node")
  |> child_process.arg("server.js")
  |> child_process.supervised(stdio.lines(fn(line) {
    io.println(line)
  }))
)
pub fn write(
  process: Process,
  text: String,
) -> Result(Nil, WriteError)

Write text to the process’s stdin, without appending a newline character.

Note: Writing to stdin is not supported when using stdio.inherit(), as the stdin stream is connected directly to the parent’s terminal.

pub fn writeln(
  process: Process,
  text: String,
) -> Result(Nil, WriteError)

Write a line of text to the process’s stdin.

Search Document