Standardbibliothek
Antra::Process
import Antra::ProcessProcess helpers for Antra.
Process exposes a small child-process API around an opaque runtime value.
The returned handle owns the child process plus its standard streams.
Use the API in these rough tiers:
spawn(...)when you want the rawProcesshandle and explicit controlcapture(...)when you only needstdoutplusexit_codepipe_from(...)for the explicitcmd |shape with a readable stdout handle plus the owningprocesswith_output(...)when you want capturedstdout,stderr, andexit_codein one callbackwith_pipes(...)for interactivestdin/stdout/stderrwork with realFileHandles
Use signal(...), terminate(...) or kill(...) when a process should not
just be waited on but actively interrupted.
Überblick#
Für einfache Child-Processes mit stdin/stdout/stderr-Pipes und opakem Process-Wert.
Boundary-Fehler wie ungueltige Kommandos, falsche Argumente oder geschlossene
Streams kommen bei den nicht-Bang-Varianten als %Err[%Error{...}] zurueck.
Der Einstieg ist bewusst klein gehalten:
Process.spawn(...)Process.capture(...)Process.pipe_from(...)Process.with_spawn(...)Process.pid(...)Process.stdin/stdout/stderr(...)Process.write(...)Process.write_bytes(...)Process.close_input(...)Process.read_all(...)Process.read_bytes(...)Process.read_all_bytes(...)Process.read_stderr_all(...)Process.signal(...)Process.terminate(...)Process.kill(...)Process.wait(...)Process.close(...)
Beispiel:
import Antra::Process as Process
import Antra::Result as Result
my process = Process.spawn("perl", ["-e", 'print uc(do { local $/; <STDIN> })']).!
Result.unwrap!(Process.write(process, "hello"))
Result.unwrap!(Process.close_input(process))
println(Process.read_all(process).!)
println(Process.close(process).!)Wenn ein Kindprozess nicht von selbst endet, kannst du ihn auch aktiv signalisieren:
import Antra::Process as Process
import Antra::Result as Result
my process = Process.spawn("perl", ["-e", 'select undef, undef, undef, 30;']).!
println(Result.unwrap!(Process.terminate(process)))
println(Process.close(process).!)Fuer Process.signal(...) sind die gaengigen Signale auch direkt in der
Antra-API sichtbar, zum Beispiel :term, :kill, :int, :hup, :quit,
:usr1, :usr2, :stop und :cont.
Fuer Binärprotokolle gibt es ausserdem Process.write_bytes(...),
Process.read_bytes(...) und Process.read_all_bytes(...) auf
ByteString-Basis. Das ist praktisch für komprimierte Daten, Bilder,
verschlüsselte Payloads oder eigene kleine Binärformate.
Wenn du lieber scoped arbeiten willst, kannst du den Process auch nur fuer den Callback oeffnen:
import Antra::IO::File as File
import Antra::Process as Process
import Antra::Result as Result
println(Process.with_spawn("perl", ["-e", 'exit 0']) |process| -> {
%Ok[Process.pid(process).!]
})
println(Process.with_spawn!("perl", ["-e", 'print uc(do { local $/; <STDIN> })']) |process| -> {
my stdin = Process.stdin(process).!
my stdout = Process.stdout(process).!
Result.unwrap!(File.write(stdin, "hello"))
Result.unwrap!(File.close(stdin))
File.read_all(stdout).!
})Fuer haeufige Einbahnstrassen-Faelle gibt es ausserdem zwei kleine Helfer:
import Antra::Process as Process
my capture = Process.capture("perl", ["-e", 'print qq[out]; exit 7;']).!
println(capture.stdout)
println(capture.exit_code)
my out = Process.pipe_from("perl", ["-e", 'print qq[first\nsecond];']).!
println(out.stdout)
println(Process.read_all(out.process).!)
println(Process.wait(out.process).!)capture(...) ist die kleine Surface fuer "stdout plus Exit-Code" und
verwirft stderr im MVP intern.
pipe_from(...) ist die explizite Form des klassischen cmd |-Falls, gibt
aber bewusst sowohl den stdout-Handle als auch den owning process zurueck.
Ein ausfuehrliches Einsteiger-Tutorial zu Process und System.fork(...) steht in 28-process-und-fork-fuer-einsteiger.md.
Funktionen#
capturecloseclose_inputkillpidpipe_fromread_allread_all_bytesread_bytesread_stderr_allread_stderr_all_bytesread_stderr_bytessignalspawnstderrstdinstdoutterminatetry_waitwaitwith_outputwith_output!with_pipeswith_pipes!with_spawnwith_spawn!writewrite_bytes
fn capture(command)
fn capture(command, args)Spawns a process, reads its stdout as text, waits for exit, and returns
%{stdout, exit_code}.
In the current MVP, stderr is only drained internally so the helper
stays focused on the common "stdout plus exit code" case.
Example:
my result = Process.capture("perl", ["-e", 'print qq[out]; exit 7;']).!
println(result.stdout)
println(result.exit_code)fn close(process)Closes all streams, waits for the child, and returns the exit status.
close(...) does not send a signal. It only closes handles and then
waits for the process to finish on its own.
fn close_input(process)Closes the child's stdin.
Call this when the child is waiting for EOF before it can finish.
fn kill(process)Sends SIGKILL to the child process.
Use this only when softer shutdown paths are not enough.
fn pid(process)Returns the child PID.
fn pipe_from(command)
fn pipe_from(command, args)Spawns a process with only stdout piped back to the caller.
This is the explicit Antra form of the common one-way cmd | pattern.
The return value keeps both the readable stdout handle and the owning
process visible so the lifecycle stays explicit.
Example:
my out = Process.pipe_from("perl", ["-e", 'print qq[first\nsecond]']).!
println(File.read_line(out.stdout).!)
println(Process.wait(out.process).!)fn read_all(process)Reads the remaining stdout of the child as text.
Returns %Ok[text] or %Err[%Error{...}].
fn read_all_bytes(process)Reads the remaining stdout of the child as raw ByteString data.
Returns %Ok[bytes] or %Err[%Error{...}].
fn read_bytes(process, n)Reads up to n bytes from the child's stdout as ByteString.
Returns %Ok[bytes] or %Err[%Error{...}].
fn read_stderr_all(process)Reads the remaining stderr of the child as text.
Returns %Ok[text] or %Err[%Error{...}].
fn read_stderr_all_bytes(process)Reads the remaining stderr of the child as raw ByteString data.
Returns %Ok[bytes] or %Err[%Error{...}].
fn read_stderr_bytes(process, n)Reads up to n bytes from the child's stderr as ByteString.
Returns %Ok[bytes] or %Err[%Error{...}].
fn signal(process, :term)
fn signal(process, :kill)
fn signal(process, :int)
fn signal(process, :hup)
fn signal(process, :quit)
# … 5 weitere KlauselnSends an explicit signal to the child process.
Common keyword shorthands are visible directly in this API:
:term, :kill, :int, :hup, :quit, :usr1, :usr2, :stop
and :cont.
Strings like "TERM", "SIGTERM" and positive signal numbers are
still accepted through the generic fallback clause.
Example:
Result.unwrap!(Process.signal(process, :term))fn spawn(command)
fn spawn(command, args)Spawns a child process without extra arguments.
Returns %Ok[#Process<...>] or %Err[%Error{...}].
fn stderr(process)Returns the readable stderr handle as FileHandle.
fn stdin(process)Returns the writable stdin handle as FileHandle.
Useful when you want lower-level stream control instead of the
convenience helpers like write(...).
fn stdout(process)Returns the readable stdout handle as FileHandle.
fn terminate(process)Sends SIGTERM to the child process.
This is the polite "please stop" variant.
fn try_wait(process)Probes whether the process has already exited without blocking.
Returns %Ok[%Some[exit_code]] once the process is reaped, otherwise
%Ok[%None[]] while it is still running.
fn wait(process)Waits for process exit and returns the exit status.
Returns %Ok[exit_code] or %Err[%Error{...}].
A signaled process is reported in shell style as 128 + signal, e.g.
143 for SIGTERM and 137 for SIGKILL.
fn with_output(process, f)Reads remaining stdout/stderr, waits for process exit and calls f with
stdout, stderr and exit_code.
This is useful for use ... <- style code when a command should be
fully captured before branching on its exit status.
Example:
my process = Process.spawn("perl", ["-e", 'print qq[out]; print STDERR qq[warn]; exit 3;']).!
use stdout, stderr, exit_code <- Process.with_output(process)
println(stdout <> ":" <> stderr <> ":" <> str(exit_code))fn with_output!(process, f)Bang/raw counterpart of with_output.
fn with_pipes(command, f)
fn with_pipes(command, args, f)Spawns a process and exposes stdin, stdout, stderr, and the raw
process handle to f.
This is the interactive pipe-oriented counterpart to with_output(...).
The stream handles are regular FileHandles and can be used with
Antra::IO::File.
Example:
Process.with_pipes!("perl", ["-e", 'my $line = <STDIN>; print uc($line)'], |stdin, stdout, stderr, process| -> {
Result.unwrap!(File.write(stdin, "hello\n"))
println(Result.unwrap!(File.close(stdin)))
File.read_all(stdout).!
})fn with_pipes!(command, f)
fn with_pipes!(command, args, f)Bang/raw counterpart of with_pipes.
fn with_spawn(command, f)
fn with_spawn(command, args, f)Spawns a child process, passes it to f, and closes it afterwards.
The callback must return %Ok[...] or %Err[...].
Example:
println(Process.with_spawn("perl", ["-e", 'print qq[ok]; exit 0;']) |process| -> {
%Ok[Process.read_all(process).!]
})fn with_spawn!(command, f)
fn with_spawn!(command, args, f)Bang/raw counterpart for callbacks using bang-style process operations.
This variant throws directly on errors instead of returning Result.
fn write(process, data)Writes text to the child's stdin.
This is raw text I/O. For structured values over fork-based channels,
prefer Antra::System.send(...).
fn write_bytes(process, bytes)Writes binary ByteString data to the child's stdin.
Use this for raw byte protocols, compressed data, image payloads, or any other non-text transport.
