module Rye
  1. lib/rye/box.rb
  2. lib/rye/cmd.rb
  3. lib/rye/dsl.rb
  4. lib/rye/hop.rb
  5. lib/rye/key.rb
  6. lib/rye/rap.rb
  7. lib/rye/set.rb
  8. lib/rye.rb
  9. show all
Parent: rye.rb

vim: set sw=2 ts=2 :

vim: set sw=2 ts=2 :

vim: set sw=2 ts=2 :

vim: set sw=2 ts=2 :

vim: set sw=2 ts=2 :


Safely run remote commands via SSH in Ruby.

Rye is similar to Rush but everything happens over SSH (no HTTP daemon) and the default settings are less dangerous (for safety). For example, file globs and the "rm" command are disabled so unless otherwise specified, you can't do this: rbox.rm('/etc/*/').

However, you can do this:

rset ="dev-machines") rset.add_boxes('host1', 'host2', 'host3', 'host4')'aux')

  • See bin/try for a bunch of working examples.

  • See Rye::Box#initialize for info about disabling safe-mode.


DEBUG = false unless defined?(Rye::DEBUG)  
HOME = File.expand_path( File.join(File.dirname(__FILE__), '..') )  

Public Class methods

sysinfo ()

Accessor for an instance of SystemInfo

[show source]
# File lib/rye.rb, line 75
def Rye.sysinfo
  @@sysinfo = if @@sysinfo.nil?

Public Instance methods

add_keys (*keys)

Add one or more private keys to the SSH Agent.

  • keys one or more file paths to private keys used for passwordless logins.

[show source]
# File lib/rye.rb, line 146
def add_keys(*keys)
  keys = keys.flatten.compact || []
  return if keys.empty?"ssh-add", keys)
escape (safe, cmd, *args)

Creates a string from cmd and args. If safe is true it will send them through Escape.shell_command otherwise it will return them joined by a space character.

[show source]
# File lib/rye.rb, line 256
def escape(safe, cmd, *args)
  args = args.flatten.compact || []
  safe ? Escape.shell_command(cmd, *args).to_s : [cmd, args].flatten.compact.join(' ')
find_private_keys (path)

Looks for private keys in path and returns an Array of paths to the files it finds. Raises an Exception if path does not exist. If path is a file rather than a directory, it will check whether that single file is a private key.

[show source]
# File lib/rye.rb, line 123
def find_private_keys(path)
  raise "#{path} does not exist" unless File.exists?(path || '')
    files = Dir.entries(path).collect { |file| File.join(path, file) }
    files = [path]

  files = do |file|
    next if
    pk = nil
      tmp = Rye::Key.from_file(file)
      pk = tmp if tmp.private?
    rescue OpenSSL::PKey::PKeyError
  files || []
keys ()

Returns an Array of info about the currently available SSH keys, as provided by the SSH Agent.

Returns: [[bits, finger-print, file-path], ...]

[show source]
# File lib/rye.rb, line 157
def keys
  # 2048 76:cb:d7:82:90:92:ad:75:3d:68:6c:a9:21:ca:7b:7f /Users/rye/.ssh/id_rsa (RSA)
  # 2048 7b:a6:ba:55:b1:10:1d:91:9f:73:3a:aa:0c:d4:88:0e /Users/rye/.ssh/id_dsa (DSA)
  #keystr ="ssh-add", '-l')
  #return nil unless keystr
  #keystr.collect do |key|
  #  key.split(/\s+/)
  Dir.glob(File.join(Rye.sysinfo.home, '.ssh', 'id_*sa'))
mutex ()
[show source]
# File lib/rye.rb, line 115
def mutex
prepare_command (cmd, *args)

Takes a command with arguments and returns it in a single String with escaped args and some other stuff.

  • cmd The shell command name or absolute path.

  • args an Array of command arguments.

The command is searched for in the local PATH (where Rye is running). An exception is raised if it's not found. NOTE: Because this happens locally, you won't want to use this method if the environment is quite different from the remote machine it will be executed on.

The command arguments are passed through Escape.shell_command (that means you can't use environment variables or asterisks).

[show source]
# File lib/rye.rb, line 190
def prepare_command(cmd, *args)
  args &&= [args].flatten.compact
  found_cmd = Rye.which(cmd)
  raise || '[unknown]') unless found_cmd
  # Symbols to switches. :l -> -l, :help -> --help
  args.collect! do |a|
    a = "-#{a}" if a.is_a?(Symbol) && a.to_s.size == 1
    a = "--#{a}" if a.is_a?(Symbol)
  Rye.escape(@safe, found_cmd, *args)
reload ()

Reload Rye dynamically. Useful with irb. NOTE: does not reload rye.rb.

[show source]
# File lib/rye.rb, line 110
def reload
  pat = File.join(File.dirname(__FILE__), 'rye')
  %{key rap cmd box set hop}.each {|lib| load File.join(pat, "#{lib}.rb") }
remote_host_keys (*hostnames)
[show source]
# File lib/rye.rb, line 168
def remote_host_keys(*hostnames)
  hostnames = hostnames.flatten.compact || []
  return if hostnames.empty?"ssh-keyscan", hostnames)
shell (cmd, *args)

Execute a local system command (via the shell, not SSH)

  • cmd the executable path (relative or absolute)

  • args Array of arguments to be sent to the command. Each element

is one argument:. i.e. ['-l', 'some/path']

NOTE: shell is a bit paranoid so it escapes every argument. This means you can only use literal values. That means no asterisks too.

Returns a Rye::Rap object.

[show source]
# File lib/rye.rb, line 231
def shell(cmd, *args)
  args = args.flatten.compact
  cmd = cmd.to_s if cmd.is_a?(Symbol)
  # TODO: allow stdin to be sent to the cmd
  tf =
  cmd = Rye.prepare_command(cmd, args)
  cmd << " 2>#{tf.path}" # Redirect STDERR to file. Works in DOS too.
  # Deal with STDOUT
  handle = IO.popen(cmd, "r")
  stdout =
  # Then STDERR
  stderr = File.exists?(tf.path) ? : ''
  # Create the response object
  rap =
  rap.add_stdout(stdout || '')
  rap.add_stderr(stderr || '')
sshagent_info ()
[show source]
# File lib/rye.rb, line 261
def sshagent_info
strand ( len=8, safe=true )

Generates a string of random alphanumeric characters.

  • len is the length, an Integer. Default: 8

  • safe in safe-mode, ambiguous characters are removed (default: true):

    i l o 1 0
[show source]
# File lib/rye.rb, line 277
def strand( len=8, safe=true )
   chars = ("a".."z").to_a + ("0".."9").to_a
   chars.delete_if { |v| %(i l o 1 0).member?(v) } if safe
   str = ""
   1.upto(len) { |i| str << chars[rand(chars.size-1)] }
sysinfo ()

Accessor for an instance of SystemInfo

[show source]
# File lib/rye.rb, line 81
def sysinfo; Rye.sysinfo end
which (executable)

An all ruby implementation of unix "which" command.

  • executable the name of the executable

Returns the absolute path if found in PATH otherwise nil.

[show source]
# File lib/rye.rb, line 208
def which(executable)
  return unless executable.is_a?(String)
  return executable if Rye.sysinfo.os == :windows
  #return executable if File.exists?(executable) # SHOULD WORK, MUST TEST
  shortname = File.basename(executable)
  dir = do |path|    # dir contains all of the
    next unless File.exists? path             # occurrences of shortname  # found in the paths.
  File.join(dir.first, shortname) unless dir.empty? # Return just the first
without_indent (str)

Returns str with the leading indentation removed. Stolen from because it was better.

[show source]
# File lib/rye.rb, line 267
def without_indent(str)
  indent = str.split($/).each {|line| !line.strip.empty? }.map {|line| line.index(/[^\s]/) }.compact.min
  str.gsub(/^[[:blank:]]{#{indent}}/, '')