remote-dcl 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,