philiprehberger-task_runner

Tests Gem Version Last updated

Shell command runner with output capture, timeout, streaming, signal handling, and stdin piping

Requirements

  • Ruby >= 3.1

Installation

Add to your Gemfile:

gem "philiprehberger-task_runner"

Or install directly:

gem install philiprehberger-task_runner

Usage

require "philiprehberger/task_runner"

result = Philiprehberger::TaskRunner.run('ls', '-la')
puts result.stdout
puts result.exit_code    # => 0
puts result.success?     # => true
puts result.duration     # => 0.012

Raising on Failure

# Raises CommandError if the command exits non-zero
result = Philiprehberger::TaskRunner.run!('make', 'build')

# The error includes the full Result for inspection
begin
  Philiprehberger::TaskRunner.run!('false')
rescue Philiprehberger::TaskRunner::CommandError => e
  puts e.message          # => "command exited with code 1"
  puts e.result.stderr    # => captured stderr
end

Timeout

result = Philiprehberger::TaskRunner.run('long-process', timeout: 30)

Environment Variables and Working Directory

result = Philiprehberger::TaskRunner.run(
  'make', 'build',
  env: { 'DEBUG' => '1' },
  chdir: '/path/to/project'
)

Signal Handling

result = Philiprehberger::TaskRunner.run(
  'long-process',
  timeout: 30,
  signal: :TERM,
  kill_after: 5
)
# On timeout: sends SIGTERM first, then SIGKILL after 5 seconds if still running
# result.signal reports which signal killed the process (:TERM, :KILL, or nil)

Input Piping

result = Philiprehberger::TaskRunner.run('cat', stdin: "hello world")
puts result.stdout  # => "hello world"

# Also accepts IO objects
result = Philiprehberger::TaskRunner.run('wc', '-l', stdin: File.open('data.txt'))

Streaming Output

Philiprehberger::TaskRunner.run('tail', '-f', '/var/log/app.log', timeout: 10) do |line|
  puts ">> #{line}"
end

Stderr Streaming

Philiprehberger::TaskRunner.run('make', 'build') do |line, stream|
  case stream
  when :stdout then puts "OUT: #{line}"
  when :stderr then puts "ERR: #{line}"
  end
end

API

Method / Class Description
.run(cmd, *args, timeout:, env:, chdir:, signal:, kill_after:, stdin:) Run a command and return a Result
.run!(cmd, *args, **opts) Same as run, raises CommandError on non-zero exit
CommandError#result The failed Result object
`.run(cmd) { \ line\
`.run(cmd) { \ line, stream\
Result#stdout Captured standard output
Result#stderr Captured standard error
Result#exit_code Process exit code
Result#success? Whether exit code is 0
Result#failure? Logical inverse of #success?
Result#duration Execution time in seconds
Result#signal Signal that killed the process (:TERM, :KILL, or nil)
Result#timed_out? Whether the process was killed for exceeding its timeout
Result#to_h Hash representation of the result (includes :success and :timed_out)

Development

bundle install
bundle exec rspec
bundle exec rubocop

Support

If you find this project useful:

Star the repo

🐛 Report issues

💡 Suggest features

❤️ Sponsor development

🌐 All Open Source Projects

💻 GitHub Profile

🔗 LinkedIn Profile

License

MIT