rye 0.7.5 → 0.7.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES.txt +14 -1
- data/lib/rye.rb +12 -7
- data/lib/rye/box.rb +75 -33
- data/lib/rye/rap.rb +2 -3
- data/rye.gemspec +1 -1
- metadata +2 -2
data/CHANGES.txt
CHANGED
@@ -7,7 +7,20 @@ TODO
|
|
7
7
|
* Add S3 support for Rye::Box.upload / download
|
8
8
|
|
9
9
|
|
10
|
-
#### 0.7.
|
10
|
+
#### 0.7.6 (2009-06-19) #############################
|
11
|
+
|
12
|
+
* FIXED: Raise Rye::NoPty exception when Net::SSH returns message
|
13
|
+
"Pseudo-terminal will not be allocated because stdin is not a terminal."
|
14
|
+
* FIXED: Rye::Box#disconnect would hang in some instances. Now waits 3 seconds.
|
15
|
+
* FIXED: Bug in net_ssh_exec which was causing it to not return an exit code
|
16
|
+
* CHANGE: All exceptions now inherit from Rye::Error (Runtimerror)
|
17
|
+
* CHANGE: A NoPassword exception is raised when a password prompt returns nil.
|
18
|
+
* CHANGE: pre_command_hook block arguments have changed:
|
19
|
+
NEW: complete command, user, host, nickname
|
20
|
+
OLD: command, args, user, host, nickname
|
21
|
+
|
22
|
+
|
23
|
+
#### 0.7.5 (2009-06-13) #############################
|
11
24
|
|
12
25
|
* FIXED: Rye::Set methods were not accepting or passing blocks.
|
13
26
|
* ADDED: Rye::Set#user and Rye::Set#opts methods
|
data/lib/rye.rb
CHANGED
@@ -11,6 +11,7 @@ require 'net/scp'
|
|
11
11
|
require 'openssl'
|
12
12
|
require 'tempfile'
|
13
13
|
require 'highline'
|
14
|
+
require 'timeout'
|
14
15
|
|
15
16
|
require 'storable'
|
16
17
|
require 'sysinfo'
|
@@ -59,21 +60,25 @@ module Rye
|
|
59
60
|
# Accessor for an instance of SystemInfo
|
60
61
|
def sysinfo; SYSINFO; end
|
61
62
|
|
62
|
-
class
|
63
|
-
class
|
64
|
-
class
|
65
|
-
|
66
|
-
|
63
|
+
class RyeError < RuntimeError; end
|
64
|
+
class NoBoxes < RyeError; end
|
65
|
+
class NoPassword < RyeError
|
66
|
+
def message; "Password prompt did not return a value"; end
|
67
|
+
end
|
68
|
+
class NoHost < RyeError; end
|
69
|
+
class NotConnected < RyeError; end
|
70
|
+
class CommandNotFound < RyeError; end
|
71
|
+
class NoPty < RyeError
|
67
72
|
def message; "Could not obtain pty (i.e. an interactive ssh session)"; end
|
68
73
|
end
|
69
|
-
class CommandError <
|
74
|
+
class CommandError < RyeError
|
70
75
|
attr_reader :rap
|
71
76
|
# * +rap+ a Rye::Rap object
|
72
77
|
def initialize(rap)
|
73
78
|
@rap = rap
|
74
79
|
end
|
75
80
|
def message
|
76
|
-
"(code: %s)
|
81
|
+
"%s (code: %s)" % [@rap.stderr.join($/), @rap.exit_code]
|
77
82
|
end
|
78
83
|
def stderr; @rap.stderr if @rap; end
|
79
84
|
def stdout; @rap.stdout if @rap; end
|
data/lib/rye/box.rb
CHANGED
@@ -194,17 +194,7 @@ module Rye
|
|
194
194
|
disconnect
|
195
195
|
connect
|
196
196
|
end
|
197
|
-
|
198
|
-
|
199
|
-
# Close the SSH session with +@rye_host+. This is called
|
200
|
-
# automatically at exit if the connection is open.
|
201
|
-
def disconnect
|
202
|
-
return unless @rye_ssh && !@rye_ssh.closed?
|
203
|
-
@rye_ssh.loop(0.1) { @rye_ssh.busy? }
|
204
|
-
debug "Closing connection to #{@rye_ssh.host}"
|
205
|
-
@rye_ssh.close
|
206
|
-
end
|
207
|
-
|
197
|
+
|
208
198
|
|
209
199
|
# Open an interactive SSH session. This only works if STDIN.tty?
|
210
200
|
# returns true. Otherwise it returns the SSH command that would
|
@@ -594,6 +584,22 @@ module Rye
|
|
594
584
|
self
|
595
585
|
end
|
596
586
|
|
587
|
+
# Close the SSH session with +@rye_host+. This is called
|
588
|
+
# automatically at exit if the connection is open.
|
589
|
+
def disconnect
|
590
|
+
return unless @rye_ssh && !@rye_ssh.closed?
|
591
|
+
begin
|
592
|
+
Timeout::timeout(3) do
|
593
|
+
@rye_ssh.loop(0.3) { @rye_ssh.busy?; }
|
594
|
+
end
|
595
|
+
rescue Timeout::Error => ex
|
596
|
+
error "Disconnect timeout (was something still running?)"
|
597
|
+
end
|
598
|
+
|
599
|
+
debug "Closing connection to #{@rye_ssh.host}"
|
600
|
+
@rye_ssh.close
|
601
|
+
end
|
602
|
+
|
597
603
|
|
598
604
|
private
|
599
605
|
|
@@ -655,12 +661,6 @@ module Rye
|
|
655
661
|
cmd_clean = [cwd, cmd_clean].join(' && ')
|
656
662
|
end
|
657
663
|
|
658
|
-
info "COMMAND: #{cmd_clean}"
|
659
|
-
debug "Executing: %s" % cmd_clean
|
660
|
-
|
661
|
-
if @rye_pre_command_hook.is_a?(Proc)
|
662
|
-
@rye_pre_command_hook.call(cmd, args, user, host, nickname)
|
663
|
-
end
|
664
664
|
|
665
665
|
## NOTE: Do not raise a CommandNotFound exception in this method.
|
666
666
|
# We want it to be possible to define methods to a single instance
|
@@ -672,6 +672,13 @@ module Rye
|
|
672
672
|
## raise Rye::CommandNotFound unless self.can?(cmd)
|
673
673
|
|
674
674
|
begin
|
675
|
+
info "COMMAND: #{cmd_clean}"
|
676
|
+
debug "Executing: %s" % cmd_clean
|
677
|
+
|
678
|
+
if @rye_pre_command_hook.is_a?(Proc)
|
679
|
+
@rye_pre_command_hook.call(cmd_clean, user, host, nickname)
|
680
|
+
end
|
681
|
+
|
675
682
|
stdout, stderr, ecode, esignal = net_ssh_exec!(cmd_clean)
|
676
683
|
|
677
684
|
rap = Rye::Rap.new(self)
|
@@ -681,16 +688,30 @@ module Rye
|
|
681
688
|
rap.exit_signal = esignal
|
682
689
|
rap.cmd = cmd
|
683
690
|
|
691
|
+
#info "stdout: #{rap.stdout}"
|
692
|
+
#info "stderr: #{rap.stderr}"
|
693
|
+
#info "exit_code: #{rap.exit_code}"
|
694
|
+
|
684
695
|
# It seems a convention for various commands to return -1
|
685
696
|
# when something only mildly concerning happens. ls even
|
686
697
|
# returns -1 for apparently no reason sometimes. In any
|
687
698
|
# case, the real errors are the ones greater than zero
|
688
|
-
raise Rye::CommandError.new(rap) if ecode
|
699
|
+
raise Rye::CommandError.new(rap) if ecode != 0
|
689
700
|
|
690
701
|
rescue Exception => ex
|
691
|
-
|
692
|
-
|
693
|
-
|
702
|
+
choice = nil
|
703
|
+
@rye_exception_hook.each_pair do |klass,act|
|
704
|
+
next unless ex.kind_of? klass
|
705
|
+
choice = @rye_exception_hook[klass].call(ex)
|
706
|
+
break
|
707
|
+
end
|
708
|
+
if choice == :retry
|
709
|
+
retry
|
710
|
+
elsif choice == :skip
|
711
|
+
# do nothing
|
712
|
+
else
|
713
|
+
raise ex
|
714
|
+
end
|
694
715
|
end
|
695
716
|
|
696
717
|
@rye_post_command_hook.call(rap) if @rye_post_command_hook.is_a?(Proc)
|
@@ -729,42 +750,63 @@ module Rye
|
|
729
750
|
# http://www.ruby-forum.com/topic/169997
|
730
751
|
#
|
731
752
|
def net_ssh_exec!(command)
|
732
|
-
|
753
|
+
|
733
754
|
block ||= Proc.new do |channel, type, data|
|
755
|
+
|
734
756
|
channel[:stdout] ||= ""
|
735
757
|
channel[:stderr] ||= ""
|
736
|
-
channel[:exit_code] ||= 0
|
737
758
|
channel[:stdout] << data if type == :stdout
|
759
|
+
|
738
760
|
if type == :stderr
|
739
761
|
# NOTE: Use sudo to test this since it prompts for a passwords.
|
740
762
|
# Use sudo -K to kill the user's timestamp (ask for a password every time)
|
741
763
|
if data =~ /Password:/
|
742
764
|
ret = Annoy.get_user_input("Password: ", '*')
|
765
|
+
raise Rye::NoPassword if ret.nil?
|
743
766
|
channel.send_data "#{ret}\n"
|
744
767
|
else
|
745
768
|
channel[:stderr] << data
|
746
769
|
end
|
770
|
+
|
771
|
+
# If someone tries to open an interactive ssh session
|
772
|
+
# through a regular Rye::Box command, Net::SSH will
|
773
|
+
# return the following error and appear to hang. We
|
774
|
+
# catch it and raise the appropriate exception.
|
775
|
+
raise Rye::NoPty if data =~ /Pseudo-terminal will not/
|
776
|
+
|
747
777
|
end
|
748
|
-
|
749
|
-
# Anything greater than 0 is an error
|
750
|
-
channel[:exit_code] = data.read_long
|
751
|
-
end
|
752
|
-
channel.on_request("exit-signal") do |ch, data|
|
753
|
-
# This should be the POSIX SIGNAL that ended the process
|
754
|
-
channel[:exit_signal] = data.read_long
|
755
|
-
end
|
778
|
+
|
756
779
|
end
|
757
780
|
|
758
781
|
channel = @rye_ssh.exec(command, &block)
|
759
782
|
|
783
|
+
channel.on_request("exit-status") do |ch, data|
|
784
|
+
# Anything greater than 0 is an error
|
785
|
+
channel[:exit_code] = data.read_long
|
786
|
+
end
|
787
|
+
channel.on_request("exit-signal") do |ch, data|
|
788
|
+
# This should be the POSIX SIGNAL that ended the process
|
789
|
+
channel[:exit_signal] = data.read_long
|
790
|
+
end
|
791
|
+
|
760
792
|
channel.wait # block until we get a response
|
761
793
|
channel.request_pty do |ch, success|
|
762
794
|
raise Rye::NoPty if !success
|
763
795
|
end
|
764
796
|
|
765
|
-
|
797
|
+
## I'm getting weird behavior with exit codes. Sometimes
|
798
|
+
## a command which usually returns an exit code will not
|
799
|
+
## return one the next time it's run. The following crap
|
800
|
+
## was from the debugging.
|
801
|
+
##Kernel.sleep 5
|
802
|
+
###channel.close
|
803
|
+
#channel.eof!
|
804
|
+
##p [:active, channel.active?]
|
805
|
+
##p [:closing, channel.closing?]
|
806
|
+
##p [:eof, channel.eof?]
|
807
|
+
|
808
|
+
channel[:exit_code] ||= 0
|
766
809
|
channel[:exit_code] &&= channel[:exit_code].to_i
|
767
|
-
|
768
810
|
channel[:stderr].gsub!(/bash: line \d+:\s+/, '') if channel[:stderr]
|
769
811
|
|
770
812
|
[channel[:stdout], channel[:stderr], channel[:exit_code], channel[:exit_signal]]
|
data/lib/rye/rap.rb
CHANGED
@@ -76,13 +76,12 @@ module Rye;
|
|
76
76
|
# it's just an exit code returned by Net::SSH.
|
77
77
|
# Returns the exit code as an Integer.
|
78
78
|
def add_exit_code(code)
|
79
|
-
code =
|
79
|
+
code = 0 if code.nil?
|
80
80
|
if code.is_a?(Process::Status)
|
81
81
|
@exit_code, @pid = code.exitstatus.to_i, code.pid
|
82
82
|
else
|
83
83
|
@exit_code = code.to_i
|
84
84
|
end
|
85
|
-
@exit_code
|
86
85
|
end
|
87
86
|
def code; @exit_code; end
|
88
87
|
|
@@ -91,7 +90,7 @@ module Rye;
|
|
91
90
|
def to_s
|
92
91
|
return self.first if self.size == 1
|
93
92
|
return "" if self.size == 0
|
94
|
-
|
93
|
+
super
|
95
94
|
end
|
96
95
|
|
97
96
|
# Output STDOUT content to (remote) +path+
|
data/rye.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
@spec = Gem::Specification.new do |s|
|
2
2
|
s.name = "rye"
|
3
3
|
s.rubyforge_project = "rye"
|
4
|
-
s.version = "0.7.
|
4
|
+
s.version = "0.7.6"
|
5
5
|
s.summary = "Rye: Safely run SSH commands on a bunch of machines at the same time (from Ruby)."
|
6
6
|
s.description = s.summary
|
7
7
|
s.author = "Delano Mandelbaum"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rye
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Delano Mandelbaum
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-06-
|
12
|
+
date: 2009-06-19 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|