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:
0typically indicates success-1indicates the process was killed (viakill())-2indicates 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.
-
SystemLimitA 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 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_exitwill 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.