Reparto 1.0.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.
- 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
|
+
|