em-ssh 0.2.1 → 0.3.0.pre0

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/README.md CHANGED
@@ -7,45 +7,50 @@ Em-ssh is not associated with the Jamis Buck's [net-ssh](http://net-ssh.github.c
7
7
 
8
8
  ##Synopsis
9
9
  EM.run do
10
- EM::Ssh.start(host, user, :password => password) do |ssh|
11
- # capture all stderr and stdout output from a remote process
12
- ssh.exec!('uname -a').tap {|r| puts "\nuname: #{r}"}
13
-
14
- # capture only stdout matching a particular pattern
15
- stdout = ""
16
- ssh.exec!("ls -l /home") do |channel, stream, data|
17
- stdout << data if stream == :stdout
18
- end
19
- puts "\n#{stdout}"
20
-
21
- # run multiple processes in parallel to completion
22
- ssh.exec('ping -c 1 www.google.com')
23
- ssh.exec('ping -c 1 www.yahoo.com')
24
- ssh.exec('ping -c 1 www.rakuten.co.jp')
25
-
26
- #open a new channel and configure a minimal set of callbacks, then wait for the channel to finishes (closees).
27
- channel = ssh.open_channel do |ch|
28
- ch.exec "/usr/local/bin/ruby /path/to/file.rb" do |ch, success|
29
- raise "could not execute command" unless success
30
-
31
- # "on_data" is called when the process writes something to stdout
32
- ch.on_data do |c, data|
33
- $stdout.print data
34
- end
35
-
36
- # "on_extended_data" is called when the process writes something to stderr
37
- ch.on_extended_data do |c, type, data|
38
- $stderr.print data
39
- end
40
-
41
- ch.on_close { puts "done!" }
42
- end
43
- end
44
-
45
- channel.wait
46
-
47
- ssh.close
48
- EM.stop
10
+ EM::Ssh.start(host, user, :password => password) do |connection|
11
+ connection.errback do |err|
12
+ $stderr.puts "#{err} (#{err.class})"
13
+ end
14
+ connection.callback do |ssh|
15
+ # capture all stderr and stdout output from a remote process
16
+ ssh.exec!('uname -a').tap {|r| puts "\nuname: #{r}"}
17
+
18
+ # capture only stdout matching a particular pattern
19
+ stdout = ""
20
+ ssh.exec!("ls -l /home") do |channel, stream, data|
21
+ stdout << data if stream == :stdout
22
+ end
23
+ puts "\n#{stdout}"
24
+
25
+ # run multiple processes in parallel to completion
26
+ ssh.exec('ping -c 1 www.google.com')
27
+ ssh.exec('ping -c 1 www.yahoo.com')
28
+ ssh.exec('ping -c 1 www.rakuten.co.jp')
29
+
30
+ #open a new channel and configure a minimal set of callbacks, then wait for the channel to finishes (closees).
31
+ channel = ssh.open_channel do |ch|
32
+ ch.exec "/usr/local/bin/ruby /path/to/file.rb" do |ch, success|
33
+ raise "could not execute command" unless success
34
+
35
+ # "on_data" is called when the process writes something to stdout
36
+ ch.on_data do |c, data|
37
+ $stdout.print data
38
+ end
39
+
40
+ # "on_extended_data" is called when the process writes something to stderr
41
+ ch.on_extended_data do |c, type, data|
42
+ $stderr.print data
43
+ end
44
+
45
+ ch.on_close { puts "done!" }
46
+ end
47
+ end
48
+
49
+ channel.wait
50
+
51
+ ssh.close
52
+ EM.stop
53
+ end
49
54
  end
50
55
  end
51
56
 
data/bin/em-ssh CHANGED
@@ -66,37 +66,45 @@ end
66
66
 
67
67
 
68
68
  EM.run do
69
- EM::Ssh.start(host, options[:user], options) do |connection|
70
- debug "**** connected: #{connection}"
71
- connection.open_channel do |channel|
72
- debug "**** channel: #{channel}"
73
- channel.request_pty(options[:pty] || {}) do |pty,suc|
74
- debug "***** pty: #{pty}; suc: #{suc}"
75
- pty.send_channel_request("shell") do |shell,success|
76
- raise ConnectionError, "Failed to create shell." unless success
77
- debug "***** shell: #{shell}"
78
- connected = true
79
-
80
- shell.on_data { |c,d| $stdout.print d }
81
- shell.on_extended_data { |c,data| $STDERR.print data }
82
- shell.on_eof do
83
- shell.close
84
- EM.stop
85
- end #
86
-
87
- trap("SIGINT") { shell.send_data("\C-c") }
88
- trap("SIGEXIT") do
89
- shell.close
90
- trap("SIGINT", "SIG_DFL")
91
- end #
92
-
93
- conn = EM.watch($stdin, CInput)
94
- conn.shell = shell
95
- conn.notify_readable = true
96
-
97
- end # |shell,success|
98
- end # |pty,suc|
99
- end # |channel|
69
+ EM::Ssh.start(host, options[:user], options) do |ssh|
70
+ ssh.errback do |err|
71
+ puts "#{err} (#{err.class})"
72
+ EM.stop
73
+ end
74
+
75
+ ssh.callback do |connection|
76
+ debug "**** connected: #{connection}"
77
+ connection.open_channel do |channel|
78
+ debug "**** channel: #{channel}"
79
+ channel.request_pty(options[:pty] || {}) do |pty,suc|
80
+ debug "***** pty: #{pty}; suc: #{suc}"
81
+ pty.send_channel_request("shell") do |shell,success|
82
+ raise ConnectionError, "Failed to create shell." unless success
83
+ debug "***** shell: #{shell}"
84
+ connected = true
85
+
86
+ shell.on_data { |c,d| $stdout.print d }
87
+ shell.on_extended_data { |c,data| $STDERR.print data }
88
+ shell.on_eof do
89
+ shell.close
90
+ EM.stop
91
+ end #
92
+
93
+ trap("SIGINT") { shell.send_data("\C-c") }
94
+ trap("SIGEXIT") do
95
+ shell.close
96
+ trap("SIGINT", "SIG_DFL")
97
+ end #
98
+
99
+ conn = EM.watch($stdin, CInput)
100
+ conn.shell = shell
101
+ conn.notify_readable = true
102
+
103
+ end # |shell,success|
104
+ end # |pty,suc|
105
+ end # |channel|
106
+ end
107
+
100
108
  end # |connection|
101
109
  end # EM.start
102
110
 
data/lib/em-ssh.rb CHANGED
@@ -50,8 +50,8 @@ module EventMachine
50
50
  # channel.request_pty(options[:pty] || {}) do |pty,suc|
51
51
  def connect(host, user, opts = {}, &blk)
52
52
  logger.debug("#{self}.connect(#{host}, #{user}, #{opts})")
53
- options = { :host => host, :user => user, :port => DEFAULT_PORT, :callback => blk }.merge(opts)
54
- EM.connect(options[:host], options[:port], Connection, options)
53
+ options = { :host => host, :user => user, :port => DEFAULT_PORT }.merge(opts)
54
+ EM.connect(options[:host], options[:port], Connection, options, &blk)
55
55
  end
56
56
  alias :start :connect
57
57
  end # << self
@@ -5,6 +5,7 @@ module EventMachine
5
5
  # itself into Net::SSH so that the EventMachine reactor loop can take the place of the Net::SSH event loop.
6
6
  # Most of the methods here are only for compatibility with Net::SSH
7
7
  class Connection < EventMachine::Connection
8
+ include EM::Deferrable
8
9
  include Log
9
10
 
10
11
  # Allows other objects to register callbacks with events that occur on a Ssh instance
@@ -127,11 +128,26 @@ module EventMachine
127
128
  @timeout = options[:timeout] || TIMEOUT
128
129
 
129
130
  begin
130
- on(:connected, &options[:callback]) if options[:callback]
131
- @nocon = on(:closed) { raise ConnectionFailed, @host }
132
- @contimeout = EM::Timer.new(@timeout) { raise ConnectionTimeout, @host }
131
+ on(:connected) do |session|
132
+ succeed(session, @host)
133
+ end
134
+ on(:error) do |e|
135
+ fail(e)
136
+ close_connection
137
+ end
138
+ @nocon = on(:closed) do
139
+ fail(SshError.new(@host))
140
+ close_connection
141
+ end
142
+ @contimeout = EM::Timer.new(@timeout) do
143
+ fail(ConnectionTimeout.new(@host))
144
+ close_connection
145
+ end
133
146
 
134
- @error_callback = lambda { |code| raise SshError.new(code) }
147
+ @error_callback = lambda do |code|
148
+ fail(SshError.new(code))
149
+ close_connection
150
+ end
135
151
 
136
152
  @host_key_verifier = select_host_key_verifier(options[:paranoid])
137
153
  @server_version = ServerVersion.new(self)
@@ -149,7 +165,6 @@ module EventMachine
149
165
  fire(:connected, Session.new(self, options))
150
166
  else
151
167
  fire(:error, Net::SSH::AuthenticationFailed.new(user))
152
- close_connection
153
168
  end # auth.authenticate("ssh-connection", user, options[:password])
154
169
  end.resume # Fiber
155
170
  end # :algo_init
@@ -157,7 +172,7 @@ module EventMachine
157
172
 
158
173
  rescue Exception => e
159
174
  log.fatal("caught an error during initialization: #{e}\n #{e.backtrace.join("\n ")}")
160
- Process.exit
175
+ fail(e)
161
176
  end # begin
162
177
  self
163
178
  end # initialize(options = {})
@@ -273,7 +288,12 @@ module EventMachine
273
288
  when :very then
274
289
  Net::SSH::Verifiers::Strict.new
275
290
  else
276
- paranoid.respond_to?(:verify) ? paranoid : (raise ArgumentError.new("argument to :paranoid is not valid: #{paranoid.inspect}"))
291
+ if paranoid.respond_to?(:verify)
292
+ paranoid
293
+ else
294
+ fail(@host, ArgumentError.new("argument to :paranoid is not valid: #{paranoid.inspect}"))
295
+ close_connection
296
+ end # paranoid.respond_to?(:verify)
277
297
  end # paranoid
278
298
  end # select_host_key_verifier(paranoid)
279
299
  end # class::Connection < EventMachine::Connection
@@ -61,7 +61,9 @@ module EventMachine
61
61
  @packet_length = @packet.read_long
62
62
  end
63
63
  need = @packet_length + 4 - server.block_size
64
- raise SshError, "padding error, need #{need} block #{server.block_size}" if need % server.block_size != 0
64
+ if need % server.block_size != 0
65
+ @connection.fire(:error, SshError.new("padding error, need #{need} block #{server.block_size}"))
66
+ end
65
67
 
66
68
  return nil if available < need + server.hmac.mac_length
67
69
 
@@ -82,7 +84,10 @@ module EventMachine
82
84
  padding = @packet.read(padding_length) if padding_length > 0
83
85
 
84
86
  my_computed_hmac = server.hmac.digest([server.sequence_number, @packet.content].pack("NA*"))
85
- raise Net::SSH::Exception, "corrupted mac detected" if real_hmac != my_computed_hmac
87
+ if real_hmac != my_computed_hmac
88
+ @connection.fire(:error, Net::SSH::Exception.new("corrupted mac detected"))
89
+ return
90
+ end
86
91
 
87
92
  # try to decompress the payload, in case compression is active
88
93
  payload = server.decompress(payload)
@@ -23,7 +23,9 @@ module EventMachine
23
23
  if @version[-1] == "\n"
24
24
  @version.chomp!
25
25
  log.debug("server version: #{@version}")
26
- raise SshError.new("incompatible SSH version `#{@version}'") unless @version.match(/^SSH-(1\.99|2\.0)-/)
26
+ unless @version.match(/^SSH-(1\.99|2\.0)-/)
27
+ return connection.fire(:error, SshError.new("incompatible SSH version `#{@version}'"))
28
+ end
27
29
  log.debug("local version: #{Net::SSH::Transport::ServerVersion::PROTO_VERSION}")
28
30
  connection.send_data("#{Net::SSH::Transport::ServerVersion::PROTO_VERSION}\r\n")
29
31
  cb.cancel
@@ -34,7 +34,10 @@ module EventMachine
34
34
 
35
35
  def register_callbacks
36
36
  transport.on(:packet) do |packet|
37
- raise SshError, "unexpected response #{packet.type} (#{packet.inspect})" unless MAP.key?(packet.type)
37
+ unless MAP.key?(packet.type)
38
+ transport.fire(:error, SshError.new("unexpected response #{packet.type} (#{packet.inspect})"))
39
+ return
40
+ end
38
41
  send(MAP[packet.type], packet)
39
42
  end # |packet|
40
43
 
data/lib/em-ssh/shell.rb CHANGED
@@ -236,11 +236,15 @@ module EventMachine
236
236
  return if connected?
237
237
  trace = caller
238
238
  f = Fiber.current
239
- con = ::EM::Ssh.start(host, user, connect_opts) { |connection| f.resume(@connection = connection) }
240
- con.on(:error) do |e|
241
- e.set_backtrace(trace + Array(e.backtrace))
242
- fire(:error, e)
243
- f.resume(e)
239
+ ::EM::Ssh.start(host, user, connect_opts) do |connection|
240
+ connection.callback do |ssh|
241
+ f.resume(@connection = ssh)
242
+ end # ssh
243
+ connection.errback do |e|
244
+ e.set_backtrace(trace + Array(e.backtrace))
245
+ fire(:error, e)
246
+ f.resume(e)
247
+ end # err
244
248
  end
245
249
  return Fiber.yield
246
250
  end
@@ -1,5 +1,5 @@
1
1
  module EventMachine
2
2
  class Ssh
3
- VERSION='0.2.1'
3
+ VERSION='0.3.0.pre0'
4
4
  end # class::Ssh
5
5
  end # module::EventMachine
metadata CHANGED
@@ -1,19 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: em-ssh
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
5
- prerelease:
4
+ version: 0.3.0.pre0
5
+ prerelease: 6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Caleb Crane
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-02 00:00:00.000000000Z
12
+ date: 2012-05-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: eventmachine
16
- requirement: &70209705582020 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70209705582020
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: net-ssh
27
- requirement: &70209705581560 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,10 +37,15 @@ dependencies:
32
37
  version: '0'
33
38
  type: :runtime
34
39
  prerelease: false
35
- version_requirements: *70209705581560
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: ruby-termios
38
- requirement: &70209705581140 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
51
  - - ! '>='
@@ -43,10 +53,15 @@ dependencies:
43
53
  version: '0'
44
54
  type: :development
45
55
  prerelease: false
46
- version_requirements: *70209705581140
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: highline
49
- requirement: &70209705580720 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
50
65
  none: false
51
66
  requirements:
52
67
  - - ! '>='
@@ -54,7 +69,12 @@ dependencies:
54
69
  version: '0'
55
70
  type: :development
56
71
  prerelease: false
57
- version_requirements: *70209705580720
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
58
78
  description: ''
59
79
  email:
60
80
  - em-ssh@simulacre.org
@@ -98,7 +118,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
98
118
  version: 1.3.6
99
119
  requirements: []
100
120
  rubyforge_project:
101
- rubygems_version: 1.8.10
121
+ rubygems_version: 1.8.21
102
122
  signing_key:
103
123
  specification_version: 3
104
124
  summary: An EventMachine compatible net-ssh