child_process

Types

A builder for configuring and spawning child processes.

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

Example

child_process.new("node")
|> child_process.arg("server.js")
|> child_process.env("PORT", "3000")
|> child_process.cwd("/app")
|> child_process.stdio(stdio.lines(fn(line) {
  io.println(line)
}))
|> child_process.on_exit(fn(code) {
  io.println("Server exited with code: " <> int.to_string(code))
})
|> child_process.spawn()
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

    Output capture: The output field will be empty if stdio.inherit() was used, since output goes directly to the terminal.

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 {
  FileNotFound(String)
  FileNotExecutable(String)
  SystemLimit
}

Constructors

  • FileNotFound(String)

    The executable file was not found at the specified path.

  • FileNotExecutable(String)

    The file exists but is not executable.

  • SystemLimit

    A system resource limit prevented the process from starting. This could be an operating system limit or a VM limit.

Values

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

Add a command-line argument to the process.

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 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() -> factory_supervisor.Builder(Builder, Process)

Create a factory supervisor builder for dynamically spawning supervised processes.

Keep in mind that a non-zero exit code still indicates success and the Erlang process will exit normally.

Example

import gleam/otp/factory_supervisor

let assert Ok(factory) =
  child_process.factory() |> 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 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 new(executable_path: String) -> Builder

Create a new process builder with the given executable path.

Example

new("/usr/bin/git")
|> arg("status")
|> run()
pub fn new_with_path(executable_name: String) -> Builder

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

Example

new_with_path("git")
|> arg("status")
|> run()
pub fn on_exit(
  builder: Builder,
  on_exit callback: fn(Int) -> Nil,
) -> Builder

Configure a callback that is called when the process exits.

Example

new("vite")
|> on_exit(fn(status_code) {
  process.end(self, ViteExited(status_code))
})
pub fn os_process_id(process: Process) -> Int

Get the operating system process ID.

pub fn run(builder: Builder) -> Result(Output, StartError)

Run the process synchronously and wait for it to complete.

If the stdio is not explicitly set to inherit, the stdio configuration will be replaced and all output will be captured.

Returns the exit status and captured output. The on_exit callback will be called before this function returns.

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) -> Result(Process, StartError)

Spawn the process asynchronously, returning a handle to interact with it.

Note: Node delivers errors asynchronously, so this implementation makes various checks beforehand to be reasonably sure that the call to spawn will succeed. If the process fails to start, on_exit will report a status_code of -2.

pub fn stdio(builder: Builder, stdio: stdio.Stdio) -> Builder

Configure stdio handling for the process.

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,
) -> supervision.ChildSpecification(Process)

Create a child specification for use with OTP supervisors.

Using the Permanent restart strategy, the process will always be restarted if it exits (including normal exits). This allows you to add long running external processes like servers or daemons to your OTP app.

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()
)
pub fn write(process: Process, text: String) -> Nil

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) -> Nil

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

Search Document