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 +4 -4
- data/bin/jssh +25 -105
- data/lib/jssh.rb +71 -2
- data/lib/jssh/printer.rb +45 -0
- data/lib/jssh/string.rb +23 -0
- data/lib/jssh/version.rb +2 -2
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dd8ac63db606331d0c105e6e284e684a31634683
|
4
|
+
data.tar.gz: e4033249bf64dd46edf79457b33397e1a9039b40
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
-
|
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
|
-
|
4
|
-
|
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
|
data/lib/jssh/printer.rb
ADDED
@@ -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
|
+
|
data/lib/jssh/string.rb
ADDED
@@ -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
|
-
|
2
|
-
VERSION = "0.0.
|
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.
|
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-
|
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:
|