Files | Admin

Notes:

Release Name: 0.8.3

Notes:
= Rye - v0.8

Safely run SSH commands on a bunch of machines at the same time (from Ruby).

Rye is similar to Rush[http://rush.heroku.com] but everything happens over SSH (no HTTP daemon) and the default settings are less powerful (for safety). For example, file globs and the "rm" command are disabled so unless otherwise specified, you can't do this: <tt>rbox.rm('-rf', '/etc/**/*')</tt>.


== Installation

One of:

    $ sudo gem install rye
    $ sudo gem install delano-rye --source http://gems.github.com/
    $ git clone git://github.com/delano/rye.git


See bin/try for examples!


== EXAMPLE 1 -- SSH Authorization

Does it annoy you to manually authorize remote SSH accounts? Rye can help!

Enable passwordless logins to HOST1 and HOST2:

    $ rye authorize HOST1 HOST2    

This will copy your public SSH keys to the <tt>~/.ssh/authorized_keys</tt> and <tt>~/.ssh/authorized_keys2</tt> files on the remote machine(s). 

See <tt>rye -h</tt> for more info
    
    
== EXAMPLE 2 -- Basic Usage
    
    rbox = Rye::Box.new('localhost')
    rbox.uptime                            # => 11:02  up 16:01, 3 users
    rbox['/usr/bin'].pwd                   # => /usr/bin
    
You can specify environment variables

    rbox.setenv(:RYE, "Forty Creek")
    rbox.env             # => ['HOME=/home/rye', 'RYE=Forty Creek', ...]
    
    
== EXAMPLE 3a -- Accessing Multiple Machines

    rset = Rye::Set.new
    rbox = Rye::Box.new
    
    rset.add_boxes(rbox, 'localhost')      # Add boxes as hostnames or objects
    
Calling methods on Rye::Set objects is very similar to calling them on Rye::Box objects. In fact, it's identical:

    p rset.uptime        # => [[14:19:02 up 32 days, 19:35 ...], [14:19:02 up 30 days, 01:35]]
    p rset['/etc'].ls    # => [['file1', 'file2', ...], ['life1', 'life2', ...]]
    
== EXAMPLE 3b -- Accessing Multiple Machines -- In Parallel
   
By default, Rye:Set connects to each machine sequentially in the order they were added to the set. Commands can also be run in parallel:

   rset = Rye::Set.new('set-name', :parallel => true)
     OR
   rset.parallel = true
   
   
== EXAMPLE 4 -- File Transfers

    rbox = Rye::Box.new("localhost", :info => true)

    dir_upload = "#{Rye.sysinfo.tmpdir}/rye-upload/"
    dir_download = "#{Rye.sysinfo.tmpdir}/rye-download/"
    
    rbox.file_upload("#{RYE_HOME}/README.rdoc", "#{RYE_HOME}/LICENSE.txt", dir_upload)

    applejack = StringIO.new("Some in-memory content")
    rbox.file_upload(applejack, "#{dir_upload}/applejack.txt")

    p rbox.ls(dir_upload)      # => [README.rdoc, LICENSE.txt, applejack.txt]
    p rbox.cat("#{dir_upload}/applejack.txt")   # => "Some in-memory content"

    filecontent = StringIO.new
    rbox.file_download("#{dir_upload}/applejack.txt", filecontent)

    p filecontent.read

== EXAMPLE 5 -- Local processes

For local processes, you can bypass <tt>Rye::Box</tt> and execute commands directly with <tt>Rye.shell</tt>:

    Rye.shell :uptime    # => 11:02  up 16:01, 3 users


The first argument must be the command name and the remaining arguments are sent directly as arguments to the command. They're not escaped like with <tt>Rye::Box</tt> so you can use the asterisk, environment variables, pipes, and redirects etc. Also note that you can specify single character switches as symbols and you can separate arguments or put them into a single String.

    Rye.shell :ls, '*'
    Rye.shell :ls, '-l $HOME'
    Rye.shell :ls, :l, '$HOME > $TMPDIR/crazy.txt'

The return value is a Rye::Rap object (just like with Rye::Box) so you have access to the exit code and STDERR output:

    ret = Rye.shell :ls, 'nofile'
    ret.exit_code        # => 1
    ret.stderr           # => "sh: nofile: No such file or directory"
    ret.class            # => Rye::Rap



== About Safe-Mode

In safe-mode:

* You can't use file globs. This means you can't do this: <tt>rbox.ls('*.rb')</tt>. <tt>~</tt> also doesn't work!
* You can't use environment variables as arguments. This means you can't do this: <tt>rbox.echo('$HOME')</tt>. However, environment variables are available to the commands you run.
* Pipes and operators don't work: <tt>|, &&, >, <, ||, ~</tt>, etc...
* Backticks don't work either: <tt>procs=`ps aux`</tt>

Why? In safe-mode, all command arguments are escaped which turns all arguments into their literal values. 

Using a Ruby interface to execute shell commands is pretty awesome, particularly to run them on several machines simultaneously. That's a lot of power and it's potentially very dangerous. That's why Rye disables this stuff by default. There's probably a way to do it safely but it's not obvious yet (to me). If you have any ideas, I'd love to hear them!


== Command Whitelist

Rye permits only a limited number of system commands to be run. This default whitelist is defined in Rye::Cmd[http://github.com/delano/rye/blob/master/lib/rye/cmd.rb] but you can add your own commands as you please (see Example 3).

== Dependencies

* OpenSSL[http://www.openssl.org] (The C library)
* Ruby Gems:
  * net-ssh
  * net-scp
  * highline
  * drydock
  * sysinfo
  * storable


== Known Issues

This list will grow. If you find one let me know!

* Rye doesn't read the ~/.ssh/config file yet
* Rye uses OpenSSL's ssh-agent (if it exists). Rye starts it up as a child process and shuts it down using at_exit. If you have code in an at_exit that rely's on Rye, make sure your code runs before Rye's at_exit block is called. For example, Drydock uses at_exit too which is why in bin/rye you can see that Drydock is called explicitly so that Rye's at_exit is executed after Drydock executes a command. 


== Thanks

* Solutious Incorporated (http://solutious.com) for all the orange juice.
* Kalin Harvey (http://rely.ca)
* Rush[http://github.com/adamwiggins/rush]
* Capistrano[http://github.com/jamis/capistrano/blob/master/lib/capistrano/shell.rb]


== More Info

* GitHub[http://github.com/delano/rye]
* Rdocs[http://delano.github.com/rye]
* Inspiration[http://www.youtube.com/watch?v=_StUVh6ENuw]

== Credits

* Delano Mandelbaum (delano@solutious.com)
* Escape, Copyright (C) 2006,2007 Tanaka Akira <akr@fsij.org>
* Rye::Box#instance_exec (for Ruby 1.8) Mauricio Fernandez

== License

See: LICENSE.txt


Changes: RYE, CHANGES TODO * Re-implement Rye::Rap as an Observable StringIO object for dynamic printing of output. * Fingerprints: ssh-keygen -l -f id_rsa_repos.pub #### 0.8.3 (2009-06-30) ############################# * ADDED: JRuby 1.3 support * ADDED: Tryouts (i.e. better testing) #### 0.8.2 (2009-06-23) ############################# * FIXED: Rye::Box.switch_user will disconnect but not create a new connection. * FIXED: Rye::Cmd#add_command hard coded argument handling for blocks * CHANGE: Rye::Rap#to_s now returns stdout.join($/) * CHANGE: Regexp workaround for remote password prompts is now case insensitive. * ADDED: Rye::Cmd#string_upload and Rye::Cmd#string_download * ADDED: Rye.shell example to README (thanks rogerdpack) #### 0.8.1 (2009-06-22) ############################# * FIXED: file_upload now handles globs like a champ * FIXED: Handling of relative paths in Rye::Box#cd and Rye::Box#[] * ADDED: file_upload now assumes uploading to home directory when only 1 arg * ADDED: Rudyfile for remote 'clean-machine' tests * CHANGE: guess_user_home, ostype, and getenv now run quietly #### 0.8.0 (2009-06-21) ############################# * FIXED: safely and unsafely (Rye::Box) now return the block return value * ADDED: Rye::Set#parallel and Rye::Set#parallel= methods * ADDED: Rye::Box#quietly * CHANGE: Updated Rye::Set#inspect and Rye::Set#to_s * CHANGE: Exception hook now receives: ex, cmd, user, host, nickname * CHANGE: Increased Kernel.sleep to 0.03 in Rye::Set.run_command_parallel * CHANGE: Renamed Rye::Cmd#upload and Rye::Cmd#download to file_upload and file_download * CHANGE: Rye::Cmd#file_exists? now executes quietly (doesn't pollute logging) #### 0.7.6 (2009-06-19) ############################# * FIXED: Raise Rye::NoPty exception when Net::SSH returns message "Pseudo-terminal will not be allocated because stdin is not a terminal." * FIXED: Rye::Box#disconnect would hang in some instances. Now waits 3 seconds. * FIXED: Bug in net_ssh_exec which was causing it to not return an exit code * CHANGE: All exceptions now inherit from Rye::Error (Runtimerror) * CHANGE: A NoPassword exception is raised when a password prompt returns nil. * CHANGE: pre_command_hook block arguments have changed: NEW: complete command, user, host, nickname OLD: command, args, user, host, nickname #### 0.7.5 (2009-06-13) ############################# * FIXED: Rye::Set methods were not accepting or passing blocks. * ADDED: Rye::Set#user and Rye::Set#opts methods * ADDED: Rye::Box#nickname * ADDED: exception hooks for Rye::Box. * CHANGE: Rye::Set method missing now forwards to Rye::Box methods instead of Rye::Cmd #### 0.7.4 (2009-06-04) ############################# * FIXED: Bug in Rye::Box#interactive_ssh related to instance variable renaming from 0.7.0. * FIXED: Bug in Rye::Cmd#file_append which tried to download files that didn't exist * CHANGE: Removed error message, "EC2 instances generate new SSH keys on first boot" * ADDED: Rye::Cmd#remove_method * ADDED: Rye::Rap#> and Rye::Rap#>> methods to emulate shell redirect to file #### 0.7.3 (2009-06-03) ############################# * ADDED: enable_safe_mode and disable_safe_mode methods * ADDED: New default Rye::Cmd methods: gzip, bzip, tar and all derivatives. ./configure and make too. * ADDED: Rye::Cmd#safely and Rye::Cmd#unsafely methods * ADDED: Rye::Cmd#digest_md5, Rye::Cmd#digest_sha1, Rye::Cmd#digest_sha2 methods * ADDED: Rye::Cmd#file_verified? method * ADDED: Rye::Box#net_ssh_exec! now checks and correctly prompts for a sudo response password. Note: this will be upgraded in for 0.8 to support any prompt. * FIXED: Net::SSH paranoid now set to false when safe mode is disabled. #### 0.7.2 (2009-06-01) ############################# *A re-release of 0.7.1 to force Rubyforge to update the gem* #### 0.7.1 (2009-06-01) ############################# * CHANGE: Removed broken grep method from Rye::Rap * FIXED: Bug which prevented setting relative paths in non-home directory * ADDED: Rye::Cmd#add_command helper for adding new command methods. * ADDED: pre-command-hook now sends the hostname to the block #### 0.7.0 (2009-05-30) ############################# * CHANGE: Rye::Box now uses unique instance variable names to encourage using instance variables in batch command blocks. * ADDED: Rye::Box#file_append #### 0.6.6 (2009-05-21) ############################# * CHANGE: Key management is handled by ssh-agent again (instead of Net::SSH) #### 0.6.5 (2009-05-10) ############################# * CHANGE: Default exit code is now 0 instead of -1 * CHANGE: Removed Sys (using sysinfo gem) * CHANGE: Removed vendor/highline-1.5.1 (it's now available via gem) #### 0.6.4 (2009-05-04) ############################# * FIXED: authorize_remote was not returning to the directory it started with. * ADDED: pre and post command hooks to Rye::Box * ADDED: Rye::Box.batch * ADDED: Support for OS X for Rye::Box.guess_user_home #### 0.6.3 (2009-05-02) ############################# * FIXED: Rye::Box.guess_user_home wasn't handling the username arg (only using default name) * ADDED: Rye::Cmd.can? * ADDED: Rye::Cmd.ostype #### 0.6.2 (2009-04-29) ############################# * FIXED: I forgot to add highline to the gemspec file manifest. Cripes! #### 0.6.1 (2009-04-29) ############################# * ADDED: Prints message to STDERR when passwordless login fails. * ADDED: Highline 1.5.1 to vendor to fix the Ruby 1.9 issue (Highline 1.5.1 is not released as a gem yet) * CHANGE: Cleaned examples and links in README #### 0.6.0 (2009-04-28) ############################# * FIXED: handling of Process::Status ($?) in Rye.shell * FIXED: Removed reference to Rudy::Error in bin/rye * ADDED: Rye::Box.getenv * ADDED: Rye::Box.can? * ADDED: Rye::Box.umask= (a similar work around as cd / []) * ADDED: Rye::Box.file_exists? * ADDED: Rye::Box.authorize_keys_remote can now authorize for a different user * ADDED: Rye::Box.upload and Rye::Box.download * ADDED: Rye::SystemInfo.tmpdir * CHANGE: Rye::Box.prep_args doesn't treat multicharacter Symbols as command-line options any more (single character ones are still converted) * CHANGE: Renamed Rye::Box.add_env to Rye::Box.setenv * CHANGE: rm and kill are available in Rye::Cmd by default * CHANGE: Rye::Box.authorize_keys renamed Rye::Box.authorize_keys_remote * CHANGE: The Rye::Rap object now contains the exit code as an integer for Rye.shell and Rye::Box.run_command (SSH) commands. * UPDATED: Rdocs and README #### 0.5.4 (2009-04-22) ############################# * FIXED: Sys is now returning environment paths and home path in JRuby. * ADDED: Better Interrupt handling * ADDED: Rings terminal bell when asks to Continue after HostKey error. * CHANGE: Removed require 'rubygems' #### 0.5.3 (2009-04-20) ############################# * FIXED: Rye::Box.connect raises exceptions instead of exits * ADDED: Rye::Box.connect now rescues HostKeyMismatch exceptions and prompts for a response. #### 0.5.2 (2009-04-19) ############################# * FIXED: authorize-local command attempted to connect via SSH before authorizing. #### 0.5.0 (2009-04-18) ############################# * FIXED: Bug in connect which prevented key-based logins for reconnections * FIXED: Method errors in JRuby * FIXED: Bug in Rye::Set.add_boxes pushing nils into the list of boxes * ADDED: Rye::Box.switch_user * ADDED: Several new commands to Rye::Cmd * ADDED: Rye::Box.authorize_keys_local and "rye authorize-local #### 0.4.3 (2009-04-14) ############################# * FIXED: All Rye::Cmd command methods accept *args to make calling consistent. * ADDED: Rye::Box.missing_method to handle non existent commands #### 0.4.2 (2009-04-13) ############################# * ADDED: More helpful debug output * ADDED: hostname command to Rye::Cmd * ADDED: Rye::Box.connect now supports multiple password attempts if STDIN.tty returns true * ADDED: Rye::Box.interactive_ssh for opening an SSH session to the given box. * CHANGE: Using OpenSSL's ssh-agent but also let's Net::SSH handle the ssh keys. #### 0.4.1 (2009-04-06) ############################# * FIXED: Rye::Box.authorize_keys_remote was not disabling safe mode properly * FIXED: Disabled debug mode. * ADDED: "rye authorize" now specifically enforces the auth method order #### 0.4.0 (2009-04-06) ############################# * FIXED: Box.run_command was parsing arguments incorrectly * FIXED: Box.net_ssh_exec was working on nil stderr * FIXED: bin/try handles the new command exceptions * ADDED: to_s and inspect methods for cleaner debugging output * ADDED: == method for Rye::Box * ADDED: exit code and exit signal to Rye::Rap objects * ADDED: Command switches can now be sent as Symbols (rbox.ls(:h)) * ADDED: Rye.host_keys * ADDED: bin/rye * ADDED: commands now raise a Rye::CommandError exception when the command returns an exit code greater than 0. * CHANGE: Box.add_command renamed to Box.run_command #### 0.3.2 (2009-04-05) ############################# * FIXED: Module.instance_methods bug. In Ruby 1.9 it's Symbols (1.8 was Strings). * FIXED: Rye::Set#add_boxes didn't return self. * UPDATED: Lots of docs tweaks. #### 0.3 (2009-04-05) ############################### * FIXED: Rye::Box wasn't properly adding keypairs to SSH Agent * FIXED: Rye::Box.method_missing Symbol/String ambiguity * ADDED: Rye::Set supports executing commands parallel * ADDED: Rye::Rap now contains STDERR output from command * ADDED: Supports all options provided by Net::SSH#start. This includes support for password logins and proxies. * ADDED: Safe mode can now be disabled (to allow file globs and environment variable access). * ADDED: Basic sanity test * ADDED: Mucho more rdocs and examples. * CHANGE: Moved all SSH key stuff to Rye (used to be done per Box) #### 0.2 (2009-04-04) ############################### * FIXED: ssh-agent shutdown wasn't deleting the SSH tmp directory * ADDED: Now with more rdocs! #### 0.1 (2009-04-03) ############################### Initial public release