Class: Rye::Box
- Inherits:
-
Object
- Object
- Rye::Box
- 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
-
#rye_pty ⇒ Object
Returns the value of attribute rye_pty.
-
#rye_shell ⇒ Object
Returns the value of attribute rye_shell.
Instance Method Summary collapse
-
#==(other) ⇒ Object
Compares itself with the
otherbox. -
#[](fpath = nil) ⇒ Object
Change the current working directory (sort of).
-
#add_keys(*keys) ⇒ Object
(also: #add_key)
Add one or more private keys to the list of key paths.
-
#batch(*args, &block) ⇒ Object
Execute a block in the context of an instance of Rye::Box.
-
#cd(fpath = nil) ⇒ Object
Like [] except it returns an empty Rye::Rap object to mimick a regular command method.
-
#connect(reconnect = true) ⇒ Object
Open an SSH session with @rye_host.
-
#current_umask ⇒ Object
The most recent valud for umask (or 0022).
-
#current_working_directory ⇒ Object
The most recent value from Box.cd or Box.[].
- #debug? ⇒ Boolean
- #disable_quiet_mode ⇒ Object
- #disable_safe_mode ⇒ Object
- #disable_sudo ⇒ Object
-
#disconnect ⇒ Object
Close the SSH session with @rye_host.
- #enable_quiet_mode ⇒ Object
- #enable_safe_mode ⇒ Object
- #enable_sudo ⇒ Object
- #error? ⇒ Boolean
-
#exception_hook(klass, &block) ⇒ Object
Supply a block to be called whenever there’s an Exception.
-
#exception_hook=(val) ⇒ Object
A Hash.
-
#getenv(key = nil) ⇒ Object
Returns the hash containing the parsed output of “env” on the remote machine.
-
#guess_user_home(other_user = nil) ⇒ Object
Uses the output of “useradd -D” to determine the default home directory.
- #host ⇒ Object
- #host=(val) ⇒ Object
-
#host_key ⇒ Object
Returns the host SSH keys for this box.
- #impltype ⇒ Object
- #impltype=(val) ⇒ Object
- #info? ⇒ Boolean
-
#initialize(host = 'localhost', opts = {}) ⇒ Box
constructor
-
hostThe hostname to connect to.
-
- #inspect ⇒ Object
-
#instance_exec(*args, &block) ⇒ Object
!> method redefined; discarding old instance_exec.
-
#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).
-
#keys ⇒ Object
See Rye.keys.
-
#method_missing(cmd, *args, &block) ⇒ Object
(also: #execute)
A handler for undefined commands.
- #nickname ⇒ Object
- #nickname=(val) ⇒ Object
- #opts ⇒ Object
- #opts=(val) ⇒ Object
-
#ostype ⇒ Object
Return the value of uname in lowercase This is a temporary fix.
- #ostype=(val) ⇒ Object
-
#post_command_hook(&block) ⇒ Object
Supply a block to be called after every command.
- #post_command_hook=(val) ⇒ Object
-
#pre_command_hook(&block) ⇒ Object
Supply a block to be called before every command.
- #pre_command_hook=(val) ⇒ Object
-
#preview_command(*args) ⇒ Object
Returns the command an arguments as a String.
- #quiet ⇒ Object
-
#quietly(*args, &block) ⇒ Object
Like batch, except it enables quiet mode before executing the block.
-
#remove_keys(*keys) ⇒ Object
(also: #remove_key)
Remove one or more private keys fromt he list of key paths.
- #root? ⇒ Boolean
- #safe ⇒ Object
- #safe? ⇒ Boolean
-
#safely(*args, &block) ⇒ Object
See unsafely (except in reverse).
-
#setenv(n, v) ⇒ Object
(also: #add_env)
Add an environment variable.
-
#ssh_config_options(host) ⇒ Object
Parse SSH config files for use with Net::SSH.
-
#stash ⇒ Object
Returns the current value of the stash @rye_stash.
-
#stash=(val) ⇒ Object
Store a value to the stash @rye_stash.
-
#stdout_hook(&block) ⇒ Object
Supply a block to be called every time a command receives STDOUT data.
- #stdout_hook=(val) ⇒ Object
-
#sudo(*args, &block) ⇒ Object
Like batch, except it enables sudo mode before executing the block.
- #sudo? ⇒ Boolean
-
#switch_user(newuser) ⇒ Object
Reconnect as another user.
- #templates ⇒ Object
- #templates? ⇒ Boolean
-
#to_s ⇒ Object
Returns user@rye_host.
-
#umask=(val = '0022') ⇒ Object
Change the current umask (sort of – works the same way as cd) The default umask is 0022.
-
#unsafely(*args, &block) ⇒ Object
(also: #wildly)
Like batch, except it disables safe mode before executing the block.
- #user ⇒ Object
- #via ⇒ Object
- #via=(val) ⇒ Object
- #via? ⇒ Boolean
-
#via_hop(*args) ⇒ Object
-
hopsRye::Hop objects will be added directly to the set.
-
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
-
hostThe hostname to connect to. Default: localhost. -
optsa 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
hostenvironment 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 = (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_pty ⇒ Object
Returns the value of attribute rye_pty.
37 38 39 |
# File 'lib/rye/box.rb', line 37 def rye_pty @rye_pty end |
#rye_shell ⇒ Object
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.
-
keysis 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
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.
-
reconnectDisconnect first if already connected. The default
is true. When set to false, connect will do nothing if already connected.
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. 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_umask ⇒ Object
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_directory ⇒ Object
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
81 |
# File 'lib/rye/box.rb', line 81 def debug?; !@rye_debug.nil?; end |
#disable_quiet_mode ⇒ Object
71 |
# File 'lib/rye/box.rb', line 71 def disable_quiet_mode; @rye_quiet = false; end |
#disable_safe_mode ⇒ Object
67 |
# File 'lib/rye/box.rb', line 67 def disable_safe_mode; @rye_safe = false; end |
#disable_sudo ⇒ Object
49 |
# File 'lib/rye/box.rb', line 49 def disable_sudo; @rye_sudo = false; end |
#disconnect ⇒ Object
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.})" debug ex.backtrace rescue Interrupt debug "Exiting..." end end |
#enable_quiet_mode ⇒ Object
70 |
# File 'lib/rye/box.rb', line 70 def enable_quiet_mode; @rye_quiet = true; end |
#enable_safe_mode ⇒ Object
66 |
# File 'lib/rye/box.rb', line 66 def enable_safe_mode; @rye_safe = true; end |
#enable_sudo ⇒ Object
48 |
# File 'lib/rye/box.rb', line 48 def enable_sudo; @rye_sudo = true; end |
#error? ⇒ 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 |
#host ⇒ Object
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_key ⇒ Object
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 |
#impltype ⇒ Object
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
80 |
# File 'lib/rye/box.rb', line 80 def info?; !@rye_info.nil?; end |
#inspect ⇒ Object
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 |
#nickname ⇒ Object
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 |
#opts ⇒ Object
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 |
#ostype ⇒ Object
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 |
#quiet ⇒ Object
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.
-
keysis 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
43 |
# File 'lib/rye/box.rb', line 43 def root?; user.to_s == "root" end |
#safe ⇒ Object
41 |
# File 'lib/rye/box.rb', line 41 def safe; @rye_safe; end |
#safe? ⇒ 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 (host) return Net::SSH::Config.for(host) end |
#stash ⇒ Object
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
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.
-
newuserThe 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 |
#templates ⇒ Object
45 |
# File 'lib/rye/box.rb', line 45 def templates; @rye_templates; end |
#templates? ⇒ Boolean
46 |
# File 'lib/rye/box.rb', line 46 def templates?; !@rye_templates.nil?; end |
#to_s ⇒ Object
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 |
#user ⇒ Object
42 |
# File 'lib/rye/box.rb', line 42 def user; @rye_user; end |
#via ⇒ Object
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
79 |
# File 'lib/rye/box.rb', line 79 def via?; !@rye_via.nil?; end |
#via_hop(*args) ⇒ Object
-
hopsRye::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 |