std.os
The host environment and process. env and exec are gated for package code.
import std.os
os.env("HOME") # null when unset
os.env_or("PORT", "8080")
os.set_env("TZ", "UTC")
os.unset_env("TZ") # the inverse; already absent is fine
os.args() # arguments after the script
os.cwd()
os.platform() # "linux" | "macos" | "windows"
os.pid() # this process's id
os.cpu_count() # usable parallelism, read once per process
os.hostname() # the machine name
os.mem() # resident memory in bytes, or null
os.arch() # "x86_64" | "aarch64"
os.family()
os.script() # the running file
r = os.exec("git", ["status", "--short"])
print(r.code) print(r.stdout) print(r.stderr)
os.exit(1)
env returns null
One of the three documented nullable lookups in the error dialect - absence is expected for an environment variable. env_or supplies a default in one call.
Wrap anything sensitive immediately:
key = secret(os.env("API_KEY"))
See Secrets. A credential read into a plain string can reach a log line; wrapped, it cannot.
exec
Returns { code, stdout, stderr } and does not raise on a non-zero exit - check code yourself. That is deliberate: for many commands a non-zero status is information rather than a failure.
r = os.exec("which", ["ecko"])
if r.code != 0 { install() }
Arguments are a list, and they are not shell-interpreted. There is no shell involved, so no quoting rules and no injection through argument values:
os.exec("git", ["log", "--grep", user_input]) # safe
If you route through a shell yourself - os.exec("sh", ["-c", cmd]) - you take that safety back off. Avoid building cmd from anything you did not write.
mem
How much physical memory the program holds right now, in bytes. A long job can log it as it goes, or slow down before a container's memory limit stops it:
if os.mem() > 1500 * 1024 * 1024 { flush_batch() }
It is read from the operating system on every call, and it is the current figure, not the peak. It returns null where the platform gives no answer rather than raising, so compare it after checking:
m = os.mem()
unless is_null(m) { print("rss {m / 1024 / 1024} MB") }
The number changes from run to run, so keep it out of output a test compares.
exit
Ends the process with a status. finally blocks do not run, so close what needs closing first. Prefer returning from main logic where you can, so cleanup happens.
Portability
Check platform() rather than assuming. Path separators come from fs.join; do not hardcode /.