Namespace

Rye

vim: set sw=2 ts=2 :


vim: set sw=2 ts=2 :


vim: set sw=2 ts=2 :


vim: set sw=2 ts=2 :


Rye

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 = Rye::Set.new("dev-machines") rset.add_boxes('host1', 'host2', 'host3', 'host4') rset.ps('aux')

Constants

DEBUG
VERSION

Public Class Methods

sysinfo() click to toggle source

Accessor for an instance of SystemInfo

# File lib/rye.rb, line 53
def Rye.sysinfo
  @@sysinfo = SysInfo.new if @@sysinfo.nil?
  @@sysinfo
end

Public Instance Methods

add_keys(*keys) click to toggle source

Add one or more private keys to the SSH Agent.

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

# File lib/rye.rb, line 124
def add_keys(*keys)
  keys = keys.flatten.compact || []
  return if keys.empty?
  Rye.shell("ssh-add", keys)
end
escape(safe, cmd, *args) click to toggle source

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.

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

Looks for private keys in path and returns and 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.

# File lib/rye.rb, line 101
def find_private_keys(path)
  raise "#{path} does not exist" unless File.exists?(path || '')
  if File.directory?(path)
    files = Dir.entries(path).collect { |file| File.join(path, file) }
  else
    files = [path]
  end
  
  files = files.select do |file|
    next if File.directory?(file)
    pk = nil
    begin
      tmp = Rye::Key.from_file(file) 
      pk = tmp if tmp.private?
    rescue OpenSSL::PKey::PKeyError
    end
    !pk.nil?
  end
  files || []
end
keys() click to toggle source

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

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

# File lib/rye.rb, line 135
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 = Rye.shell("ssh-add", '-l')
  #return nil unless keystr
  #keystr.collect do |key|
  #  key.split(/\s+/)
  #end
  Dir.glob(File.join(Rye.sysinfo.home, '.ssh', 'id_*sa'))
end
mutex() click to toggle source
# File lib/rye.rb, line 93
def mutex
  @@mutex
end
prepare_command(cmd, *args) click to toggle source

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).

# File lib/rye.rb, line 168
def prepare_command(cmd, *args)
  args &&= [args].flatten.compact
  found_cmd = Rye.which(cmd)
  raise CommandNotFound.new(cmd || '[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)
    a
  end
  Rye.escape(@safe, found_cmd, *args)
end
reload() click to toggle source

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

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

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.

# File lib/rye.rb, line 209
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 = Tempfile.new(cmd)
  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 = handle.read.chomp
  handle.close
  # Then STDERR
  stderr = File.exists?(tf.path) ? File.read(tf.path) : ''
  tf.delete
  # Create the response object
  rap = Rye::Rap.new(self)
  rap.add_stdout(stdout || '')
  rap.add_stderr(stderr || '')
  rap.add_exit_status($?)
  rap
end
sshagent_info() click to toggle source
# File lib/rye.rb, line 239
def sshagent_info
  @@agent_env
end
strand( len=8, safe=true ) click to toggle source

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
# File lib/rye.rb, line 255
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)] }
   str
end
sysinfo() click to toggle source

Accessor for an instance of SystemInfo

# File lib/rye.rb, line 59
def sysinfo; Rye.sysinfo end
which(executable) click to toggle source

An all ruby implementation of unix "which" command.

  • executable the name of the executable

Returns the absolute path if found in PATH otherwise nil.

# File lib/rye.rb, line 186
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 = Rye.sysinfo.paths.select do |path|    # dir contains all of the 
    next unless File.exists? path             # occurrences of shortname  
    Dir.new(path).entries.member?(shortname)  # found in the paths. 
  end
  File.join(dir.first, shortname) unless dir.empty? # Return just the first
end
without_indent(str) click to toggle source

Returns str with the leading indentation removed. Stolen from github.com/mynyml/unindent/ because it was better.

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

[Validate]

Generated with the Darkfish Rdoc Generator 2.