Allow passing an env var hash to commands
This updates the `Command` class to take a hash for passing env variables. These are passed to the `popen4` call and are set as environment variables for the child process. This allows passing sensitive env vars like passwords without putting them in the command string.
This adds the `rubysl` gem to the rbx platform. It is needed to run the test suite on Rubinius.
* some minor cleanups to the gem meta (4451e18) * some general cleanups and modernizations (#16) * have `RunError` *optionally* take a custom backtrace (#17) * read output from stdout and stderr while cmd is running (#18) * Add a bench mark script to help measure performance impact of changes (#20) * use a "self-pipe" to handle cmd timeouts (#21) * Some minor tweaks to the setup (#22) /cc @jcredding
Some minor tweaks to the setup
This breaks resetting the attributes into its own method and makes the setup/teardown more about setting up or tearing down cmd runs. This is a slight improvement in code organization with no behavior changes.
This switches to defining a stop "self-pipe" for signaling when the child process has exited. Intead of looping in the `wait_for_exit` and checking if you've timed out every `WAIT_INTERVAL`, you instead just select on the stop pipe with a timeout (or not). The thread streaming the child process output also checks if the child process has exited. If it has the stream thread writes to the stop pipe which triggers the wait to end.
Add a bench mark script to help measure performance impact of changes
This add a bench mark script that measures running cmds multiple times and writes the results so we can know how a change impacts performance.
read output from stdout and stderr while cmd is running
This updates the cmd to begin reading from stdout and stderr as soon as the cmd has started running. This is accomplished by starting a thread that reads `READ_SIZE` bytes from the io as long as the cmd is running. Data is read using `read_nonblock` and new data is detected using `IO.select`. As before, calling `wait` if the cmd was started asynchronously is highly recommended (this either waits for the cmd to finish or times out). Either way, this ensures the read output thread is exited and the exitstatus captured. This is handled automatically if the cmd is started synchronously using `run`. The goal here is to prevent "deadlock" scenarios where a cmd can't finish b/c it has filled up one of the output streams. It also enables output "streaming" as output will now be available for inspecting as soon as it is written. I've added some deadlock tests where I test both a `cat` cmd on both a small and big file. The big file is larger than 64k (the default buffer size of stdout). Both execute the cmd just fine without deadlocking and timing out on the `.wait(1)`. This test fails without these changes. To accomplish this, I also remodeled the command's "run data" as a "child process" object. This is a more appropriate name for the data and behavior this is encapsulating. This allows the same access to the child process' data and allows us to abstract child process handling behavior in this object. Finally, this switches to _not_ stripping any read output. This is necessary b/c we are now streaming output but also good b/c we want to preserve the output exactly as the cmd produced it.
have `RunError` *optionally* take a custom backtrace
This updates the RunError custom exception to be optionally created with a custom backtrace. If none is provided, it falls back to the `caller`. This makes it behave like any other exception class.
some general cleanups and modernizations
* add `license` to gemspec * require latest assert * modernize tests No behavior changes - just cleanups.
* needed to kick rubygems so 2.1.x will install with bundler * b/c of a rubygems bug this morning
Run cmds asynchronously: start, wait, stop, kill
This adds an API for running cmds and explicitly waiting for them to exit. This updates the original `run` implementation to just be a macro to `start` then `wait`. Closes #9.
This is so you don't need to track state of each attr individually.
reworked pid status gathering using `waitpid2`
Also removed Errno::ENOENT handling as it is not needed anymore with moving to posix_spawn. Finally, moved status gathering to after the wait pid call.
updated and modernized
Updated to latest gem lib standards from https://github.com/kellyredding/ggem. Updated for use with Assert 2.0.
* using posix-spawn to execute the commands * renamed `exitcode` to `exitstatus` * renamed `Scmd::Command::Failure` to `Scmd::RunError` * more appropriate backtraces on `Scmd::RunError` exceptions * supports jruby
renaming the `exitcode` attribute to `exitstatus`
better exceptions when running commands
using 'posix-spawn' instead of 'open4'