System, Environment, And Processes

Import sys for process information, environment variables, script arguments, sleeping, exit status, and subprocess execution.

sys is about the running process and the host operating system. It does not own filesystem mutation; use io for files/directories and path for path string manipulation.

import sys;
import io;

io.println(sys.platform());
io.println(sys.cwd());

Module Boundaries

Need Module
Read/write files, make directories, chmod, temp files io
Join, clean, inspect, glob path strings path / pathlib
Current user, environment variables, cwd, process info sys
Run or manage subprocesses sys or process

Process Information

Function Returns Description
platform() string Host OS name, such as linux, darwin, or windows
arch() string CPU architecture, such as amd64 or arm64
hostname() string Hostname
pid() int Current process ID
username() string Current OS username
homedir() string Current user's home directory
tmpdir() string Host temporary directory
cwd() string Current working directory
io.println(sys.hostname());
io.println(sys.pid() as string);
io.println(sys.homedir());
io.println(sys.tmpdir());

Use sys.tmpdir() with path.join when you need a location, and io.tempFile or io.tempDir when you want Geblang to create a unique path for you.

Environment Variables

Function Returns Description
getenv(name) `string null`
setenv(name, value) void Set an environment variable for the current process and child processes
environ() dict<string, string> Snapshot of the current environment
let env = sys.getenv("APP_ENV");
if (env == null) {
    sys.setenv("APP_ENV", "development");
}

let all = sys.environ();
io.println(all["PATH"]);

setenv affects the current Geblang process and subprocesses launched after the call. It does not change the parent shell's environment.

Use the dotenv module when loading .env files:

import dotenv;

if (io.exists(".env")) {
    dotenv.loadAndApply(".env");
}

Script Arguments

Function Returns Description
args() list<string> Arguments passed to the script
let argv = sys.args();
if (argv.length() > 0) {
    io.println("first arg: " + argv[0]);
}

For user-facing command-line applications, prefer the cli module for option parsing, help text, prompts, and terminal formatting.

Sleep And Exit

Function Returns Description
sleep(ms) void Block for the given milliseconds
exit(code) never Exit the script with the given process status
sys.sleep(500);
sys.exit(0);

sys.sleep blocks the current execution thread. In async code, prefer async.sleep(ms) so the scheduler can continue other work while waiting.

Running Subprocesses

Use sys.run when you want to run a command, wait for it to finish, and inspect captured stdout/stderr.

Function Returns Description
run(command, args) dict Run a command with a list of arguments
shell(command) dict Run a shell command through /bin/sh -c
runWithOptions(options) dict Run with cwd/env/timeout options

Result dictionary:

Field Type Description
code int Exit code, where 0 normally means success
stdout string Captured standard output
stderr string Captured standard error
timedOut bool Whether the process was killed by timeout
let result = sys.run("git", ["log", "--oneline", "-5"]);
if ((result["code"] as int) == 0) {
    io.println(result["stdout"]);
} else {
    io.stderrWrite(result["stderr"]);
}

sys.shell(command) is convenient for shell features such as pipes and redirection, but it executes through the host shell. Do not pass untrusted input into a shell command string.

let result = sys.shell("ls -la | head -5");

runWithOptions

sys.runWithOptions(options) accepts:

Option Type Description
command string Required executable
args list<string> Arguments, default []
cwd string Working directory
env dict<string, string> Extra environment values merged into the current environment
timeoutMs int Kill the process after this many milliseconds
let result = sys.runWithOptions({
    "command": "npm",
    "args": ["run", "build"],
    "cwd": "/app",
    "env": {"NODE_ENV": "production"},
    "timeoutMs": 30000
});

if (result["timedOut"] as bool) {
    io.stderrWrite("build timed out\n");
}

The env dictionary is merged with the current process environment. To modify or pass through a large environment, start with sys.environ():

let env = sys.environ();
env["PATH"] = "/usr/local/bin:" + env["PATH"];

let result = sys.runWithOptions({
    "command": "node",
    "args": ["server.js"],
    "env": env
});

Streaming Subprocess Handles

Use sys.start when you need to interact with a process while it runs.

Function Returns Description
start(command, args) process handle Start a process with stdin/stdout/stderr pipes
startWithOptions(options) process handle Start with cwd/env options
processWrite(proc, text) int Write text to stdin
processCloseStdin(proc) void Close stdin
processReadStdout(proc) string Read all remaining stdout
processReadStderr(proc) string Read all remaining stderr
processReadStdoutN(proc, n) string Read up to n bytes from stdout
processReadStderrN(proc, n) string Read up to n bytes from stderr
processWait(proc) int Wait for exit and return the code
processKill(proc) void Send SIGKILL
processSignal(proc, signal) void Send KILL, TERM, INT, or HUP
processPid(proc) int Return the OS process ID
let proc = sys.start("cat", []);

sys.processWrite(proc, "hello\n");
sys.processCloseStdin(proc);

io.println(sys.processReadStdout(proc));
let code = sys.processWait(proc);
io.println(code);

startWithOptions accepts command, args, cwd, and env. It does not accept timeoutMs; manage long-running process lifecycle yourself with processKill, processSignal, or the object-oriented process module.

Async Patterns

sys.run and sys.runWithOptions are synchronous. Use async.run to start blocking work concurrently:

import async;
import sys;

let lintTask = async.run(func(): dict {
    return sys.run("eslint", ["src/"]);
});

let testTask = async.run(func(): dict {
    return sys.run("pytest", ["tests/"]);
});

let lintResult = await lintTask;
let testResult = await testTask;

Inside async functions, prefer async.sleep over sys.sleep.

process Module

Import process for a class-based alternative to sys.run and sys.start. The process module wraps the same underlying functionality in Result and Process objects.

import process;

let result = process.run("git", ["status", "--short"]);
if (result.isOk()) {
    io.println(result.stdout());
}

Module Functions

Function Returns Description
process.run(cmd, args...) Result Run command and wait
process.runWithOptions(opts) Result Run with options dict
process.shell(cmd) Result Run through the host shell
process.start(cmd, args...) Process Start a live process
process.startWithOptions(opts) Process Start with options dict

Both run and start accept either variadic string arguments or a command followed by a list.

process.Result

Method Returns Description
isOk() bool Exit code is 0
code() int Exit code
stdout() string Captured stdout
stderr() string Captured stderr
timedOut() bool Process was killed by timeout

process.Process

Method Returns Description
write(text) int Write text to stdin
closeStdin() void Close stdin
readStdout() string Read all remaining stdout
readStderr() string Read all remaining stderr
readStdoutN(n) string Read up to n bytes from stdout
readStderrN(n) string Read up to n bytes from stderr
wait() int Wait for exit
kill() void Send SIGKILL
signal(name) void Send KILL, TERM, INT, or HUP
pid() int OS process ID
let proc = process.start("cat", []);
proc.write("hello\n");
proc.closeStdin();
io.println(proc.readStdout());
io.println(proc.wait());