Reparto 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +46 -0
- data/bin/reparto +17 -0
- data/data/Reparto/i18n/en.yml +41 -0
- data/data/Reparto/i18n/es.yml +41 -0
- data/lib/reparto.rb +428 -0
- metadata +100 -0
data/README.rdoc
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
=Reparto
|
2
|
+
Do things on multiple ssh connections
|
3
|
+
|
4
|
+
==Requirements
|
5
|
+
you can install from rubygems or well from your distribution repositories
|
6
|
+
|
7
|
+
* net/ssh
|
8
|
+
* net/sftp
|
9
|
+
* ini
|
10
|
+
* r18n-desktop
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
==You can
|
15
|
+
* Call commands
|
16
|
+
* Copy files
|
17
|
+
* Copy directories
|
18
|
+
* Update directories
|
19
|
+
* Easy file .ini with your actions
|
20
|
+
|
21
|
+
|
22
|
+
create a file myssh.ini:
|
23
|
+
;this a comment to host 192.168.1.33
|
24
|
+
[192.168.1.33]
|
25
|
+
type = ssh
|
26
|
+
username = root
|
27
|
+
password = root
|
28
|
+
port = 22
|
29
|
+
;update fail2ban from this host to remote host 192.168.1.33
|
30
|
+
cmd_1 = service fail2ban stop
|
31
|
+
updatedir_local_2 = /etc/fail2ban
|
32
|
+
updatedir_remote_2 = /etc/fail2ban
|
33
|
+
cmd_3 = service fail2ban start
|
34
|
+
;backups directory
|
35
|
+
cpdir_local_4 = /etc/fail2ban
|
36
|
+
cpdir_remote_4 = /var/backups/fail2ban/20120415
|
37
|
+
;update/copy one file
|
38
|
+
cp_local_5 = /etc/rc.local
|
39
|
+
cp_remote_5 = /etc/rc.local
|
40
|
+
|
41
|
+
;another host actions
|
42
|
+
[....]
|
43
|
+
....
|
44
|
+
|
45
|
+
then from a terminal call script, and look the output:
|
46
|
+
$ ruby reparto.rb myssh.ini
|
data/bin/reparto
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
|
4
|
+
require 'reparto'
|
5
|
+
|
6
|
+
#Muestra ayuda de uso
|
7
|
+
def usage
|
8
|
+
print $t.reparto.usage($0, REPARTO_VERSION)
|
9
|
+
print "\n"
|
10
|
+
exit -1
|
11
|
+
end
|
12
|
+
|
13
|
+
usage() if ARGV.size != 1 or not File.exist? ARGV[0]
|
14
|
+
r = Reparto.new(ARGV[0])
|
15
|
+
$threads.each do |th|
|
16
|
+
th.join
|
17
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
ini:
|
2
|
+
type: type
|
3
|
+
username: username
|
4
|
+
password: password
|
5
|
+
port: port
|
6
|
+
reparto:
|
7
|
+
conecting: Conecting to %1 port %2
|
8
|
+
closing: Closing conection %1
|
9
|
+
type_not_supported: Type %1 not supported
|
10
|
+
require_username: Required username
|
11
|
+
require_password: Required password
|
12
|
+
port_numeric: Port only numeric
|
13
|
+
usage: "
|
14
|
+
Reparto v%2 do things on multiple clients\n
|
15
|
+
%1: <file .ini>\n
|
16
|
+
example, myclients.ini:\n\n
|
17
|
+
[192.168.1.33]\n
|
18
|
+
type = ssh\n
|
19
|
+
username = user\n
|
20
|
+
password = pass\n
|
21
|
+
;execute command\n
|
22
|
+
cmd_1 = hostname\n
|
23
|
+
;execute another command\n
|
24
|
+
cmd_2 = date\n
|
25
|
+
;copy new dir\n
|
26
|
+
cpdir_local_1 = /root/data\n
|
27
|
+
cpdir_remote_1 = /root/data\n
|
28
|
+
;cp file\n
|
29
|
+
cp_local_1 = /etc/rc.local\n
|
30
|
+
cp_remote_1 = /root/backups/rc.local\n
|
31
|
+
;update dir remote\n
|
32
|
+
updatedir_1 = /root/data\n
|
33
|
+
|
34
|
+
;another host\n
|
35
|
+
[.....]\n
|
36
|
+
...\n
|
37
|
+
|
38
|
+
;another host\n
|
39
|
+
[....]\n
|
40
|
+
..
|
41
|
+
"
|
@@ -0,0 +1,41 @@
|
|
1
|
+
ini:
|
2
|
+
type: tipo
|
3
|
+
username: usuario
|
4
|
+
password: clave
|
5
|
+
port: puerto
|
6
|
+
reparto:
|
7
|
+
conecting: Conectando a %1 puerto %2
|
8
|
+
closing: Cerrando conexion de %1
|
9
|
+
type_not_supported: Tipo %1 no soportado
|
10
|
+
require_username: Nombre de usuario requerido
|
11
|
+
require_password: Clave requerida
|
12
|
+
port_numeric: Puerto solo numerico
|
13
|
+
usage: "
|
14
|
+
Reparto v%2 do things on multiple clients\n
|
15
|
+
%1: <file .ini>\n
|
16
|
+
ejemplo, myclients.ini:\n\n
|
17
|
+
[192.168.1.33]\n
|
18
|
+
tipo = ssh\n
|
19
|
+
usuario = user\n
|
20
|
+
clave = pass\n
|
21
|
+
;ejecuta comando \n
|
22
|
+
cmd_1 = hostname\n
|
23
|
+
;ejecuta otro comando\n
|
24
|
+
cmd_2 = date\n
|
25
|
+
;copia un directorio no existente en el equipo remoto\n
|
26
|
+
cpdir_local_1 = /root/data\n
|
27
|
+
cpdir_remote_1 = /root/data\n
|
28
|
+
;copia un archivo\n
|
29
|
+
cp_local_1 = /etc/rc.local\n
|
30
|
+
cp_remote_1 = /root/backups/rc.local\n
|
31
|
+
;actualiza directory remoto con local\n
|
32
|
+
updatedir_1 = /root/data\n
|
33
|
+
|
34
|
+
;otro equipo\n
|
35
|
+
[.....]\n
|
36
|
+
...\n
|
37
|
+
|
38
|
+
;otro equipo\n
|
39
|
+
[....]\n
|
40
|
+
..
|
41
|
+
"
|
data/lib/reparto.rb
ADDED
@@ -0,0 +1,428 @@
|
|
1
|
+
#Reparto 0.0
|
2
|
+
#::Author:: bit4bit <bit4bit@riseup.net>
|
3
|
+
#::Date:: 15 abril 2012
|
4
|
+
#::License:: GPLv3 o Superior
|
5
|
+
|
6
|
+
|
7
|
+
|
8
|
+
require 'find'
|
9
|
+
|
10
|
+
begin
|
11
|
+
require 'inifile'
|
12
|
+
require 'r18n-desktop'
|
13
|
+
require 'logger'
|
14
|
+
require 'net/ssh'
|
15
|
+
require 'net/sftp'
|
16
|
+
|
17
|
+
rescue LoadError
|
18
|
+
require 'rubygems'
|
19
|
+
require 'net/ssh'
|
20
|
+
require 'net/sftp'
|
21
|
+
require 'inifile'
|
22
|
+
require 'r18n-desktop'
|
23
|
+
require 'logger'
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
REPARTO_VERSION = 0.0
|
28
|
+
|
29
|
+
$t = R18n.from_env File.join Gem.datadir('Reparto'), 'i18n/'
|
30
|
+
$logs = Logger.new(STDOUT)
|
31
|
+
$threads = []
|
32
|
+
|
33
|
+
class String
|
34
|
+
def is_number?
|
35
|
+
true if Float(self) rescue false
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class SSHClient
|
40
|
+
def initialize(ip, port, username, password)
|
41
|
+
@ip = ip
|
42
|
+
@port = port
|
43
|
+
@username = username
|
44
|
+
@password = password
|
45
|
+
@actions = []
|
46
|
+
end
|
47
|
+
|
48
|
+
#ejecuta acciones
|
49
|
+
def do
|
50
|
+
$logs.debug($t.reparto.conecting(@ip, @port))
|
51
|
+
|
52
|
+
Net::SSH.start(@ip, @username, :password => @password, :port => @port) do |ssh|
|
53
|
+
@actions.each do |action|
|
54
|
+
name = action[:action]
|
55
|
+
|
56
|
+
|
57
|
+
case name
|
58
|
+
when :cmd
|
59
|
+
cmd = action[:cmd]
|
60
|
+
$logs.debug("%s command execute: %s" % [@ip,cmd])
|
61
|
+
r = ssh.exec! cmd
|
62
|
+
$logs.debug("%s command return: %s" % [@ip,r])
|
63
|
+
when :cp
|
64
|
+
local = action[:local]
|
65
|
+
remote = action[:remote]
|
66
|
+
|
67
|
+
unless File.exist? local
|
68
|
+
$logs.error("%s Not found %s to copy on local machine" % [@ip,local])
|
69
|
+
next
|
70
|
+
end
|
71
|
+
|
72
|
+
begin
|
73
|
+
ssh.sftp.connect do |sftp|
|
74
|
+
|
75
|
+
begin
|
76
|
+
remote = File.join(remote, File.basename(local)) if ssh.sftp.file.directory? remote
|
77
|
+
rescue
|
78
|
+
end
|
79
|
+
|
80
|
+
sftp.upload!(local, remote)
|
81
|
+
$logs.debug("%s cp: %s %s" % [@ip, local, remote])
|
82
|
+
|
83
|
+
end
|
84
|
+
rescue Net::SFTP::StatusException => e
|
85
|
+
$logs.error("%s error[%s] cp: %s %s" % [@ip, e.description, local, remote])
|
86
|
+
end
|
87
|
+
|
88
|
+
#Copia directorio local con remoto solo si no existe
|
89
|
+
when :cpdir
|
90
|
+
local = action[:local]
|
91
|
+
remote = action[:remote]
|
92
|
+
|
93
|
+
unless File.directory? local
|
94
|
+
$logs.error("%s Only dir allow for cpdir not %s" % [@ip, local])
|
95
|
+
end
|
96
|
+
|
97
|
+
begin
|
98
|
+
ssh.sftp.upload!(local, remote)
|
99
|
+
$logs.debug("%s cpdir: %s %s" % [@ip, local, remote])
|
100
|
+
|
101
|
+
rescue Net::SFTP::StatusException => e
|
102
|
+
case e.code
|
103
|
+
when 4
|
104
|
+
$logs.error("%s error[Can't copy directory already exist, use updatedir] cpdir: %s %s" % [@ip, local, remote])
|
105
|
+
else
|
106
|
+
$logs.error("%s error[%s] cpdir: %s %s" % [@ip, e.description, local, remote])
|
107
|
+
end
|
108
|
+
rescue ArgumentError
|
109
|
+
$logs.error("%s error[Need directory to upload] cpdir: %s %s" % [@ip, local, remote])
|
110
|
+
end
|
111
|
+
|
112
|
+
#Actualiza directory local con remoto
|
113
|
+
when :updatedir
|
114
|
+
|
115
|
+
ssh.sftp.connect do |sftp|
|
116
|
+
local_dir = action[:local]
|
117
|
+
remote_dir = action[:remote]
|
118
|
+
|
119
|
+
$logs.debug("Checking for files which need updating %s" % @ip)
|
120
|
+
Find.find(local_dir) do |file|
|
121
|
+
local_file = file
|
122
|
+
remote_file = File.join(remote_dir, local_file.sub(local_dir, ''))
|
123
|
+
|
124
|
+
#actualiza directorio no existene en el remoto
|
125
|
+
if File.directory? file
|
126
|
+
begin
|
127
|
+
ssh.sftp.file.directory? remote_file
|
128
|
+
rescue Net::SFTP::StatusException => e
|
129
|
+
if e.code == 2
|
130
|
+
sftp.upload!(file, remote_file)
|
131
|
+
$logs.debug("%s Updating, new dir %s" % [@ip, remote_file])
|
132
|
+
else
|
133
|
+
$logs.error("%s error[%s] updating new dir %s" % [@ip, e.description, remote_file])
|
134
|
+
end
|
135
|
+
end
|
136
|
+
next
|
137
|
+
end
|
138
|
+
|
139
|
+
#actualiza comparando mtime de stat
|
140
|
+
#o fechas de modificacion
|
141
|
+
begin
|
142
|
+
lstat = File.stat(local_file)
|
143
|
+
rstat = sftp.stat!(remote_file)
|
144
|
+
|
145
|
+
if lstat.mtime > Time.at(rstat.mtime)
|
146
|
+
$logs.debug("%s Updating %s" % [@ip, remote_file])
|
147
|
+
sftp.upload!(local_file, remote_file)
|
148
|
+
sftp.setstat!(remote_file, :permissions => lstat.mode)
|
149
|
+
end
|
150
|
+
rescue Net::SFTP::StatusException => e
|
151
|
+
if e.code == 2
|
152
|
+
sftp.upload!(local_file, remote_file)
|
153
|
+
$logs.debug("%s Updating new file %s" % [@ip, remote_file])
|
154
|
+
else
|
155
|
+
$logs.error("%s error[%s] updating new file %s" % [@ip, e.description, local_file])
|
156
|
+
end
|
157
|
+
rescue Errno::ENOENT
|
158
|
+
$logs.error("%s error[No such directory] updating: %s %s" % [@ip, local_file, remote_file])
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def <<(action)
|
168
|
+
@actions << action
|
169
|
+
end
|
170
|
+
|
171
|
+
#Ejecuta comando en cliente
|
172
|
+
#::cmd:: comando en cliente
|
173
|
+
def cmd(cmd)
|
174
|
+
@actions << {:action => :cmd, :cmd => cmd}
|
175
|
+
end
|
176
|
+
|
177
|
+
#Copia archivo local a remote
|
178
|
+
#::local:: archivo local
|
179
|
+
#::remote:: archivo remote
|
180
|
+
def cp(local, remote)
|
181
|
+
@actions << {:action => :cp, :local =>local, :remote =>remote}
|
182
|
+
end
|
183
|
+
|
184
|
+
#Copia directoria local a remote
|
185
|
+
#::local:: directorio local
|
186
|
+
#::remote:: directorio remote
|
187
|
+
def cp_dir(local, remote)
|
188
|
+
@actions << {:action => :cpdir, :local => local, :remote => remote}
|
189
|
+
end
|
190
|
+
|
191
|
+
#Actualiza directorio remote en caso de cambio
|
192
|
+
#::dir:: directorio local/remote
|
193
|
+
def update_dir(local, remote)
|
194
|
+
@actions << {:action => :updatedir, :local => local, :remote => remote}
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
|
199
|
+
#Clase Reparto
|
200
|
+
#Lee archivo .ini parsea, y crea hilos de ejecucion segun
|
201
|
+
#instrucciones indicadas
|
202
|
+
class Reparto
|
203
|
+
|
204
|
+
#::filename:: archivo .ini
|
205
|
+
def initialize(filename)
|
206
|
+
@fn = filename
|
207
|
+
@ini = IniFile.new(@fn)
|
208
|
+
|
209
|
+
@ssh_clients = {}
|
210
|
+
|
211
|
+
@types_supported = ['ssh']
|
212
|
+
parse
|
213
|
+
end
|
214
|
+
|
215
|
+
#Parse el archivo indicado y crea hilos de ejecucion
|
216
|
+
def parse
|
217
|
+
|
218
|
+
#Por cada seccion o equipo, es un hilo
|
219
|
+
@ini.each_section do |section|
|
220
|
+
|
221
|
+
#@todo validate ip
|
222
|
+
ip = section
|
223
|
+
|
224
|
+
#obtiene tipo
|
225
|
+
if @ini[section].has_key? $t.ini['type']
|
226
|
+
type = @ini[section][$t.ini['type']]
|
227
|
+
unless @types_supported.member? type
|
228
|
+
raise RuntimeError, $t.reparto.type_not_supported(type)
|
229
|
+
end
|
230
|
+
else
|
231
|
+
type = 'ssh'
|
232
|
+
end
|
233
|
+
|
234
|
+
#valida campos requeridos
|
235
|
+
raise RuntimeError, $t.reparto.require_username unless @ini[section].has_key? $t.ini.username
|
236
|
+
raise RuntimeError, $t.reparto.require_password unless @ini[section].has_key? $t.ini.password
|
237
|
+
|
238
|
+
username = @ini[section][$t.ini.username]
|
239
|
+
password = @ini[section][$t.ini.password]
|
240
|
+
|
241
|
+
#se obtiene puerto o por defecto 22
|
242
|
+
if @ini[section].has_key? $t.ini.port
|
243
|
+
port = @ini[section][$t.ini.port]
|
244
|
+
unless port.is_number?
|
245
|
+
raise RuntimeError, $t.reparto.port_numeric
|
246
|
+
end
|
247
|
+
port = port.to_i
|
248
|
+
else
|
249
|
+
case type
|
250
|
+
when 'ssh'
|
251
|
+
port = 22
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
#comandos a ejecutar
|
256
|
+
#en orden , segun paramentro terminado en [0-9]+
|
257
|
+
cmds = []
|
258
|
+
cmd_index = nil
|
259
|
+
|
260
|
+
#se lee parametros y se asignan segun nombre
|
261
|
+
@ini[section].keys.each do |param|
|
262
|
+
cpdirs = nil
|
263
|
+
cpfiles = nil
|
264
|
+
updatedirs = nil
|
265
|
+
|
266
|
+
cmd = param.match(/cmd_([0-9]+)/)
|
267
|
+
if param =~ /cmd/
|
268
|
+
cmd_index = cmd[1].to_i
|
269
|
+
cmds[cmd_index] = ["cmd", @ini[section][param]]
|
270
|
+
end
|
271
|
+
|
272
|
+
#cp directorios
|
273
|
+
cpdir = param.match(/cpdir_local_([0-9]+)/)
|
274
|
+
if cpdir
|
275
|
+
cpdir_num = cpdir[1].to_i
|
276
|
+
cpdir_index = "cpdir_%d" % cpdir_num
|
277
|
+
cmd_index = cpdir_num
|
278
|
+
cpdirs = cmds.assoc(cpdir_index)
|
279
|
+
|
280
|
+
if cpdirs.nil?
|
281
|
+
cpdirs = [cpdir_index, {}]
|
282
|
+
cpdirs[1][:local] = @ini[section][param]
|
283
|
+
cmds[cmd_index] = cpdirs
|
284
|
+
else
|
285
|
+
cmds[cmds.index{|x| x[0] == cpdir_index unless x.nil?}][1][:local] = @ini[section][param]
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
cpdir = param.match(/cpdir_remote_([0-9]+)/)
|
290
|
+
if cpdir
|
291
|
+
cpdir_num = cpdir[1].to_i
|
292
|
+
cpdir_index = "cpdir_%d" % cpdir_num
|
293
|
+
cmd_index = cpdir_num
|
294
|
+
cpdirs = cmds.assoc(cpdir_index)
|
295
|
+
if cpdirs.nil?
|
296
|
+
cpdirs = [cpdir_index, {}]
|
297
|
+
cpdirs[1][:remote] = @ini[section][param]
|
298
|
+
cmds[cmd_index] = cpdirs
|
299
|
+
else
|
300
|
+
cmds[cmds.index{|x| x[0] == cpdir_index unless x.nil?}][1][:remote] = @ini[section][param]
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
|
305
|
+
#cp archivos
|
306
|
+
cpfile = param.match(/cp_local_([0-9]+)/)
|
307
|
+
if cpfile
|
308
|
+
cp_num = cpfile[1].to_i
|
309
|
+
cp_index = "cp_%d" % cp_num
|
310
|
+
cmd_index = cp_num
|
311
|
+
cpfiles = cmds.assoc(cp_index)
|
312
|
+
if cpfiles.nil?
|
313
|
+
cpfiles = [cp_index, {}]
|
314
|
+
cpfiles[1][:local] = @ini[section][param]
|
315
|
+
cmds[cmd_index] = cpfiles
|
316
|
+
else
|
317
|
+
cmds[cmds.index{|x| x[0] == cp_index unless x.nil?}][1][:remote] = @ini[section][param]
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
cpfile = param.match(/cp_remote_([0-9]+)/)
|
322
|
+
if cpfile
|
323
|
+
cp_num = cpfile[1].to_i
|
324
|
+
cp_index = "cp_%d" % cp_num
|
325
|
+
cmd_index = cp_num
|
326
|
+
cpfiles = cmds.assoc(cp_index)
|
327
|
+
if cpfiles.nil?
|
328
|
+
cpfiles = [cp_index, {}]
|
329
|
+
cpfiles[1][:remote] = @ini[section][param]
|
330
|
+
cmds[cmd_index] = cpfiles
|
331
|
+
else
|
332
|
+
cmds[cmds.index{|x| x[0] == cp_index unless x.nil?}][1][:remote] = @ini[section][param]
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
|
337
|
+
#actualiza archivos/directorios en remoto
|
338
|
+
updatedir = param.match(/updatedir_([a-z]+_)?([0-9]+)/)
|
339
|
+
|
340
|
+
if param =~ /^updatedir_([0-9]+)$/
|
341
|
+
i_num = updatedir[2].to_i
|
342
|
+
cmd_index = i_num
|
343
|
+
up_index = "updatedir_%d" % i_num
|
344
|
+
updatedirs = cmds.assoc(up_index)
|
345
|
+
if updatedirs.nil?
|
346
|
+
updatedirs = [up_index, {}]
|
347
|
+
updatedirs[1][:remote] = @ini[section][param]
|
348
|
+
updatedirs[1][:local] = @ini[section][param]
|
349
|
+
cmds[cmd_index] = updatedirs
|
350
|
+
else
|
351
|
+
cmds[cmds.index{|x| x[0] == up_index unless x.nil?}][1][:local] = @ini[section][param]
|
352
|
+
cmds[cmds.index{|x| x[0] == up_index unless x.nil?}][1][:remote] = @ini[section][param]
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
if param =~ /^updatedir_local/
|
357
|
+
i_num = updatedir[2].to_i
|
358
|
+
cmd_index = i_num
|
359
|
+
up_index = "updatedir_%d" % i_num
|
360
|
+
updatedirs = cmds.assoc(up_index)
|
361
|
+
if updatedirs.nil?
|
362
|
+
updatedirs = [up_index, {}]
|
363
|
+
updatedirs[1][:local] = @ini[section][param]
|
364
|
+
cmds[cmd_index] = updatedirs
|
365
|
+
else
|
366
|
+
cmds[cmds.index{|x| x[0] == up_index unless x.nil?}][1][:local] = @ini[section][param]
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
if param =~ /^updatedir_remote/
|
371
|
+
i_num = updatedir[2].to_i
|
372
|
+
cmd_index = i_num
|
373
|
+
up_index = "updatedir_%d" % i_num
|
374
|
+
updatedirs = cmds.assoc(up_index)
|
375
|
+
if updatedirs.nil?
|
376
|
+
updatedirs = [up_index, {}]
|
377
|
+
updatedirs[1][:remote] = @ini[section][param]
|
378
|
+
cmds[cmd_index] = updatedirs
|
379
|
+
else
|
380
|
+
cmds[cmds.index{|x| x[0] == up_index unless x.nil?}][1][:remote] = @ini[section][param]
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
|
385
|
+
end
|
386
|
+
|
387
|
+
case type
|
388
|
+
when 'ssh'
|
389
|
+
cssh = SSHClient.new(ip, port, username, password)
|
390
|
+
cmds.each do |cmd|
|
391
|
+
next if cmd.nil?
|
392
|
+
type = cmd[0]
|
393
|
+
args = cmd[1]
|
394
|
+
|
395
|
+
if type =~ /cmd/
|
396
|
+
cssh.cmd(args)
|
397
|
+
elsif type =~ /cpdir/
|
398
|
+
cssh.cp_dir(args[:local], args[:remote])
|
399
|
+
elsif type =~ /cp/
|
400
|
+
cssh.cp(args[:local], args[:remote])
|
401
|
+
elsif type =~ /updatedir/
|
402
|
+
cssh.update_dir(args[:local], args[:remote])
|
403
|
+
else
|
404
|
+
$logs.error("Unknown action %s\n" % type)
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
408
|
+
#Hilo por cliente
|
409
|
+
$threads << Thread.new(cssh) do |tssh|
|
410
|
+
begin
|
411
|
+
cssh.do
|
412
|
+
rescue Errno::ENETUNREACH
|
413
|
+
$logs.error("Can't connect to %s" % ip)
|
414
|
+
rescue Errno::EHOSTUNREACH
|
415
|
+
$logs.error("Can't route to host %s" % ip)
|
416
|
+
end
|
417
|
+
end
|
418
|
+
|
419
|
+
end
|
420
|
+
|
421
|
+
end
|
422
|
+
|
423
|
+
end
|
424
|
+
|
425
|
+
end
|
426
|
+
|
427
|
+
|
428
|
+
|
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: Reparto
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 1.0.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Bit4bit
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-06-08 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: inifile
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 31
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
- 0
|
32
|
+
- 0
|
33
|
+
version: 0.0.0
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: r18n-desktop
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 31
|
45
|
+
segments:
|
46
|
+
- 0
|
47
|
+
- 0
|
48
|
+
- 0
|
49
|
+
version: 0.0.0
|
50
|
+
type: :runtime
|
51
|
+
version_requirements: *id002
|
52
|
+
description: Exectue commands on multiple computers
|
53
|
+
email: bit4bit@riseup.net
|
54
|
+
executables:
|
55
|
+
- reparto
|
56
|
+
extensions: []
|
57
|
+
|
58
|
+
extra_rdoc_files:
|
59
|
+
- README.rdoc
|
60
|
+
files:
|
61
|
+
- lib/reparto.rb
|
62
|
+
- data/Reparto/i18n/es.yml
|
63
|
+
- data/Reparto/i18n/en.yml
|
64
|
+
- README.rdoc
|
65
|
+
- bin/reparto
|
66
|
+
homepage: https://github.com/bit4bit/reparto
|
67
|
+
licenses: []
|
68
|
+
|
69
|
+
post_install_message:
|
70
|
+
rdoc_options: []
|
71
|
+
|
72
|
+
require_paths:
|
73
|
+
- lib
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
hash: 3
|
80
|
+
segments:
|
81
|
+
- 0
|
82
|
+
version: "0"
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
hash: 3
|
89
|
+
segments:
|
90
|
+
- 0
|
91
|
+
version: "0"
|
92
|
+
requirements: []
|
93
|
+
|
94
|
+
rubyforge_project:
|
95
|
+
rubygems_version: 1.8.24
|
96
|
+
signing_key:
|
97
|
+
specification_version: 3
|
98
|
+
summary: Do thing with multiple ssh connections
|
99
|
+
test_files: []
|
100
|
+
|