Processes
Run other programs and read their output.
On this page
core.Process starts other programs, and core.exec runs a shell command. Waiting for a child or its output only pauses the current coroutine, so a server on the same thread keeps running.
Run a program and collect its output#
use valk.core
fn main() {
let result = core.Process.output("echo", .{ "hello", "world" }) ! {
println("Could not start echo")
return
}
println(result.code) // 0
print(result.stdout) // hello world
}
output waits until the program ends and returns its exit code, stdout and stderr. Each argument reaches the program as it is, with no shell and no quoting. Named arguments set the rest:
| Argument | Meaning |
|---|---|
input |
Text written to the child's stdin |
cwd |
The working directory of the child |
env |
The child's environment, replacing the current one |
use valk.core
fn main() {
let sorted = core.Process.output("sort", input: "pear\napple\n") ! return
print(sorted.stdout) // apple, pear
}
Starting fails with an io.IoError when the program cannot be found. A program that runs but fails is not an error: check code.
Run a shell command#
core.exec runs a command line through /bin/sh (cmd.exe on Windows) and returns the exit code and the output, stderr included:
use valk.core
fn main() {
let code, out = core.exec("echo one; echo two | tr a-z A-Z")
println(code) // 0
print(out) // one, TWO
}
The shell reads quotes, spaces and ; in the command, so never put outside input in it. Use Process.output with arguments instead.
Start a program and keep control#
Process.start returns right away. Each of stdin, stdout and stderr is .inherit (the default), .pipe or .discard:
use valk.core
fn main() {
let child = core.Process.start("sort", stdin: .pipe, stdout: .pipe) ! return
child.stdin.write("b\na\n") ! return
child.stdin.close() ! return // ends the child's input
print(child.stdout.read_all() ! return) // a, b
println(child.wait() ! return) // 0
}
| Method | Does |
|---|---|
wait(timeout_ms) |
Waits for the exit code; throws timeout when the time runs out |
did_exit() |
Whether it has exited, without waiting |
signal(.terminate) |
Sends a signal (on Windows only .terminate) |
stop() |
Kills the child and waits for it |
detach() |
Lets the child run on without you |
id() |
The process id |
The pipes are an io.Reader / io.Writer, so io.copy and io.LineReader work on them. Dropping a Process does not stop the child.
Environment variables#
use valk.core
fn main() {
core.setenv("APP_MODE", "test") ! return
println(core.getenv("APP_MODE") !? "none") // test
core.unsetenv("APP_MODE") ! return
println(core.getenv("APP_MODE") !? "none") // none
println(core.env_vars().length > 0) // true
}
getenv throws when the variable is not set. Changes apply to this process and the children it starts afterwards. To give one child its own environment, change a copy from core.env_vars() and pass it as env.
Arguments and exit code#
main can take the command-line arguments, and core.exit ends the program with a code:
use valk.core
fn main(args: Array[String]) {
if args.length < 2 {
println("usage: greet <name>")
core.exit(1)
}
println("Hello " + args[1])
}
args[0] is the program itself. main may also return an i32 as the exit code.
About the machine#
| Function | Returns |
|---|---|
core.cpu_thread_count() |
Logical CPUs |
core.cpu_core_count() |
Physical cores |
core.memory_limit() |
RAM, or the container's limit |
core.process_id() |
This process's id |
core.hostname() |
The machine's name |
