mirror of
https://github.com/gechandesu/runcmd.git
synced 2026-01-02 13:49:34 +03:00
init
This commit is contained in:
44
examples/error_handling.v
Normal file
44
examples/error_handling.v
Normal file
@@ -0,0 +1,44 @@
|
||||
import os
|
||||
import runcmd
|
||||
|
||||
fn main() {
|
||||
// Prepare the command.
|
||||
mut cmd := runcmd.new('sh', '-c', 'echo -n This command always fails! >&2; sleep 30; false')
|
||||
|
||||
// Run this example with `-d runcmd_trace` to see debug logs.
|
||||
// Look for line like this: runcmd[pid=584015]: Process.wait: wait for pid 584016
|
||||
// Try to `kill -9 ${pid_here}` while program runs and see whats happen.
|
||||
|
||||
// Run command with capturing its output.
|
||||
out := cmd.output() or {
|
||||
if err is runcmd.ExitError {
|
||||
// Command exited with non-zero code. Handle it here.
|
||||
eprintln(err)
|
||||
// `err.state` can tell you the failure details.
|
||||
eprintln(err.state)
|
||||
// Let's check if the process was killed by someone...
|
||||
status := runcmd.WaitStatus(err.state.sys())
|
||||
if status.term_signal() == int(os.Signal.kill) {
|
||||
eprintln('Oh, process is killed... ( x__x )')
|
||||
} else {
|
||||
// Not killed.
|
||||
}
|
||||
exit(err.code()) // `err.code()` here contains the command exit status.
|
||||
} else {
|
||||
// Another error occurred. Most likely, something went wrong while executing
|
||||
// the process creation system calls. Check `err.code()` to get the concrete
|
||||
// error, it contains the standard C errno value.
|
||||
// See https://www.man7.org/linux/man-pages/man3/errno.3.html
|
||||
|
||||
// Replace 0 to actual errno value (real errno never be zero).
|
||||
if err.code() == 0 {
|
||||
// Do something here...
|
||||
}
|
||||
|
||||
// Fallback to panic.
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
println(out)
|
||||
}
|
||||
59
examples/stream_input_and_output.v
Normal file
59
examples/stream_input_and_output.v
Normal file
@@ -0,0 +1,59 @@
|
||||
import io.string_reader
|
||||
import rand
|
||||
import runcmd
|
||||
import time
|
||||
|
||||
fn main() {
|
||||
// Prepare the command.
|
||||
mut cmd := runcmd.new('cat')
|
||||
|
||||
// Setup I/O redirection.
|
||||
cmd.redirect_stdio = true
|
||||
|
||||
// Start a process.
|
||||
// Note: File descriptors will only become available after the process has started!
|
||||
pid := cmd.start()!
|
||||
println('Child process started with pid ${pid}')
|
||||
|
||||
// Get child file descriptors.
|
||||
mut child_stdin := cmd.stdin()!
|
||||
mut child_stdout := cmd.stdout()!
|
||||
|
||||
// Prepare reader to store command output.
|
||||
mut output := string_reader.StringReader.new(reader: child_stdout)
|
||||
|
||||
// Start stdout reading in a coroutine.
|
||||
//
|
||||
// The reader will be block until the descriptor contains data.
|
||||
// Therefore, to avoid blocking the main thread, we start the reader
|
||||
// in a coroutine.
|
||||
go fn [mut output] () {
|
||||
println('STDOUT reader started!')
|
||||
// Read stdout line by line until EOF.
|
||||
for {
|
||||
line := output.read_line() or { break }
|
||||
println('Recv: ${line}')
|
||||
}
|
||||
}()
|
||||
|
||||
// Start sending data to child in a loop.
|
||||
limit := 5
|
||||
for _ in 0 .. limit {
|
||||
// Generate some data.
|
||||
data := rand.string(10) + '\n'
|
||||
print('Send: ${data}')
|
||||
|
||||
// Write data to child stdin file descriptor.
|
||||
_ := child_stdin.write(data.bytes())!
|
||||
|
||||
// Sleep a bit for demonstration.
|
||||
time.sleep(500 * time.millisecond)
|
||||
}
|
||||
|
||||
// Close stdin by hand so that the child process receives EOF.
|
||||
// Without this child will hang for waiting for input.
|
||||
child_stdin.close()!
|
||||
|
||||
// wait() will close the child stdout file desciptor by itself.
|
||||
cmd.wait()!
|
||||
}
|
||||
28
examples/stream_output.v
Normal file
28
examples/stream_output.v
Normal file
@@ -0,0 +1,28 @@
|
||||
import io.string_reader
|
||||
import runcmd
|
||||
|
||||
fn main() {
|
||||
// Prepare command.
|
||||
mut cmd := runcmd.new('sh', '-c', r'for i in {1..5}; do echo line $i; sleep .5; done; echo finish!')
|
||||
|
||||
// This is required to captute standart I/O streams.
|
||||
cmd.redirect_stdio = true
|
||||
|
||||
// Start child process.
|
||||
pid := cmd.start()!
|
||||
println('Child process started with pid ${pid}')
|
||||
|
||||
// Setup StringReader with stdout input. Note the cmd.stdout()! call, it
|
||||
// returns the io.Reader interface and reads child process stdout file descriptor.
|
||||
mut reader := string_reader.StringReader.new(reader: cmd.stdout()!)
|
||||
|
||||
// Read sdtout line by line until EOF.
|
||||
for {
|
||||
line := reader.read_line() or { break }
|
||||
println('Read: ${line}')
|
||||
}
|
||||
|
||||
cmd.wait()! // Wait to child process completed.
|
||||
|
||||
println('Child state: ${cmd.state}')
|
||||
}
|
||||
38
examples/write_to_child_stdin.v
Normal file
38
examples/write_to_child_stdin.v
Normal file
@@ -0,0 +1,38 @@
|
||||
import io.string_reader
|
||||
import strings
|
||||
import runcmd
|
||||
|
||||
fn main() {
|
||||
input := 'Hello from parent process!'
|
||||
|
||||
// Prepare reader and writer.
|
||||
//
|
||||
// * `reader` reads input from the parent process; it will be copied to the
|
||||
// standard input of the child process.
|
||||
// * `writer` accepts data from the child process; it will be copied from the
|
||||
// standard output of the child process.
|
||||
mut reader := string_reader.StringReader.new(reader: runcmd.buffer(input.bytes()), source: input)
|
||||
mut writer := strings.new_builder(4096)
|
||||
|
||||
// Prepare the command.
|
||||
mut cmd := runcmd.new('cat')
|
||||
|
||||
// Set redirect_stdio to perform I/O copying between parent and child processes.
|
||||
cmd.redirect_stdio = true
|
||||
|
||||
// Setup reader and writer for child I/O streams.
|
||||
cmd.stdin = reader
|
||||
cmd.stdout = writer
|
||||
|
||||
// Start and wait for command.
|
||||
cmd.run()!
|
||||
|
||||
// Get command output as string.
|
||||
output := writer.str()
|
||||
|
||||
// Make sure that `cat` returned the same data that we sent to it as input.
|
||||
assert input == output, 'output data differs from input!'
|
||||
|
||||
println('Child state: ${cmd.state}')
|
||||
println('Child output: ${output}')
|
||||
}
|
||||
Reference in New Issue
Block a user