### Create a robust command wrapper with Open4 Source: https://context7.com/ahoward/open4/llms.txt A comprehensive example of wrapping Open4::popen4 to handle command execution, input piping, output capturing, and error management in a structured return format. ```ruby require 'open4' def run_command(command, input: nil, timeout: nil, cwd: nil) stdout_buf = '' stderr_buf = '' pid = nil begin status = Open4::popen4(command) do |p, stdin, stdout, stderr| pid = p if input stdin.puts input end stdin.close stdout_buf = stdout.read stderr_buf = stderr.read end { pid: pid, stdout: stdout_buf, stderr: stderr_buf, status: status.exitstatus, success: status.exitstatus == 0 } rescue Errno::ENOENT => e { pid: nil, stdout: '', stderr: e.to_s, status: 127, success: false } rescue Timeout::Error => e { pid: pid, stdout: stdout_buf, stderr: "Timeout: #{e}", status: -1, success: false } end end ``` -------------------------------- ### bg/background - Asynchronous Process Execution in Ruby Source: https://context7.com/ahoward/open4/llms.txt The `bg` or `background` method in Open4 executes a process asynchronously in a separate thread. It returns a thread object that provides methods to access the process ID (`pid`), block until completion to get the exit code (`exitstatus`), and retrieve the full status object (`spawn_status`). This is ideal for non-blocking operations. ```ruby require 'open4' include Open4 stdin = "42\n" stdout = '' stderr = '' # Start background process t = bg('ruby -e "sleep 2; puts ARGF.read"', 0 => stdin, 1 => stdout, 2 => stderr) # Get the PID immediately (non-blocking) puts "Started process: #{t.pid}" # Check thread status while running while t.status puts "Thread status: #{t.status}" # "run" or "sleep" sleep 0.5 end # t.exitstatus blocks until process completes puts "Exit status: #{t.exitstatus}" # => 0 puts "Output: #{stdout}" # => "42\n" # Multiple background processes threads = [] 3.times do |i| threads << bg("ruby -e 'sleep #{i}; puts #{i}'", 1 => STDOUT) end # Wait for all to complete threads.each { |t| t.exitstatus } ``` -------------------------------- ### Execute code in child processes with Open4.pfork4 Source: https://context7.com/ahoward/open4/llms.txt Demonstrates running Ruby code in isolated child processes. It covers basic I/O communication, exception propagation from child to parent, and graceful process termination. ```ruby echo_lambda = lambda do input = $stdin.read $stdout.write "Processed: #{input}" end result = '' Open4.pfork4(echo_lambda) do |cid, stdin, stdout, stderr| stdin.write "Hello from parent" stdin.close result = stdout.read end puts result failing_lambda = lambda do $stdout.write $stdin.read raise RuntimeError, "Something went wrong in child" end begin Open4.pfork4(failing_lambda) do |cid, stdin, stdout, stderr| stdin.write "data" stdin.close stdout.read end rescue RuntimeError => e puts "Caught exception from child: #{e.message}" end ``` -------------------------------- ### spawn - Convenient Command Execution in Ruby Source: https://context7.com/ahoward/open4/llms.txt The `spawn` method in Open4 offers a higher-level interface for command execution, accepting various input types for stdin and supporting flexible output redirection to stdout/stderr. It can handle multiple exit statuses, ignore failures, set working directories, and process output via lambdas. It raises `Open4::SpawnError` on non-zero exit status by default. ```ruby require 'open4' include Open4 # Basic spawn with string I/O stdout, stderr = '', '' status = spawn('cat', 'stdin' => "Hello World\n", 'stdout' => stdout, 'stderr' => stderr) puts stdout # => "Hello World\n" # Using numeric keys (0=stdin, 1=stdout, 2=stderr) out, err = '', '' spawn('ruby -e "puts ARGF.read.upcase"', 0 => 'test input', 1 => out, 2 => err) puts out # => "TEST INPUT\n" # Using arrays for command arguments (useful for special characters) spawn(['touch', 'file with spaces.txt'], :stdout => STDOUT) # Accept multiple exit statuses spawn('ruby -e "exit 42"', :exitstatus => [0, 42]) # Ignore exit failures with :status => true status = spawn('ruby -e "exit 1"', :status => true) puts status.exitstatus # => 1 # Working directory option spawn('pwd', 1 => STDOUT, :cwd => '/tmp') # => /tmp # Using a lambda/proc for stdout processing cmd = 'ruby -e "3.times { |i| puts i }"' spawn(cmd, :stdout => lambda { |buf| puts "Received: #{buf}" }) # Handle spawn errors begin spawn('ruby -e "exit 1"') rescue Open4::SpawnError => e puts "Command failed with status: #{e.exitstatus}" puts "Full status: #{e.status.inspect}" end ``` -------------------------------- ### Configure execution timeouts with Open4 Source: https://context7.com/ahoward/open4/llms.txt Shows how to implement timeouts for commands, stdout, and stdin operations. It uses the :timeout, :stdout_timeout, and :stdin_timeout options to prevent processes from hanging. ```ruby require 'open4' include Open4 begin spawn('sleep 10', :timeout => 2) rescue Timeout::Error puts "Command timed out after 2 seconds" end begin spawn('ruby -e "sleep 5; puts 42"', :stdout_timeout => 2) rescue Timeout::Error puts "No stdout received within 2 seconds" end ``` -------------------------------- ### popen4 - Basic Process Execution in Ruby Source: https://context7.com/ahoward/open4/llms.txt The `popen4` method in Open4 allows for basic execution of child processes, returning handles for PID, stdin, stdout, and stderr. It supports both direct and block forms, with automatic exception marshaling from child to parent for failed exec calls. It's useful for direct interaction with shell commands. ```ruby require "open4" # Direct form - manual process management pid, stdin, stdout, stderr = Open4::popen4("sh") stdin.puts "echo 'Hello from stdout'" stdin.puts "echo 'Error message' 1>&2" stdin.close ignored, status = Process::waitpid2(pid) puts "PID: #{pid}" puts "STDOUT: #{stdout.read.strip}" # => "Hello from stdout" puts "STDERR: #{stderr.read.strip}" # => "Error message" puts "Exit Status: #{status.exitstatus}" # => 0 # Block form - automatic process waiting status = Open4::popen4("sh") do |pid, stdin, stdout, stderr| stdin.puts "ls /tmp" stdin.close puts "Process ID: #{pid}" puts "Output: #{stdout.read}" end puts "Exit status: #{status.exitstatus}" # Exception handling for non-existent commands begin Open4::popen4("nonexistent_command") rescue Errno::ENOENT => e puts "Command not found: #{e.message}" end ``` -------------------------------- ### pfork4 - Fork with Ruby Code Execution in Ruby Source: https://context7.com/ahoward/open4/llms.txt The `pfork4` method in Open4 allows for executing a Ruby lambda or proc within a child process, similar to `popen4` but without needing an external command. It ensures that exceptions raised in the child process are automatically propagated back to the parent process, simplifying error handling in forked Ruby code. ```ruby require 'open4' ``` -------------------------------- ### Manage process lifecycle with Open4 utilities Source: https://context7.com/ahoward/open4/llms.txt Utilizes Open4.alive? to check process status and Open4.maim to terminate processes using escalating signals like SIGTERM and SIGKILL. ```ruby require 'open4' include Open4 t = bg('sleep 60', 1 => '') pid = t.pid puts Open4.alive?(pid) killed = Open4.maim(pid) puts "Process killed: #{killed}" Open4.maim(pid, :signals => %w(SIGTERM SIGKILL), :suspend => 2 ) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.