jssh 0.0.2 → 0.0.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 802cfe834425216c50891414dec0f5a71b4c6498
4
- data.tar.gz: bca4531307cf24e4c6b654cd7c0a791b0acf8672
3
+ metadata.gz: dd8ac63db606331d0c105e6e284e684a31634683
4
+ data.tar.gz: e4033249bf64dd46edf79457b33397e1a9039b40
5
5
  SHA512:
6
- metadata.gz: 4e7e49858f77e2d1d164d257a1197be768bbab91090a4650dbe811663c9b9d8b0bb944f6f16b268654b77f913bd399dd19b6bfc27b5b56a9d472fd226a82413c
7
- data.tar.gz: dadbd6e0b570a80dd86568bbd5faccd83a30258a57a086333e5cb57358de33864b4938a418cbd8f8aee22c9df1e4503991bc8306529706ae44328527db03d648
6
+ metadata.gz: 593a5f5473b552ea2e9e350abbbf4a6b84570fa9f6de8cd540ced58c5718a76218078cfd574b03bac1758645f992e5ecab2569cfbba476ea597c19acb211d042
7
+ data.tar.gz: bff5756a0b8b6431585bd63a95bc9c9788f7d6193ed254a2b513c23de80597ade2882e3a5adb8de7168035b1d07cf651e32f3f3475a60868e1fb1e4dcf9b27f2
data/bin/jssh CHANGED
@@ -2,42 +2,10 @@
2
2
  require 'net/ssh'
3
3
  require 'optparse'
4
4
  require 'yaml'
5
-
6
- class String
7
- def to_black
8
- "\033[30m#{self}\033[0m"
9
- end
10
- def to_red
11
- "\033[31m#{self}\033[0m"
12
- end
13
- def to_yellow
14
- "\033[33m#{self}\033[0m"
15
- end
16
- def to_blue
17
- "\033[34m#{self}\033[0m"
18
- end
19
- def to_white
20
- "\033[37m#{self}\033[0m"
21
- end
22
- def to_green
23
- "\033[32m#{self}\033[0m"
24
- end
25
- def to_cyan
26
- "\033[36m#{self}\033[0m"
27
- end
28
- def to_magenta
29
- "\033[35m#{self}\033[0m"
30
- end
31
- def to_bold
32
- "\033[1m#{self}\033[0m"
33
- end
34
- def to_underline
35
- "\033[4m#{self}\033[0m"
36
- end
37
- end
5
+ require "jssh"
38
6
 
39
7
  options = {}
40
- OptionParser.new do |opts|
8
+ op=OptionParser.new do |opts|
41
9
  opts.banner = "Usage: jssh [options]"
42
10
  opts.on("-f file","--hostfile file", "host file, every host occupy a line") do |v|
43
11
  options[:hostfile] = v
@@ -61,6 +29,9 @@ OptionParser.new do |opts|
61
29
  opts.on("-b","--break", "pause after first operation") do |v|
62
30
  options[:pause] = v
63
31
  end
32
+ opts.on("-g gsize","--groupsize gsize",OptionParser::OctalInteger, "The size of parallel group, default is 10") do |v|
33
+ options[:gsize] = v
34
+ end
64
35
  opts.on("-c cmdfile","--cmdfile cmdfile", "script path") do |v|
65
36
  options[:cmdfile] = v
66
37
  unless File.exists? v
@@ -68,6 +39,9 @@ OptionParser.new do |opts|
68
39
  exit
69
40
  end
70
41
  end
42
+ opts.on("-o outputfile","--output outputfile", "output file") do |v|
43
+ options[:output] = v
44
+ end
71
45
  opts.on("--help", "help") do |v|
72
46
  puts opts
73
47
  exit
@@ -75,7 +49,12 @@ OptionParser.new do |opts|
75
49
  opts.on("--debug", "debug inputs") do |v|
76
50
  options[:debug]=v
77
51
  end
78
- end.parse!
52
+ end
53
+ begin op.parse!
54
+ rescue => e
55
+ puts e.to_s.to_red
56
+ exit
57
+ end
79
58
 
80
59
  # If neither the rsa file or password specified, go get rsa file in home directory
81
60
  unless options[:key] || options[:password]
@@ -100,75 +79,9 @@ if options[:debug]
100
79
  exit
101
80
  end
102
81
 
103
- lambda{puts "No command or command file specify";exit}.call unless options[:cmdfile] || options[:command]
104
- lambda{puts "Please specify the user";exit}.call unless options[:user]
105
- lambda{puts "Please specify the rsa file or password";exit}.call unless options[:key] || options[:password]
106
-
107
- class Jssh
108
- attr_accessor :hosts,:user, :auth_cfg, :cmd, :printer
109
-
110
- def initialize
111
- @auth_cfg={}
112
- self.printer=:on
113
- @queue=Queue.new
114
- end
115
- def messages
116
- @queue
117
- end
118
-
119
- def go(from=0,len=nil)
120
- len||=self.hosts.size
121
- to=from+len-1
122
- password=self.auth_cfg[:password]
123
- keys=[self.auth_cfg[:key]].reject{|x| x.nil?}
124
- self.hosts[from..to].each_with_index do |host,i|
125
- result=""
126
- begin
127
- Net::SSH.start(host,self.user,:keys=>keys,:password=>password) do |ssh|
128
- result=ssh.exec!(self.cmd)
129
- end
130
- rescue=>e
131
- result=e.to_s
132
- end
133
- yield host,result if block_given?
134
- end
135
- end
136
- def execute(from=0,len=nil,group_size=10)
137
- pr=start_printer(self)
138
- threads=[]
139
- len||=self.hosts.size
140
- to=from+len-1
141
- divider(self.hosts[from..to].size,group_size) do |df,dt|
142
- threads<<Thread.new(self,from+df,from+dt) do |rssh,f,t|
143
- rssh.go(f,t) do |h,r|
144
- output=("="*20+h+"="*20).to_yellow+"\n"+r
145
- rssh.messages.push output
146
- end
147
- end
148
- end
149
- threads.each{|t| t.join}
150
- loop{ break if self.messages.size==0 } if self.printer
151
- Thread.kill pr
152
- end
153
-
154
- private
155
- def start_printer(jssh)
156
- Thread.new(jssh) do |rssh|
157
- while true
158
- puts rssh.messages.pop if rssh.printer
159
- end
160
- end
161
- end
162
- def divider(total,gsize)
163
- gcnt=total/gsize
164
- gcnt=gcnt+1 if total%gsize!=0
165
- gcnt.times do |i|
166
- from,len=i*gsize,gsize
167
- len=total%gsize if i==gcnt-1
168
- yield from,len
169
- end
170
- end
171
- end
82
+ lambda{puts "No command or command file specify".to_red;exit}.call unless options[:cmdfile] || options[:command]
83
+ lambda{puts "Please specify the user".to_red;exit}.call unless options[:user]
84
+ lambda{puts "Please specify the rsa file or password".to_red;exit}.call unless options[:key] || options[:password]
172
85
 
173
86
  rs=Jssh.new
174
87
  if options[:hostfile]
@@ -176,6 +89,9 @@ if options[:hostfile]
176
89
  else
177
90
  orig_hosts=options[:hostlist].split(",")
178
91
  end
92
+
93
+ rs.printer=Printer.new(FileExecutor.new(options[:output])) if options[:output]
94
+
179
95
  rs.user=options[:user]
180
96
  rs.auth_cfg[:password]=options[:password]
181
97
  rs.auth_cfg[:key]=options[:key]
@@ -190,6 +106,7 @@ unless options[:pause]
190
106
  puts "Finished!".to_green
191
107
  exit
192
108
  end
109
+
193
110
  rs.hosts=orig_hosts.take 1
194
111
  rs.execute
195
112
  puts "Now the operations on the first host is completed, we're going to it for a check.".to_yellow
@@ -212,7 +129,10 @@ print "Continue to finish all the left operations by parallel(p) or serial(s), [
212
129
  ans=$stdin.gets.chomp
213
130
  rs.hosts=orig_hosts[1..-1]
214
131
  if ans.downcase=='p'
215
- rs.execute
132
+ options[:gsize]= rs.hosts.size/100 if options[:gsize].nil? || rs.hosts.size/options[:gsize]>100 || options[:gsize]<1
133
+ gs=options[:gsize]==0 ? 1 : options[:gsize]
134
+ rs.printer.instant=false
135
+ rs.execute 0,nil,gs
216
136
  else
217
137
  rs.execute 0,nil,rs.hosts.size
218
138
  end
data/lib/jssh.rb CHANGED
@@ -1,5 +1,74 @@
1
1
  require "jssh/version"
2
+ require "jssh/printer"
3
+ require 'jssh/string'
2
4
 
3
- module Jssh
4
- # Your code goes here...
5
+ class Jssh
6
+ attr_accessor :hosts,:user, :auth_cfg, :cmd, :printer
7
+
8
+ def initialize
9
+ @auth_cfg={}
10
+ self.printer=Printer.new(StdoutExecutor.new)
11
+ @queue=Queue.new
12
+ end
13
+ def messages
14
+ @queue
15
+ end
16
+
17
+ def go(from=0,len=nil)
18
+ len||=self.hosts.size
19
+ to=from+len-1
20
+ password=self.auth_cfg[:password]
21
+ keys=[self.auth_cfg[:key]].reject{|x| x.nil?}
22
+ self.hosts[from..to].each_with_index do |host,i|
23
+ begin
24
+ Net::SSH.start(host,self.user,:keys=>keys,:password=>password) do |ssh|
25
+ result=ssh.exec!(self.cmd) || ''
26
+ ssh.exec!(self.cmd) do |ch,stream,data|
27
+ data||=''
28
+ yield host,data,false if block_given?
29
+ end
30
+ end
31
+ rescue=>e
32
+ result=e.to_s
33
+ end
34
+ result||=''
35
+ yield host,result,true if block_given?
36
+ end
37
+ end
38
+ def execute(from=0,len=nil,group_size=1)
39
+ pr=start_printer(self)
40
+ threads=[]
41
+ len||=self.hosts.size
42
+ to=from+len-1
43
+ divider(self.hosts[from..to].size,group_size) do |df,dt|
44
+ threads<<Thread.new(self,from+df,from+dt) do |rssh,f,t|
45
+ rssh.go(f,t) do |h,r,over|
46
+ rssh.messages.push({'host'=>h,'content'=>r,'finished'=>over})
47
+ end
48
+ end
49
+ end
50
+ threads.each{|t| t.join}
51
+ loop{ break if self.printer.finished? }
52
+ Thread.kill pr
53
+ end
54
+
55
+ private
56
+ def start_printer(jssh)
57
+ jssh.printer.submit_jobs(jssh.hosts)
58
+ Thread.new(jssh) do |rssh|
59
+ while true
60
+ data=rssh.messages.pop
61
+ rssh.printer.print data['host'],data['content'],data['finished']
62
+ end
63
+ end
64
+ end
65
+ def divider(total,gsize)
66
+ gcnt=total/gsize
67
+ gcnt=gcnt+1 if total%gsize!=0
68
+ gcnt.times do |i|
69
+ from,len=i*gsize,gsize
70
+ len=total%gsize if i==gcnt-1 && total%gsize!=0
71
+ yield from,len
72
+ end
73
+ end
5
74
  end
@@ -0,0 +1,45 @@
1
+ class Printer
2
+ attr_accessor :instant
3
+ def initialize(executor)
4
+ self.instant=true
5
+ @executor=executor
6
+ end
7
+ def submit_jobs(hosts)
8
+ @memo={}
9
+ hosts.each{|j| @memo[j]=nil }
10
+ end
11
+ def print(host,content,is_end)
12
+ if self.instant
13
+ lambda{ @executor.puts ("="*20+host+"="*20).to_yellow; @memo[host]='' }.call unless @memo[host]
14
+ @executor.puts content if content
15
+ @memo.delete host if is_end
16
+ else
17
+ @memo[host]=("="*20+host+"="*20).to_yellow+"\n" unless @memo[host]
18
+ @memo[host] << content if content
19
+ lambda{ @executor.puts @memo[host]; @memo.delete host }.call if is_end
20
+ end
21
+ end
22
+ def finished?
23
+ @memo.empty?
24
+ end
25
+ end
26
+
27
+ class StdoutExecutor
28
+ def puts(str)
29
+ $stdout.puts str
30
+ end
31
+ end
32
+ class FileExecutor
33
+ def initialize(filename)
34
+ @file=File.open(filename,'a')
35
+ end
36
+ def puts(str)
37
+ @file.puts str
38
+ end
39
+ end
40
+ class NullExecutor
41
+ def puts(str)
42
+ #Do nothing
43
+ end
44
+ end
45
+
@@ -0,0 +1,23 @@
1
+ class String
2
+ def to_black
3
+ "\033[30m#{self}\033[0m"
4
+ end
5
+ def to_red
6
+ "\033[31m#{self}\033[0m"
7
+ end
8
+ def to_yellow
9
+ "\033[33m#{self}\033[0m"
10
+ end
11
+ def to_blue
12
+ "\033[34m#{self}\033[0m"
13
+ end
14
+ def to_white
15
+ "\033[37m#{self}\033[0m"
16
+ end
17
+ def to_green
18
+ "\033[32m#{self}\033[0m"
19
+ end
20
+ def to_cyan
21
+ "\033[36m#{self}\033[0m"
22
+ end
23
+ end
data/lib/jssh/version.rb CHANGED
@@ -1,3 +1,3 @@
1
- module Jssh
2
- VERSION = "0.0.2"
1
+ class Jssh
2
+ VERSION = "0.0.3"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jssh
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - qjpcpu
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-03 00:00:00.000000000 Z
11
+ date: 2014-04-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -68,6 +68,8 @@ files:
68
68
  - bin/jssh
69
69
  - jssh.gemspec
70
70
  - lib/jssh.rb
71
+ - lib/jssh/printer.rb
72
+ - lib/jssh/string.rb
71
73
  - lib/jssh/version.rb
72
74
  homepage: https://github.com/qjpcpu/jssh
73
75
  licenses: