Class: Rye::Box

Inherits:
Object
  • Object
show all
Includes:
InstanceExecHelper, Cmd
Defined in:
lib/rye/box.rb

Overview

Rye::Box

The Rye::Box class represents a machine. All system commands are made through this class.

rbox = Rye::Box.new('filibuster')
rbox.hostname   # => filibuster
rbox.uname      # => FreeBSD
rbox.uptime     # => 20:53  up 1 day,  1:52, 4 users

You can also run local commands through SSH

rbox = Rye::Box.new('localhost') 
rbox.hostname   # => localhost
rbox.uname(:a)  # => Darwin vanya 9.6.0 ...

  • When anything confusing happens, enable debug in initialize

by passing :debug => STDERR. This will output Rye debug info as well as Net::SSH info. This is VERY helpful for figuring out why some command is hanging or otherwise acting weird.

  • If a remote command is hanging, it’s probably because a

Net::SSH channel is waiting on_extended_data (a prompt). ++

Defined Under Namespace

Modules: InstanceExecHelper

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Cmd

#ab, add_command, #aptitude, #awk, #bash, #bunzip2, #bzip2, #can, #can?, can?, #cat, #chmod, #chown, #cmd?, #command?, #configure, #cp, #curl, #cvs, #date, #df, #digest_md5, #digest_sha1, #digest_sha2, #dir, #dir_download, #dir_upload, #dpkg, #du, #echo, #env, #file_append, #file_download, #file_exists?, #file_modify, #file_upload, #file_verified?, #file_write, #getconf, #git, #grep, #gunzip, #gzip, #hg, #history, #hostname, #irb, #ldconfig, #ln, #ls, #make, #mkdir, #mkfs, #mount, #mv, #perl, #printenv, #ps, #pwd, #python, #rake, remove_command, #ruby, #rudy, #rudy_ec2, #rudy_s3, #rudy_sdb, #rye, #sed, #sh, #siege, #sleep, #stella, #string_append, #string_download, #string_upload, #su, #svn, #tail, #tar, #template_upload, #template_write, #test, #touch, #try, #umount, #uname, #unxz, #unzip, #uptime, #useradd, #wc, #wget, #which, #whoami, #xz

Constructor Details

#initialize(host = 'localhost', opts = {}) ⇒ Box

  • host The hostname to connect to. Default: localhost.

  • opts a hash of optional arguments.

The opts hash excepts the following keys:

  • :user => the username to connect as. Default: SSH config file or current shell user.

  • :safe => should Rye be safe? Default: true

  • :port => remote server ssh port. Default: SSH config file or 22

  • :keys => one or more private key file paths (passwordless login)

  • :via => the Rye::Hop to access this host through

  • :info => an IO object to print Rye::Box command info to. Default: nil

  • :debug => an IO object to print Rye::Box debugging info to. Default: nil

  • :error => an IO object to print Rye::Box errors to. Default: STDERR

  • :getenv => pre-fetch host environment variables? (default: true)

  • :password => the user’s password (ignored if there’s a valid private key)

  • :templates => the template engine to use for uploaded files. One of: :erb (default)

  • :sudo => Run all commands via sudo (default: false)

  • :password_prompt => Show a password prompt on auth failure (default: true)

NOTE: opts can also contain any parameter supported by Net::SSH.start that is not already mentioned above.



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/rye/box.rb', line 114

def initialize(host='localhost', opts={})
  ssh_opts = ssh_config_options(host)
  @rye_exception_hook = {}
  @rye_host = host
  
  if opts[:user]
    @rye_user = opts[:user]
  else
    @rye_user = ssh_opts[:user] || Rye.sysinfo.user
  end

  # These opts are use by Rye::Box and also passed to Net::SSH
  @rye_opts = {
    :safe => true,
    :port => ssh_opts[:port],
    :keys => Rye.keys,
    :via => nil,
    :info => nil,
    :debug => nil,
    :error => STDERR,
    :getenv => true,
    :templates => :erb,
    :quiet => false,
    :password_prompt => true
  }.merge(opts)
  
  # Close the SSH session before Ruby exits. This will do nothing
  # if disconnect has already been called explicitly. 
  at_exit { self.disconnect }

  # Properly handle whether the opt :via is a +Rye::Hop+ or a +String+
  via_hop(@rye_opts.delete(:via))
  
  # @rye_opts gets sent to Net::SSH so we need to remove the keys
  # that are not meant for it. 
  @rye_safe, @rye_debug = @rye_opts.delete(:safe), @rye_opts.delete(:debug)
  @rye_info, @rye_error = @rye_opts.delete(:info), @rye_opts.delete(:error)
  @rye_getenv = {} if @rye_opts.delete(:getenv) # Enable getenv with a hash
  @rye_ostype, @rye_impltype = @rye_opts.delete(:ostype), @rye_opts.delete(:impltype)
  @rye_quiet, @rye_sudo = @rye_opts.delete(:quiet), @rye_opts.delete(:sudo)
  @rye_templates = @rye_opts.delete(:templates)
  @rye_password_prompt = @rye_opts.delete(:password_prompt)

  # Store the state of the terminal
  @rye_stty_save = `stty -g 2>/dev/null`.chomp rescue nil
  
  unless @rye_templates.nil?
    require @rye_templates.to_s   # should be :erb
  end
  
  @rye_opts[:logger] = Logger.new(@rye_debug) if @rye_debug # Enable Net::SSH debugging
  @rye_opts[:paranoid] ||= true unless @rye_safe == false # See Net::SSH.start
  @rye_opts[:keys] = [@rye_opts[:keys]].flatten.compact
  
  # Just in case someone sends a true value rather than IO object
  @rye_debug = STDERR if @rye_debug == true || DEBUG
  @rye_error = STDERR if @rye_error == true
  @rye_info = STDOUT if @rye_info == true
  
  # Add the given private keys to the keychain that will be used for @rye_host
  add_keys(@rye_opts[:keys])
  
  # We don't want Net::SSH to handle the keypairs. This may change
  # but for we're letting ssh-agent do it. 
  # TODO: Check if this should ot should not be enabled. 
  #@rye_opts.delete(:keys)
  
  # From: capistrano/lib/capistrano/cli.rb
  STDOUT.sync = true # so that Net::SSH prompts show up
  
  debug "ssh-agent info: #{Rye.sshagent_info.inspect}"
  debug @rye_opts.inspect

end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(cmd, *args, &block) ⇒ Object Also known as: execute

A handler for undefined commands. Raises Rye::CommandNotFound exception.



464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
# File 'lib/rye/box.rb', line 464

def method_missing(cmd, *args, &block)
  if cmd == :to_ary
    super
  elsif @rye_safe
    ex = Rye::CommandNotFound.new(cmd.to_s)
    raise ex unless @rye_exception_hook.has_key? ex.class
    @rye_exception_hook[Rye::CommandNotFound].call ex
  else
    if block.nil?
      run_command cmd, *args
    else
      ex = Rye::CommandNotFound.new(cmd.to_s)
      raise ex unless @rye_exception_hook.has_key? ex.class
    end
  end
end

Instance Attribute Details

#rye_ptyObject

Returns the value of attribute rye_pty.



37
38
39
# File 'lib/rye/box.rb', line 37

def rye_pty
  @rye_pty
end

#rye_shellObject

Returns the value of attribute rye_shell.



36
37
38
# File 'lib/rye/box.rb', line 36

def rye_shell
  @rye_shell
end

Instance Method Details

#==(other) ⇒ Object

Compares itself with the other box. If the hostnames are the same, this will return true. Otherwise false.



407
408
409
# File 'lib/rye/box.rb', line 407

def ==(other)
  @rye_host == other.host
end

#[](fpath = nil) ⇒ Object

Change the current working directory (sort of).

I haven’t been able to wrangle Net::SSH to do my bidding. “My bidding” in this case, is maintaining an open channel between commands. I’m using Net::SSH::Connection::Session#exec for all commands which is like a funky helper method that opens a new channel each time it’s called. This seems to be okay for one-off commands but changing the directory only works for the channel it’s executed in. The next time exec is called, there’s a new channel which is back in the default (home) directory.

Long story short, the work around is to maintain the current directory locally and send it with each command.

rbox.pwd              # => /home/rye ($ pwd )
rbox['/usr/bin'].pwd  # => /usr/bin  ($ cd /usr/bin && pwd)
rbox.pwd              # => /usr/bin  ($ cd /usr/bin && pwd)


245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
# File 'lib/rye/box.rb', line 245

def [](fpath=nil)
  if fpath.nil? || fpath.index('/') == 0
    @rye_current_working_directory = fpath
  else
    # Append to non-absolute paths
    if @rye_current_working_directory
      newpath = File.join(@rye_current_working_directory, fpath)
      @rye_current_working_directory = newpath
    else
      @rye_current_working_directory = fpath
    end
  end
  debug "CWD: #{@rye_current_working_directory}"
  self
end

#add_keys(*keys) ⇒ Object Also known as: add_key

Add one or more private keys to the list of key paths.

  • keys is a list of file paths to private keys

Returns the instance of Box



322
323
324
325
326
327
# File 'lib/rye/box.rb', line 322

def add_keys(*keys)
  @rye_opts[:keys] ||= []
  @rye_opts[:keys] += keys.flatten.compact
  @rye_opts[:keys].uniq!
  self # MUST RETURN self
end

#batch(*args, &block) ⇒ Object

Execute a block in the context of an instance of Rye::Box.

rbox = Rye::Box.new

rbox.batch do
  ls :l
  uname :a
end

OR

rbox.batch(&block)

The batch can also accept arguments.

rbox.batch('path/2/file') do |file|
  ls :l file
end

Returns the return value of the block.



550
551
552
# File 'lib/rye/box.rb', line 550

def batch(*args, &block)
  self.instance_exec(*args, &block)
end

#cd(fpath = nil) ⇒ Object

Like [] except it returns an empty Rye::Rap object to mimick a regular command method. Call with nil key (or no arg) to reset.



263
264
265
# File 'lib/rye/box.rb', line 263

def cd(fpath=nil)
  Rye::Rap.new(self[fpath])
end

#connect(reconnect = true) ⇒ Object

Open an SSH session with @rye_host. This called automatically when you the first comamnd is run if it’s not already connected. Raises a Rye::NoHost exception if @rye_host is not specified. Will attempt a password login up to 3 times if the initial authentication fails.

  • reconnect Disconnect first if already connected. The default

is true. When set to false, connect will do nothing if already connected.

Raises:



649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
# File 'lib/rye/box.rb', line 649

def connect(reconnect=true)
  raise Rye::NoHost unless @rye_host
  return if @rye_ssh && !reconnect
  disconnect if @rye_ssh 
  if @rye_via
    debug "Opening connection to #{@rye_host} as #{@rye_user}, via #{@rye_via.host}"
  else
    debug "Opening connection to #{@rye_host} as #{@rye_user}"
  end
  highline = HighLine.new # Used for password prompt
  retried = 0
  @rye_opts[:keys].compact!  # A quick fix in Windows. TODO: Why is there a nil?
  begin
    if @rye_via
      # tell the +Rye::Hop+ what and where to setup,
      # it returns the local port used
      @rye_localport = @rye_via.fetch_port(@rye_host, @rye_opts[:port].nil? ? 22 : @rye_opts[:port] )
      debug "fetched localport #{@rye_localport}"
      @rye_ssh = Net::SSH.start("localhost", @rye_user, @rye_opts.merge(:port => @rye_localport) || {}) 
    else
      @rye_ssh = Net::SSH.start(@rye_host, @rye_user, @rye_opts || {}) 
    end
  rescue Net::SSH::HostKeyMismatch => ex
    STDERR.puts ex.message
    print "\a" if @rye_info # Ring the bell
    raise ex
  rescue Net::SSH::AuthenticationFailed => ex
    print "\a" if retried == 0 && @rye_info # Ring the bell once
    retried += 1

    @rye_opts[:auth_methods] ||= []

    # Raise Net::SSH::AuthenticationFailed if publickey is the 
    # only auth method
    if @rye_opts[:auth_methods] == ["publickey"]
      raise ex
    elsif @rye_password_prompt && (STDIN.tty? && retried <= 3)
      STDERR.puts "Passwordless login failed for #{@rye_user}"
      @rye_opts[:password] = highline.ask("Password: ") { |q| q.echo = '' }.strip
      @rye_opts[:auth_methods].push *['keyboard-interactive', 'password']
      retry
    else
      raise ex
    end
  end
  
  # We add :auth_methods (a Net::SSH joint) to force asking for a
  # password if the initial (key-based) authentication fails. We
  # need to delete the key from @rye_opts otherwise it lingers until
  # the next connection (if we switch_user is called for example).
  @rye_opts.delete :auth_methods if @rye_opts.has_key?(:auth_methods)
  
  self
end

#current_umaskObject

The most recent valud for umask (or 0022)



77
# File 'lib/rye/box.rb', line 77

def current_umask; @rye_current_umask; end

#current_working_directoryObject

The most recent value from Box.cd or Box.[]



74
# File 'lib/rye/box.rb', line 74

def current_working_directory; @rye_current_working_directory; end

#debug?Boolean

Returns:

  • (Boolean)


81
# File 'lib/rye/box.rb', line 81

def debug?; !@rye_debug.nil?; end

#disable_quiet_modeObject



71
# File 'lib/rye/box.rb', line 71

def disable_quiet_mode; @rye_quiet = false; end

#disable_safe_modeObject



67
# File 'lib/rye/box.rb', line 67

def disable_safe_mode; @rye_safe = false; end

#disable_sudoObject



49
# File 'lib/rye/box.rb', line 49

def disable_sudo; @rye_sudo = false; end

#disconnectObject

Close the SSH session with @rye_host. This is called automatically at exit if the connection is open.



706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
# File 'lib/rye/box.rb', line 706

def disconnect
  return unless @rye_ssh && !@rye_ssh.closed?
  begin
    if @rye_ssh.busy?;
      info "Is something still running? (ctrl-C to exit)"
      Timeout::timeout(10) do
        @rye_ssh.loop(0.3) { @rye_ssh.busy?; }
      end
    end
    debug "Closing connection to #{@rye_ssh.host}"
    @rye_ssh.close
    if @rye_via
      debug "disconnecting Hop #{@rye_via.host}"
      @rye_via.disconnect
    end
  rescue SystemCallError, Timeout::Error => ex
    error "Rye::Box: Disconnect timeout (#{ex.message})"
    debug ex.backtrace
  rescue Interrupt
    debug "Exiting..."
  end
end

#enable_quiet_modeObject



70
# File 'lib/rye/box.rb', line 70

def enable_quiet_mode;  @rye_quiet = true; end

#enable_safe_modeObject



66
# File 'lib/rye/box.rb', line 66

def enable_safe_mode;  @rye_safe = true; end

#enable_sudoObject



48
# File 'lib/rye/box.rb', line 48

def enable_sudo; @rye_sudo = true; end

#error?Boolean

Returns:

  • (Boolean)


82
# File 'lib/rye/box.rb', line 82

def error?; !@rye_error.nil?; end

#exception_hook(klass, &block) ⇒ Object

Supply a block to be called whenever there’s an Exception. It’s called with 1 argument: the exception class. If the exception block returns :retry, the command will be executed again.

e.g.

rbox.exception_hook(CommandNotFound) do |ex|
  STDERR.puts "An error occurred: #{ex.class}"
  choice = Annoy.get_user_input('(S)kip  (R)etry  (A)bort: ')
  if choice == 'R'
    :retry 
  elsif choice == 'S'
    # do nothing
  else
    exit  # !
  end
end


526
527
528
529
# File 'lib/rye/box.rb', line 526

def exception_hook(klass, &block)
  @rye_exception_hook[klass] = block if block
  @rye_exception_hook[klass]
end

#exception_hook=(val) ⇒ Object

A Hash. The keys are exception classes, the values are Procs to execute



90
# File 'lib/rye/box.rb', line 90

def exception_hook=(val); @rye_exception_hook = val; end

#getenv(key = nil) ⇒ Object

Returns the hash containing the parsed output of “env” on the remote machine. If the initialize option :getenv was set to false, this will return an empty hash. This is a lazy loaded method so it fetches the remote envvars the first time this method is called.

puts rbox.getenv['HOME']    # => "/home/gloria" (remote)

NOTE: This method should not raise an exception under normal circumstances.



367
368
369
370
371
372
373
374
375
376
377
378
# File 'lib/rye/box.rb', line 367

def getenv(key=nil)
  if @rye_getenv && @rye_getenv.empty? && self.can?(:env)
    vars = self.quietly { env } rescue []
    vars.each do |nvpair| 
      # Parse "GLORIA_HOME=/gloria/lives/here" into a name/value
      # pair. The regexp ensures we split only at the 1st = sign
      n, v = nvpair.scan(/\A([\w_-]+?)=(.+)\z/).flatten
      @rye_getenv[n] = v
    end
  end
  key.nil? ? @rye_getenv : @rye_getenv[key.to_s]
end

#guess_user_home(other_user = nil) ⇒ Object

Uses the output of “useradd -D” to determine the default home directory. This returns a GUESS rather than the a user’s real home directory. Currently used only by authorize_keys_remote. Only useful before you’ve logged in. Otherwise check $HOME



421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
# File 'lib/rye/box.rb', line 421

def guess_user_home(other_user=nil)
  this_user = other_user || opts[:user]
  @rye_guessed_homes ||= {}
  
  # A simple cache. 
  return @rye_guessed_homes[this_user] if @rye_guessed_homes.has_key?(this_user)
  
  # Some junk to determine where user home directories are by default.
  # We're relying on the command "useradd -D" so this may not work on
  # different Linuxen and definitely won't work on Windows.
  # This code will be abstracted out once I find a decent home for it.
  # /etc/default/useradd, HOME=/home OR useradd -D
  # /etc/adduser.config, DHOME=/home OR ??
  user_defaults = {}
  ostmp = self.ostype
  ostmp &&= ostype.to_s
  
  if ostmp == "sunos"
    #nv.scan(/([\w_-]+?)=(.+?)\s/).each do |n, v|
    #  n = 'HOME' if n == 'basedir'
    #  user_defaults[n.upcase] = v.strip
    #end
    # In Solaris, useradd -D says the default home path is /home
    # but that directory is not writable. See: http://bit.ly/IJDD0
    user_defaults['HOME'] = '/export/home'
  elsif ostmp == "darwin"
    user_defaults['HOME'] = '/Users'
  elsif ostmp == "windows"
    user_defaults['HOME'] = 'C:/Documents and Settings'
  else
    raw = self.quietly { useradd(:D) } rescue []
    raw = ["HOME=/home"] if raw.nil? || raw.empty?
    raw.each do |nv|
      n, v = nv.scan(/\A([\w_-]+?)=(.+)\z/).flatten
      user_defaults[n] = v
    end
  end
  
  @rye_guessed_homes[this_user] = "#{user_defaults['HOME']}/#{this_user}"
end

#hostObject



39
# File 'lib/rye/box.rb', line 39

def host; @rye_host; end

#host=(val) ⇒ Object



58
# File 'lib/rye/box.rb', line 58

def host=(val); @rye_host = val; end

#host_keyObject

Returns the host SSH keys for this box



412
413
414
415
# File 'lib/rye/box.rb', line 412

def host_key
  raise "No host" unless @rye_host
  Rye.remote_host_keys(@rye_host)
end

#impltypeObject



352
353
354
# File 'lib/rye/box.rb', line 352

def impltype
  @rye_impltype
end

#impltype=(val) ⇒ Object



85
# File 'lib/rye/box.rb', line 85

def impltype=(val); @rye_impltype = val; end

#info?Boolean

Returns:

  • (Boolean)


80
# File 'lib/rye/box.rb', line 80

def info?; !@rye_info.nil?; end

#inspectObject



397
398
399
400
401
402
403
# File 'lib/rye/box.rb', line 397

def inspect
  %q{#<%s:%s name=%s cwd=%s umask=%s env=%s safe=%s opts=%s keys=%s>} % 
  [self.class.to_s, self.host, self.nickname,
   @rye_current_working_directory, @rye_current_umask,
   (@rye_current_environment_variables || '').inspect,
   self.safe, self.opts.inspect, self.keys.inspect]
end

#instance_exec(*args, &block) ⇒ Object

!> method redefined; discarding old instance_exec



615
616
617
618
619
620
621
622
623
624
# File 'lib/rye/box.rb', line 615

def instance_exec(*args, &block) # !> method redefined; discarding old instance_exec
  mname = "__instance_exec_#{Thread.current.object_id.abs}_#{object_id.abs}"
  InstanceExecHelper.module_eval{ define_method(mname, &block) }
  begin
    ret = send(mname, *args)
  ensure
    InstanceExecHelper.module_eval{ undef_method(mname) } rescue nil
  end
  ret
end

#interactive_ssh(run = true) ⇒ Object

If STDIN.tty? is true (i.e. if we’re connected to a terminal with a human at the helm), this will open an SSH connection via the regular SSH command (via a call to system). This requires the SSH command-line executable (ssh).

If STDIN.tty? is false or run is false, this will return the SSH command (a String) that would have been run.

NOTE: As of Rye 0.9 you can run interactive sessions with rye by calling any shell method without arguments.

e.g.

rbox = Rye::Box.new 'somemachine'
rbox.bash

TODO: refactor to use net_ssh_exec! in 0.9



308
309
310
311
312
313
314
315
316
317
# File 'lib/rye/box.rb', line 308

def interactive_ssh(run=true)
  debug "interactive_ssh with keys: #{@rye_opts[:keys].inspect}"
  run = false unless STDIN.tty?
  args = []
  @rye_opts[:keys].each { |key| args.push *[:i, key] }
  args << "#{@rye_user}@#{@rye_host}"
  cmd = Rye.prepare_command("ssh", args)
  return cmd unless run
  system(cmd)
end

#keysObject

See Rye.keys



392
# File 'lib/rye/box.rb', line 392

def keys; Rye.keys; end

#nicknameObject



56
# File 'lib/rye/box.rb', line 56

def nickname; @rye_nickname || host; end

#nickname=(val) ⇒ Object



64
# File 'lib/rye/box.rb', line 64

def nickname=(val); @rye_nickname = val; end

#optsObject



40
# File 'lib/rye/box.rb', line 40

def opts; @rye_opts; end

#opts=(val) ⇒ Object



59
# File 'lib/rye/box.rb', line 59

def opts=(val); @rye_opts = val; end

#ostypeObject

Return the value of uname in lowercase This is a temporary fix. We can use SysInfo for this, upload it, execute it directly, parse the output.



344
345
346
347
348
349
350
# File 'lib/rye/box.rb', line 344

def ostype
  return @rye_ostype if @rye_ostype # simple cache
  os = self.quietly { uname.first } rescue nil
  os ||= 'unknown'
  os &&= os.downcase
  @rye_ostype = os
end

#ostype=(val) ⇒ Object



84
# File 'lib/rye/box.rb', line 84

def ostype=(val); @rye_ostype = val; end

#post_command_hook(&block) ⇒ Object

Supply a block to be called after every command. It’s called with one argument: an instance of Rye::Rap.

When this block is supplied, the command does not raise an exception when the exit code is greater than 0 (the typical behavior) so the block needs to check the Rye::Rap object to determine whether an exception should be raised.



634
635
636
637
# File 'lib/rye/box.rb', line 634

def post_command_hook(&block)
  @rye_post_command_hook = block if block
  @rye_post_command_hook
end

#post_command_hook=(val) ⇒ Object



88
# File 'lib/rye/box.rb', line 88

def post_command_hook=(val); @rye_post_command_hook = val; end

#pre_command_hook(&block) ⇒ Object

Supply a block to be called before every command. It’s called with three arguments: command name, an Array of arguments, user name, hostname e.g.

rbox.pre_command_hook do |cmd,args,user,host|
  ...
end


494
495
496
497
# File 'lib/rye/box.rb', line 494

def pre_command_hook(&block)
  @rye_pre_command_hook = block if block
  @rye_pre_command_hook
end

#pre_command_hook=(val) ⇒ Object



86
# File 'lib/rye/box.rb', line 86

def pre_command_hook=(val); @rye_pre_command_hook = val; end

#preview_command(*args) ⇒ Object

Returns the command an arguments as a String.



483
484
485
# File 'lib/rye/box.rb', line 483

def preview_command(*args)
  prep_args(*args).join(' ')
end

#quietObject



54
# File 'lib/rye/box.rb', line 54

def quiet; @rye_quiet; end

#quietly(*args, &block) ⇒ Object

Like batch, except it enables quiet mode before executing the block. After executing the block, quiet mode is returned back to whichever state it was previously in. In other words, this method won’t enable quiet mode if it was already disabled.

In quiet mode, the pre and post command hooks are not called. This is used internally when calling commands like ls to check whether a file path exists (to prevent polluting the logs).



584
585
586
587
588
589
590
# File 'lib/rye/box.rb', line 584

def quietly(*args, &block)
  previous_state = @rye_quiet
  enable_quiet_mode
  ret = self.instance_exec *args, &block
  @rye_quiet = previous_state
  ret
end

#remove_keys(*keys) ⇒ Object Also known as: remove_key

Remove one or more private keys fromt he list of key paths.

  • keys is a list of file paths to private keys

Returns the instance of Box



333
334
335
336
337
338
# File 'lib/rye/box.rb', line 333

def remove_keys(*keys)
  @rye_opts[:keys] ||= []
  @rye_opts[:keys] -= keys.flatten.compact
  @rye_opts[:keys].uniq!
  self # MUST RETURN self
end

#root?Boolean

Returns:

  • (Boolean)


43
# File 'lib/rye/box.rb', line 43

def root?; user.to_s == "root" end

#safeObject



41
# File 'lib/rye/box.rb', line 41

def safe; @rye_safe; end

#safe?Boolean

Returns:

  • (Boolean)


68
# File 'lib/rye/box.rb', line 68

def safe?; @rye_safe == true; end

#safely(*args, &block) ⇒ Object

See unsafely (except in reverse)



568
569
570
571
572
573
574
# File 'lib/rye/box.rb', line 568

def safely(*args, &block)
  previous_state = @rye_safe
  enable_safe_mode
  ret = self.instance_exec *args, &block
  @rye_safe = previous_state
  ret
end

#setenv(n, v) ⇒ Object Also known as: add_env

Add an environment variable. n and v are the name and value. Returns the instance of Rye::Box



382
383
384
385
386
387
388
# File 'lib/rye/box.rb', line 382

def setenv(n, v)
  debug "Adding env: #{n}=#{v}"
  debug "prev value: #{@rye_getenv[n]}"
  @rye_getenv[n] = v
  (@rye_current_environment_variables ||= {})[n] = v
  self
end

#ssh_config_options(host) ⇒ Object

Parse SSH config files for use with Net::SSH



190
191
192
# File 'lib/rye/box.rb', line 190

def ssh_config_options(host)
  return Net::SSH::Config.for(host)
end

#stashObject

Returns the current value of the stash @rye_stash



53
# File 'lib/rye/box.rb', line 53

def stash; @rye_stash; end

#stash=(val) ⇒ Object

Store a value to the stash @rye_stash



63
# File 'lib/rye/box.rb', line 63

def stash=(val); @rye_stash = val; end

#stdout_hook(&block) ⇒ Object

Supply a block to be called every time a command receives STDOUT data.

e.g.

rbox.stdout_hook do |content|
  ...
end


505
506
507
508
# File 'lib/rye/box.rb', line 505

def stdout_hook(&block)
  @rye_stdout_hook = block if block
  @rye_stdout_hook
end

#stdout_hook=(val) ⇒ Object



87
# File 'lib/rye/box.rb', line 87

def stdout_hook=(val); @rye_stdout_hook = val; end

#sudo(*args, &block) ⇒ Object

Like batch, except it enables sudo mode before executing the block. If the user is already root, this has no effect. Otherwise all commands executed in the block will run via sudo.

If no block is specified then sudo is called just like a regular command.



598
599
600
601
602
603
604
605
606
607
608
# File 'lib/rye/box.rb', line 598

def sudo(*args, &block)
  if block.nil?
    run_command('sudo', args);
  else
    previous_state = @rye_sudo
    enable_sudo
    ret = self.instance_exec *args, &block
    @rye_sudo = previous_state
    ret  
  end
end

#sudo?Boolean

Returns:

  • (Boolean)


50
# File 'lib/rye/box.rb', line 50

def sudo?; @rye_sudo == true end

#switch_user(newuser) ⇒ Object

Reconnect as another user. This is different from su= which executes subsequent commands via su -c COMMAND USER.

  • newuser The username to reconnect as

NOTE: if there is an open connection, it’s disconnected but not reconnected because it’s possible it wasn’t connected yet in the first place (if you create the instance with default settings for example)



283
284
285
286
287
288
# File 'lib/rye/box.rb', line 283

def switch_user(newuser)
  return if newuser.to_s == self.user.to_s
  @rye_opts ||= {}
  @rye_user = newuser
  disconnect
end

#templatesObject



45
# File 'lib/rye/box.rb', line 45

def templates; @rye_templates; end

#templates?Boolean

Returns:

  • (Boolean)


46
# File 'lib/rye/box.rb', line 46

def templates?; !@rye_templates.nil?; end

#to_sObject

Returns user@rye_host



395
# File 'lib/rye/box.rb', line 395

def to_s; '%s@rye_%s' % [user, @rye_host]; end

#umask=(val = '0022') ⇒ Object

Change the current umask (sort of – works the same way as cd) The default umask is 0022



269
270
271
272
# File 'lib/rye/box.rb', line 269

def umask=(val='0022')
  @rye_current_umask = val
  self
end

#unsafely(*args, &block) ⇒ Object Also known as: wildly

Like batch, except it disables safe mode before executing the block. After executing the block, safe mode is returned back to whichever state it was previously in. In other words, this method won’t enable safe mode if it was already disabled.



558
559
560
561
562
563
564
# File 'lib/rye/box.rb', line 558

def unsafely(*args, &block)
  previous_state = @rye_safe
  disable_safe_mode
  ret = self.instance_exec *args, &block
  @rye_safe = previous_state
  ret
end

#userObject



42
# File 'lib/rye/box.rb', line 42

def user; @rye_user; end

#viaObject



55
# File 'lib/rye/box.rb', line 55

def via; @rye_via; end

#via=(val) ⇒ Object



60
# File 'lib/rye/box.rb', line 60

def via=(val); @rye_via = val; end

#via?Boolean

Returns:

  • (Boolean)


79
# File 'lib/rye/box.rb', line 79

def via?; !@rye_via.nil?; end

#via_hop(*args) ⇒ Object

  • hops Rye::Hop objects will be added directly

to the set. Hostnames will be used to create new instances of Rye::Hop h1 = Rye::Hop.new “host1” h1.via_hop “host2”, :user => “service_user”

OR

h1 = Rye::Hop.new “host1” h2 = Rye::Hop.new “host2” h1.via_hop h2



205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/rye/box.rb', line 205

def via_hop(*args)
  args = args.flatten.compact 
  if args.first.nil?
    return @rye_via
  elsif args.first.is_a?(Rye::Hop)
    @rye_via = args.first
  elsif args.first.is_a?(String)
    hop = args.shift
    if args.first.is_a?(Hash)
      @rye_via = Rye::Hop.new(hop, args.first.merge(
                                    :debug => @rye_debug,
                                    :info => @rye_info,
                                    :error => @rye_error)
                             )
    else
      @rye_via = Rye::Hop.new(hop)
    end
  end
  disconnect
  self
end