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 Method Summary collapse

Methods included from Cmd

add_command, #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, #du, #echo, #env, #file_append, #file_download, #file_exists?, #file_upload, #file_verified?, #file_write, #getconf, #git, #grep, #gunzip, #gzip, #history, #hostname, #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, #sleep, #string_download, #string_upload, #sudo, #svn, #tar, #test, #touch, #umount, #uname, #unzip, #uptime, #useradd, #wc, #wget, #which

Constructor Details

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

  • host The hostname to connect to. The default is localhost.

  • opts a hash of optional arguments.

The opts hash excepts the following keys:

  • :user => the username to connect as. Default: the current user.

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

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

  • :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)

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



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
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
# File 'lib/rye/box.rb', line 90

def initialize(host='localhost', opts={})
  @rye_exception_hook = {}
  @rye_host = host
  
  # These opts are use by Rye::Box and also passed to Net::SSH
  @rye_opts = {
    :user => Rye.sysinfo.user, 
    :safe => true,
    :port => 22,
    :keys => [],
    :info => nil,
    :debug => nil,
    :error => STDERR,
    :getenv => true,
    :quiet => false
  }.merge(opts)
  
  # Close the SSH session before Ruby exits. This will do nothing
  # if disconnect has already been called explicitly. 
  at_exit { self.disconnect }
  
  # @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_opts.delete(:quiet)
  
  # Just in case someone sends a true value rather than IO object
  @rye_debug = STDERR if @rye_debug == true
  @rye_error = STDERR if @rye_error == true
  @rye_info = STDOUT if @rye_info == true
  
  @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
  
  # 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.



459
460
461
462
463
464
465
466
467
468
469
470
471
472
# File 'lib/rye/box.rb', line 459

def method_missing(cmd, *args, &block)
  if @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 Method Details

#==(other) ⇒ Object

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



310
311
312
# File 'lib/rye/box.rb', line 310

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)


163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/rye/box.rb', line 163

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(*additional_keys) ⇒ Object Also known as: add_key

Add one or more private keys to the SSH Agent.

  • additional_keys is a list of file paths to private keys

Returns the instance of Box



226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/rye/box.rb', line 226

def add_keys(*additional_keys)
  if Rye.sysinfo.os == :windows
    @rye_opts[:keys] ||= []
    @rye_opts[:keys] += additional_keys.flatten
    return @rye_opts[:keys]
  end
  additional_keys = [additional_keys].flatten.compact || []
  return if additional_keys.empty?
  ret = Rye.add_keys(additional_keys) 
  if ret.is_a?(Rye::Rap)
    debug "ssh-add exit_code: #{ret.exit_code}" 
    debug "ssh-add stdout: #{ret.stdout}"
    debug "ssh-add stderr: #{ret.stderr}"
  end
  self # MUST RETURN self
end

#authorize_keys_localObject

Authorize the current user to login to the local machine via SSH without a password. This is the same functionality as authorize_keys_remote except run with local shell commands.



432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
# File 'lib/rye/box.rb', line 432

def authorize_keys_local
  added_keys = []
  ssh_dir = File.join(Rye.sysinfo.home, '.ssh')
  Rye.keys.each do |path|
    debug "# Public key for #{path}"
    k = Rye::Key.from_file(path).public_key.to_ssh2
    FileUtils.mkdir ssh_dir unless File.exists? ssh_dir
    
    authkeys_file = File.join(ssh_dir, 'authorized_keys')
    
    debug "Writing to #{authkeys_file}"
    File.open(authkeys_file, 'a')       {|f| f.write("#{$/}#{k}") }
    File.open("#{authkeys_file}2", 'a') {|f| f.write("#{$/}#{k}") }
    
    unless Rye.sysinfo.os == :windows
      Rye.shell(:chmod, '700', ssh_dir)
      Rye.shell(:chmod, '0600', authkeys_file)
      Rye.shell(:chmod, '0600', "#{authkeys_file}2")
    end
    
    added_keys << path
  end
  added_keys
end

#authorize_keys_remote(other_user = nil) ⇒ Object

Copy the local public keys (as specified by Rye.keys) to this box into ~/.ssh/authorized_keys and ~/.ssh/authorized_keys2. Returns a Rye::Rap object. The private keys files used to generate the public keys are contained in stdout. Raises a Rye::ComandError if the home directory doesn’t exit. NOTE: authorize_keys_remote disables safe-mode for this box while it runs which will hit you funky style if your using a single instance of Rye::Box in a multithreaded situation.



373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
# File 'lib/rye/box.rb', line 373

def authorize_keys_remote(other_user=nil)
  this_user = other_user || opts[:user]
  added_keys = []
  rap = Rye::Rap.new(self)
  
  prevdir = self.current_working_directory
  
  # The homedir path is important b/c this is where we're going to 
  # look for the .ssh directory. That's where auth love is stored.
  homedir = self.guess_user_home(this_user)
  
  unless self.file_exists?(homedir)
    rap.add_exit_code(1)
    rap.add_stderr("Path does not exist: #{homedir}")
    raise Rye::CommandError.new(rap)
  end
  
  # Let's go into the user's home directory that we now know exists.
  self.cd homedir
  
  files = ['.ssh/authorized_keys', '.ssh/authorized_keys2']
  files.each do |akey_path|
    if self.file_exists?(akey_path)
      # TODO: Make Rye::Cmd.incremental_backup
      self.cp(akey_path, "#{akey_path}-previous")
      authorized_keys = self.file_download("#{homedir}/#{akey_path}")
    end
    authorized_keys ||= StringIO.new
    
    Rye.keys.each do |path|
      
      info "# Adding public key for #{path}"
      k = Rye::Key.from_file(path).public_key.to_ssh2
      authorized_keys.puts k
    end
    
    # Remove duplicate authorized keys
    authorized_keys.rewind
    uniqlines = authorized_keys.readlines.uniq.join
    authorized_keys = StringIO.new(uniqlines)
    # We need to rewind so that all of the StringIO object is uploaded
    authorized_keys.rewind
    
    self.mkdir(:p, :m, '700', File.dirname(akey_path))
    self.file_upload(authorized_keys, "#{homedir}/#{akey_path}")
    self.chmod('0600', akey_path)
    self.chown(:R, this_user.to_s, File.dirname(akey_path))
  end
  
  # And let's return to the directory we came from.
  self.cd prevdir
  
  rap.add_exit_code(0)
  rap
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.



532
533
534
# File 'lib/rye/box.rb', line 532

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.



181
182
183
# File 'lib/rye/box.rb', line 181

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:



612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
# File 'lib/rye/box.rb', line 612

def connect(reconnect=true)
  raise Rye::NoHost unless @rye_host
  return if @rye_ssh && !reconnect
  disconnect if @rye_ssh 
  debug "Opening connection to #{@rye_host} as #{@rye_opts[:user]}"
  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
    @rye_ssh = Net::SSH.start(@rye_host, @rye_opts[:user], @rye_opts || {}) 
  rescue Net::SSH::HostKeyMismatch => ex
    STDERR.puts ex.message
    print "\a" if @rye_info # Ring the bell
    if highline.ask("Continue? ").strip.match(/\Ay|yes|sure|ya\z/i)
      @rye_opts[:paranoid] = false
      retry
    else
      raise Net::SSH::HostKeyMismatch
    end
  rescue Net::SSH::AuthenticationFailed => ex
    print "\a" if retried == 0 && @rye_info # Ring the bell once
    retried += 1
    if STDIN.tty? && retried <= 3
      STDERR.puts "Passwordless login failed for #{@rye_opts[:user]}"
      @rye_opts[:password] = highline.ask("Password: ") { |q| q.echo = '' }
      @rye_opts[:auth_methods] ||= []
      @rye_opts[:auth_methods] << 'password'
      retry
    else
      raise Net::SSH::AuthenticationFailed
    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)



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

def current_umask; @rye_current_umask; end

#current_working_directoryObject

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



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

def current_working_directory; @rye_current_working_directory; end

#disable_quiet_modeObject



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

def disable_quiet_mode; @rye_quiet = false; end

#disable_safe_modeObject



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

def disable_safe_mode; @rye_safe = false; end

#disconnectObject

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



656
657
658
659
660
661
662
663
664
665
666
667
668
# File 'lib/rye/box.rb', line 656

def disconnect
  return unless @rye_ssh && !@rye_ssh.closed?
  begin
    Timeout::timeout(3) do
      @rye_ssh.loop(0.3) { @rye_ssh.busy?; }
    end
  rescue SystemCallError, Timeout::Error => ex
    error "Disconnect timeout (was something still running?)"
  end
  
  debug "Closing connection to #{@rye_ssh.host}"
  @rye_ssh.close
end

#enable_quiet_modeObject



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

def enable_quiet_mode;  @rye_quiet = true; end

#enable_safe_modeObject



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

def enable_safe_mode;  @rye_safe = true; 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


508
509
510
511
# File 'lib/rye/box.rb', line 508

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



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

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.



270
271
272
273
274
275
276
277
278
279
280
281
# File 'lib/rye/box.rb', line 270

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



324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
# File 'lib/rye/box.rb', line 324

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 ["HOME=/home"]
    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



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

def host; @rye_host; end

#host=(val) ⇒ Object



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

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

#host_keyObject

Returns the host SSH keys for this box



315
316
317
318
# File 'lib/rye/box.rb', line 315

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

#impltypeObject



255
256
257
# File 'lib/rye/box.rb', line 255

def impltype
  @rye_impltype
end

#impltype=(val) ⇒ Object



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

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

#inspectObject



300
301
302
303
304
305
306
# File 'lib/rye/box.rb', line 300

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



578
579
580
581
582
583
584
585
586
587
# File 'lib/rye/box.rb', line 578

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

Open an interactive SSH session. This only works if STDIN.tty? returns true. Otherwise it returns the SSH command that would have been run. This requires the SSH command-line executable (ssh).

  • run when set to false, it will return the SSH command as a String

and not open an SSH session.



215
216
217
218
219
220
221
# File 'lib/rye/box.rb', line 215

def interactive_ssh(run=true)
  debug "interactive_ssh with keys: #{Rye.keys.inspect}"
  run = false unless STDIN.tty?      
  cmd = Rye.prepare_command("ssh", "#{@rye_opts[:user]}@#{@rye_host}")
  return cmd unless run
  system(cmd)
end

#keysObject

See Rye.keys



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

def keys; Rye.keys; end

#nicknameObject



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

def nickname; @rye_nickname || host; end

#nickname=(val) ⇒ Object



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

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

#optsObject



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

def opts; @rye_opts; end

#opts=(val) ⇒ Object



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

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.



247
248
249
250
251
252
253
# File 'lib/rye/box.rb', line 247

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



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

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.



597
598
599
600
# File 'lib/rye/box.rb', line 597

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

#post_command_hook=(val) ⇒ Object



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

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


487
488
489
490
# File 'lib/rye/box.rb', line 487

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

#pre_command_hook=(val) ⇒ Object



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

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

#preview_command(*args) ⇒ Object

Returns the command an arguments as a String.



476
477
478
# File 'lib/rye/box.rb', line 476

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

#quietObject



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

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



565
566
567
568
569
570
571
# File 'lib/rye/box.rb', line 565

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

#safeObject



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

def safe; @rye_safe; end

#safe?Boolean

Returns:

  • (Boolean)


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

def safe?; @rye_safe == true; end

#safely(*args, &block) ⇒ Object

See unsafely (except in reverse)



549
550
551
552
553
554
555
# File 'lib/rye/box.rb', line 549

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



285
286
287
288
289
290
291
# File 'lib/rye/box.rb', line 285

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

#stashObject

Returns the current value of the stash @rye_stash



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

def stash; @rye_stash; end

#stash=(val) ⇒ Object

Store a value to the stash @rye_stash



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

def stash=(val); @rye_stash = val; 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)



201
202
203
204
205
206
# File 'lib/rye/box.rb', line 201

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

#to_sObject

Returns user@rye_host



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

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



187
188
189
190
# File 'lib/rye/box.rb', line 187

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

#unsafely(*args, &block) ⇒ Object

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.



540
541
542
543
544
545
546
# File 'lib/rye/box.rb', line 540

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

#userObject



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

def user; (@rye_opts || {})[:user]; end