Shell Elf
github.com/outoftime/shell_elf
Shell Elf is a small, standalone daemon whose sole purpose is to read shell commands out of a Starling queue, execute them, and optionally POST back to an HTTP service on success or failure. Shell Elf is distributed as a RubyGem, but is not meant to be included as a library; rather, it contains the standalone ‘shell-elf` executable, which starts and stops the daemon.
Features
-
Send a single shell command or a batch of commands to be executed serially
-
Specify postback URLs for success and failure, so that your application can be notified when batch has completed.
-
Gracefully catch TERM and INT signals, either finishing the current batch or requeueing it for later processing before exiting.
Usage
Installation
sudo gem install outoftime-shell_elf --source=gems.github.com
Starting the daemon
shell-elf start -- [options]
The following options are available; none are required:
- -q/–queue
-
name of the Starling queue to read from (default: shell_elf)
- -h/–host
-
hostname at which the Starling daemon is running (default: localhost)
- -p/–port
-
port on which the Starling daemon is listening (default: 22122)
- –log-file
-
full path to a log file (default: no logging)
- –log-level
-
level at which to log (default: WARN)
Stopping the daemon
shell-elf stop
Sending commands from your application
require 'rubygems'
gem 'starling-starling'
require 'starling'
starling = Starling.new('localhost:22122')
# send the single command `touch /tmp/hey`
starling.set('shell_elf', :command => ['touch', '/tmp/hey'])
# send the two commands `touch /tmp/one` followed by `touch /tmp/2`
starling.set('shell_elf', :commands => [['touch', '/tmp/one'], ['touch', '/tmp/two']])
# send a command with success/failure postbacks
starling.set('shell_elf', :command => ['touch', '/tmp/hey'],
:options => { :success => { 'http://localhost:3000/command/success' },
{ :failure => { 'http://localhost:3000/command/failure' }})
# send a command with instructions to requeue if the daemon is interrupted
starling.set('shell_elf', :command => ['sleep', '120'],
:options => { :on_interrupt => :requeue })
A note about batches and postbacks
If the postbacks are specified (you can specify neither, either, or both), ShellElf will send an HTTP POST request to the specified URL. The batch is considered successful if all of the commands exit with a status code of 0. If one of the commands in the batch exits with a non-zero status code, *the rest of the commands in the batch are not run*, and the failure postback will be sent. ShellElf waits until the postback request completes before retrieving the next batch from the queue.
The ShellElf Client
…doesn’t exist. I’m a big fan of libraries presenting intuitive APIs to the application layer, but in this case a general-purpose client would be so trivial that it doesn’t seem worth writing one. Further, I assume that in the general use case, applications will want to build task-specific APIs that wrap the task of shelling out via Starling. Having a further layer of abstraction doesn’t seem to add much value.
Dependencies
-
escape
-
starling-starling
-
daemons
-
choice
Contact and Futher Reading
Contact: Mat Brown <[email protected]> Further Reading: outofti.me/tagged/shell_elf
The MIT License
Copyright © 2009 Mat Brown
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.