remote-dcl 0.2.0 → 0.3.0

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.
@@ -5,22 +5,22 @@
5
5
  Remote-DCL is a Ruby script to execute a script at a remote server.
6
6
  DCL calles in the script creates PNG images at the remote,
7
7
  and send them to local and then display the images.
8
- It avoid X connection between the local and the remote,
8
+ It avoids X connection between the local and the remote,
9
9
  so could reduce execution time.
10
10
 
11
11
 
12
12
  == Requires
13
13
  * At remote server
14
- * <a href="http://www.ruby-lang.org/">Ruby</a>
14
+ * Ruby (http://www.ruby-lang.org/)
15
15
  * Ruby libraries which are required in your script (including DCL)
16
16
  * stdbuf command
17
17
  * ssh server
18
18
  * Xvfb
19
19
  xvfb-run command (optional)
20
20
  * At local
21
- * <a href="http://www.ruby-lang.org/">Ruby</a>
22
- * <a href="http://ruby-gnome2.sourceforge.jp/ja/">Ruby/GTK2,Ruby/GdkPixbuf2</a>
23
- * ssh client
21
+ * Ruby (http://www.ruby-lang.org/)
22
+ * Ruby/GTK2, Ruby/GdkPixbuf2 (http://ruby-gnome2.sourceforge.jp/ja/)
23
+ * Net::SSH (http://net-ssh.rubyforge.org/)
24
24
 
25
25
 
26
26
  == Install / Download
@@ -45,7 +45,7 @@ Note: xvfb-run command lounch Xvfb server internally, and the lounching is occue
45
45
  It takes some seconds, so lounching Xvfb server by your self reduces execution time of remote-dcl.
46
46
 
47
47
  ==== At local
48
- % remote-dcl [--display=] [--dir=] [--remote] server_name script_name [args]
48
+ % remote-dcl [--display=] [--dir=] [--user=] [--password=] [--remote] server_name script_name [args]
49
49
  * server_name:
50
50
  server name at which the script is execued
51
51
  * script_name:
@@ -56,9 +56,15 @@ It takes some seconds, so lounching Xvfb server by your self reduces execution t
56
56
  * dir (optional):
57
57
  directory name of the remote server at which the script is executed
58
58
  If this is ommited, the script is executed at the home directory.
59
+ * user (optional)
60
+ user name of remote server for ssh connection.
61
+ User name can be specified by username@server_name format as server_name
62
+ * password (optional)
63
+ password of user for ssh connection
64
+ If this is ommited, password is asked in prompt.
59
65
  * remote (optional):
60
66
  If --remote option is set, the script should be at the remote server,
61
- else at local.
67
+ otherwise at local.
62
68
 
63
69
  === User Interface
64
70
  Actions with key and mouse events are the followings:
@@ -13,14 +13,16 @@ usage if ARGV.index("--help") || ARGV.index("-h")
13
13
  opts = {
14
14
  "display" => nil,
15
15
  "dir" => nil,
16
- "remote" => false
16
+ "user" => nil,
17
+ "password" => nil,
18
+ "remote" => false,
17
19
  }
18
20
  opts.keys.each do |name|
19
21
  ARGV.dup.each do |opt|
20
22
  next unless /\A--#{name}/ =~ opt
21
23
  val = $' && $'[1..-1]
22
24
  case name
23
- when "display", "dir"
25
+ when "display", "dir", "user", "password"
24
26
  opts[name] = val
25
27
  when "remote"
26
28
  opts[name] = true
@@ -146,23 +148,35 @@ Process.wait(pid)
146
148
  EOC
147
149
 
148
150
 
149
- def escape(str)
151
+ def escape_ruby(str) # escape special charactors
152
+ str.gsub!(/\$/, '\$')
153
+ end
154
+ def escape(str) # escape semi-colon and back-slash
150
155
  str.gsub!("\\"){"\\\\"}
151
156
  str.gsub!(/"/,'\"')
152
157
  end
153
158
 
154
159
  escape remote_code
160
+ escape_ruby remote_code
155
161
  #cmd = "ruby -e \"#{remote_code}\""
156
162
  cmd = "stdbuf -i0 -o0 -e0 ruby -e \"#{remote_code}\" #{ARGV.join(' ')}"
157
163
 
158
164
  class Viewer
159
- def initialize(io)
165
+ @@exist = false
166
+ def initialize(channel)
167
+ if @@exist
168
+ raise "already exist an instance"
169
+ end
170
+ @@exist = true
171
+ @wait = false # true when a frame was rendered and waiting user's action
172
+ @skip = false
173
+
174
+ Gtk.init
160
175
  @window = Gtk::Window.new
161
176
  @window.realize
162
177
  @drawable = @window.window
163
178
  @gc = Gdk::GC.new(@drawable)
164
179
  @pixbuf = nil
165
- @wait = true
166
180
  @window.add_events(Gdk::Event::BUTTON_RELEASE_MASK)
167
181
  @window.signal_connect("expose_event") do |w,e|
168
182
  expose
@@ -177,46 +191,53 @@ class Viewer
177
191
  when "Return", "space", "n"
178
192
  next_fig
179
193
  when "s"
180
- print "skip waiting\n"
181
- @io.puts c
194
+ unless @skip
195
+ print "skip waiting\n"
196
+ @channel.send_data("s\n")
197
+ @skip = true
198
+ end
182
199
  when "q"
183
- quit
200
+ quit!
184
201
  end
185
202
  true
186
203
  end
187
204
  @window.signal_connect("delete_event") do
188
- quit
205
+ quit!
189
206
  false
190
207
  end
191
- @io = io
208
+ @channel = channel
192
209
  end
193
210
  def eof=(boolean)
194
- @eof = true
211
+ @eof = boolean
195
212
  end
196
213
  def eof
197
214
  return @eof if @eof
198
- @eof = @io.closed?
215
+ @eof = !@channel.active?
199
216
  end
200
217
  def next_fig
201
218
  if eof
202
- quit
219
+ quit!
203
220
  elsif @wait
204
221
  # print "next\n"
205
- @io.puts "n"
206
- @io.flush
222
+ @channel.send_data "n\n"
207
223
  @wait = false
208
224
  end
209
225
  end
210
226
  def quit
227
+ quit! unless @wait
228
+ end
229
+ def quit!
211
230
  unless @quit
212
231
  # print "quit\n"
213
232
  begin
214
- @io.puts("q") unless eof
215
- @io.flush
233
+ unless eof
234
+ @channel.send_data "q\n"
235
+ end
216
236
  rescue
217
237
  end
218
- Gtk.main_quit
238
+ @channel.eof! unless @channel.eof?
219
239
  @quit = true
240
+ Gtk.main_quit
220
241
  end
221
242
  end
222
243
  def expose
@@ -240,47 +261,92 @@ class Viewer
240
261
  end
241
262
 
242
263
 
243
- escape cmd
244
- cmd = "cd #{opts["dir"]} ; " + cmd if opts["dir"]
264
+
245
265
  if opts["display"]
246
266
  cmd = "DISPLAY=#{opts["display"]} #{cmd}"
247
267
  else
248
- cmd = "xvfb-run sh -c \"#{cmd} 2> /dev/null\""
249
268
  escape cmd
269
+ cmd = "xvfb-run sh -c \"#{cmd} 2> /dev/null\""
250
270
  end
251
- cmd = "ssh #{host} \"#{cmd}\""
271
+ cmd = "cd #{opts["dir"]} ; " + cmd if opts["dir"]
252
272
 
253
- IO.popen(cmd, "r+") do |io|
254
- begin
255
- require "rubygems"
256
- rescue LoadError
273
+
274
+ begin
275
+ require "rubygems"
276
+ rescue LoadError
277
+ end
278
+ require "gtk2"
279
+ require "base64"
280
+ require "net/ssh"
281
+ include Net::SSH::Prompt
282
+ module Net::SSH::Authentication::Methods
283
+ class Password
284
+ alias :__authenticate :authenticate
285
+ def authenticate(next_service, username, password=nil)
286
+ password ||= prompt("input #{username}'s password:", false)
287
+ __authenticate(next_service, username, password)
288
+ end
257
289
  end
258
- require "gtk2"
259
- require "base64"
260
- io.sync = true
261
- str = ""
262
- Gtk.init
263
- viewer = Viewer.new(io)
264
- t = Thread.new {
265
- Thread.pass
266
- Gtk.main
267
- }
268
- begin
269
- any = false
270
- while (c = io.gets)
271
- any = true
272
- if c == "\n"
273
- png = Base64.decode64(str)
274
- viewer.render(png)
275
- str = ""
276
- else
277
- str << c
290
+ end
291
+
292
+ if opts["user"]
293
+ user = opts["user"]
294
+ elsif /\A([^@]+)@([^@]+)\Z/ =~ host
295
+ user = $1
296
+ host = $2
297
+ else
298
+ user = ENV["USER"]
299
+ end
300
+
301
+
302
+ ssh_opts = Hash.new
303
+ ssh_opts[:password] = opts["password"] if opts["password"]
304
+ Net::SSH.start(host, user, ssh_opts) do |ssh|
305
+ ssh.open_channel do |channel|
306
+ channel.exec(cmd) do |ch, success|
307
+ unless success
308
+ Gtk.main_quit
309
+ abort "could not execute command"
310
+ end
311
+
312
+ channel[:data] = ""
313
+ channel.on_data do |ch, data|
314
+ channel[:data] << data
315
+ while channel[:data] =~ /\n\n/
316
+ str = $`
317
+ channel[:data] = $'
318
+ png = Base64.decode64(str)
319
+ @viewer.render(png)
320
+ end
278
321
  end
322
+ # channel.on_process do |ch|
323
+ # end
324
+ channel.on_extended_data do |ch, type, data|
325
+ print data
326
+ end
327
+ channel.on_eof do |ch|
328
+ @viewer.eof = true
329
+ end
330
+ channel.on_close do |ch|
331
+ @viewer.eof = true
332
+ end
333
+ channel.on_request("exit-status") do |ch, data|
334
+ @viewer.quit! unless data.read_long == 0
335
+ end
336
+
279
337
  end
280
- viewer.eof = true
281
- viewer.quit unless any
338
+
339
+ @viewer = Viewer.new(channel)
340
+ end
341
+
342
+ begin
343
+ t = Thread.new {
344
+ Thread.pass
345
+ Gtk.main
346
+ }
347
+ ssh.loop(1)
282
348
  ensure
283
- io.close
349
+ @viewer.quit
284
350
  end
285
351
  t.join
286
352
  end
@@ -1,3 +1,3 @@
1
1
  module RemoteDCL
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -28,4 +28,7 @@ so could reduce execution time.}
28
28
  # specify any dependencies here; for example:
29
29
  #s.add_development_dependency "rspec"
30
30
  s.add_runtime_dependency "gtk2"
31
+ s.add_runtime_dependency "highline"
32
+ s.add_runtime_dependency "net-ssh"
33
+
31
34
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: remote-dcl
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
4
+ hash: 19
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 2
8
+ - 3
9
9
  - 0
10
- version: 0.2.0
10
+ version: 0.3.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Seiya Nishizawa
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-01-24 00:00:00 Z
18
+ date: 2012-01-25 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: gtk2
@@ -31,6 +31,34 @@ dependencies:
31
31
  version: "0"
32
32
  type: :runtime
33
33
  version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: highline
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ hash: 3
43
+ segments:
44
+ - 0
45
+ version: "0"
46
+ type: :runtime
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: net-ssh
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ hash: 3
57
+ segments:
58
+ - 0
59
+ version: "0"
60
+ type: :runtime
61
+ version_requirements: *id003
34
62
  description: |-
35
63
  Remote-DCL is a Ruby script to execute a script at a remote server.
36
64
  DCL calles in the script creates PNG images at the remote,