Skip to content

A Simple, Capable, and Unified Interface for Managing Subprocesses in Ruby

License

Notifications You must be signed in to change notification settings

michaeleisel/Exeggutor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

35 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Exeggutor 🌴

A Simple, Capable, and Unified Interface for Managing Subprocesses in Ruby

Tired of juggling system(...), `...`, and Open3? Exeggutor provides one simple method that handles many different use cases - safely spawn processes with real-time output, captured stdout/stderr, and sane error handling.

From this:

Before using Exeggutor

To this:

After using Exeggutor

Examples

# Copy old_file to #{new_dir}/foo, and raise an exception if it fails
exeg(%W[cp #{old_file} #{new_dir}/foo]) # Exception raised by default on failure

# Collect stdout from a long-running build task while showing the progress updates as they're
# printed out to stderr
output = exeg(%W[run_build.sh], show_stderr: true).stdout

# Lots of overrides
result = exeg(
  %W[foo bar],
  env: {SOME_OVERRIDE: "1"}, # Override env vars
  chdir: "/path/to/...", # Run the process in a different working directory
  can_fail: true, # Don't throw an exception, handle the error manually or ignore
  stdin: "foo", # Send this data to stdin as soon as the process starts
)

# Async execution - like popen3, but without its deadlock issue
handle = exeg_async(%W[long_running_process.sh])
handle.stdin.write("request")
response = handle.stdout.gets

Overview

Although Ruby has many different ways of running a subprocess, they all have various drawbacks and quirks. Also, some of the most convenient ways of calling a process, e.g. with backticks, are the most dangerous, because they spawn a subshell. Here's an overview of how Exeggutor solves these shortcomings:

Problem with Standard Ruby APIs Exeggutor Solution
Subshells are slow to spawn, error-prone, and insecure Exeggutor never uses a subshell and always runs processes directly
Non-subshells use ugly varargs syntax (e.g. system('cp', old, "#{new}/foo")) Exeggutor encourages elegant %W syntax by taking an array for the arguments parameter (e.g. exeg(%W[cp #{old} #{new}/foo]))
Process failures are silent, requiring manual checks Exeggutor raises an exception on failure by default (with rich error context)
No simple way to both capture stdout/stderr as strings afterwards and also print them to the shell in real-time Exeggutor always captures stdout/stderr, and can optionally print them in real-time
Different APIs for different use cases Exeggutor provides a single method for blocking calls and another for non-blocking execution, with smart defaults and flexible named parameters

Installation

gem install exeggutor

Documentation

Docs are available here.

About

A Simple, Capable, and Unified Interface for Managing Subprocesses in Ruby

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages