rcmd 1.5.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/.bundle/config +1 -0
  3. data/.gitignore +1 -0
  4. data/.rspec_status +9 -0
  5. data/.ruby-gemset +1 -0
  6. data/.ruby-version +1 -0
  7. data/Gemfile +4 -0
  8. data/Gemfile.lock +55 -0
  9. data/README.md +84 -0
  10. data/Rakefile +37 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +8 -0
  13. data/doc/rdocs/OptionParser.html +124 -0
  14. data/doc/rdocs/README_md.html +212 -0
  15. data/doc/rdocs/Rcmd.html +362 -0
  16. data/doc/rdocs/created.rid +5 -0
  17. data/doc/rdocs/images/add.png +0 -0
  18. data/doc/rdocs/images/arrow_up.png +0 -0
  19. data/doc/rdocs/images/brick.png +0 -0
  20. data/doc/rdocs/images/brick_link.png +0 -0
  21. data/doc/rdocs/images/bug.png +0 -0
  22. data/doc/rdocs/images/bullet_black.png +0 -0
  23. data/doc/rdocs/images/bullet_toggle_minus.png +0 -0
  24. data/doc/rdocs/images/bullet_toggle_plus.png +0 -0
  25. data/doc/rdocs/images/date.png +0 -0
  26. data/doc/rdocs/images/delete.png +0 -0
  27. data/doc/rdocs/images/find.png +0 -0
  28. data/doc/rdocs/images/loadingAnimation.gif +0 -0
  29. data/doc/rdocs/images/macFFBgHack.png +0 -0
  30. data/doc/rdocs/images/package.png +0 -0
  31. data/doc/rdocs/images/page_green.png +0 -0
  32. data/doc/rdocs/images/page_white_text.png +0 -0
  33. data/doc/rdocs/images/page_white_width.png +0 -0
  34. data/doc/rdocs/images/plugin.png +0 -0
  35. data/doc/rdocs/images/ruby.png +0 -0
  36. data/doc/rdocs/images/tag_blue.png +0 -0
  37. data/doc/rdocs/images/tag_green.png +0 -0
  38. data/doc/rdocs/images/transparent.png +0 -0
  39. data/doc/rdocs/images/wrench.png +0 -0
  40. data/doc/rdocs/images/wrench_orange.png +0 -0
  41. data/doc/rdocs/images/zoom.png +0 -0
  42. data/doc/rdocs/index.html +191 -0
  43. data/doc/rdocs/js/darkfish.js +155 -0
  44. data/doc/rdocs/js/jquery.js +4 -0
  45. data/doc/rdocs/js/navigation.js +142 -0
  46. data/doc/rdocs/js/search.js +94 -0
  47. data/doc/rdocs/js/search_index.js +1 -0
  48. data/doc/rdocs/js/searcher.js +228 -0
  49. data/doc/rdocs/rdoc.css +595 -0
  50. data/doc/rdocs/table_of_contents.html +71 -0
  51. data/exe/rcmd +73 -0
  52. data/lib/rcmd.rb +123 -0
  53. data/lib/rcmd/version.rb +4 -0
  54. data/rcmd.gemspec +46 -0
  55. metadata +204 -0
@@ -0,0 +1,71 @@
1
+ <!DOCTYPE html>
2
+
3
+ <html>
4
+ <head>
5
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
6
+
7
+ <title>Table of Contents - RDoc Documentation</title>
8
+
9
+ <link type="text/css" media="screen" href="./rdoc.css" rel="stylesheet">
10
+
11
+ <script type="text/javascript">
12
+ var rdoc_rel_prefix = "./";
13
+ </script>
14
+
15
+ <script type="text/javascript" charset="utf-8" src="./js/jquery.js"></script>
16
+ <script type="text/javascript" charset="utf-8" src="./js/navigation.js"></script>
17
+ <script type="text/javascript" charset="utf-8" src="./js/search_index.js"></script>
18
+ <script type="text/javascript" charset="utf-8" src="./js/search.js"></script>
19
+ <script type="text/javascript" charset="utf-8" src="./js/searcher.js"></script>
20
+ <script type="text/javascript" charset="utf-8" src="./js/darkfish.js"></script>
21
+
22
+
23
+ <body class="indexpage">
24
+ <h1>Table of Contents - RDoc Documentation</h1>
25
+
26
+ <h2>Pages</h2>
27
+ <ul>
28
+ <li class="file">
29
+ <a href="README_md.html">README</a>
30
+
31
+ <img class="toc-toggle" src="images/transparent.png" alt="" title="toggle headings">
32
+ <ul class="initially-hidden">
33
+ <li><a href="README_md.html#label-Description">Description</a>
34
+ <li><a href="README_md.html#label-Features">Features</a>
35
+ <li><a href="README_md.html#label-Installation">Installation</a>
36
+ <li><a href="README_md.html#label-Usage+Examples">Usage Examples</a>
37
+ <li><a href="README_md.html#label-Help+Screen">Help Screen</a>
38
+ <li><a href="README_md.html#label-Specifying+nodes+manually">Specifying nodes manually</a>
39
+ <li><a href="README_md.html#label-Piping+list+of+nodes">Piping list of nodes</a>
40
+ <li><a href="README_md.html#label-Using+a+database+for+obtaining+nodes">Using a database for obtaining nodes</a>
41
+ <li><a href="README_md.html#label-Development">Development</a>
42
+ </ul>
43
+ </li>
44
+
45
+ </ul>
46
+
47
+ <h2 id="classes">Classes/Modules</h2>
48
+ <ul>
49
+ <li class="module">
50
+ <a href="OptionParser.html">OptionParser</a>
51
+ </li>
52
+ <li class="module">
53
+ <a href="Rcmd.html">Rcmd</a>
54
+ </li>
55
+
56
+ </ul>
57
+
58
+ <h2 id="methods">Methods</h2>
59
+ <ul>
60
+
61
+ <li class="method"><a href="Rcmd.html#method-c-run_command">::run_command &mdash; Rcmd</a>
62
+
63
+ </ul>
64
+
65
+
66
+ <footer id="validator-badges">
67
+ <p><a href="http://validator.w3.org/check/referer">[Validate]</a>
68
+ <p>Generated by <a href="https://github.com/rdoc/rdoc">RDoc</a> 4.0.0.
69
+ <p>Generated with the <a href="http://deveiate.org/projects/Darkfish-Rdoc/">Darkfish Rdoc Generator</a> 3.
70
+ </footer>
71
+
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'rcmd'
5
+
6
+ # This program is for executing a command on multiple nodes at the same time and accepts the following arguments.
7
+ #
8
+ # * -u, --username | Username for the connections
9
+ # * -n, --nodes | comma seperated list of nodes. '-' to use piped list
10
+ # * -t, --threads | Number of threads to run
11
+ # * -c, --command | Command to be executed
12
+ # * -q, --quiet | Boolean flag for suppressing stdout of executed commands
13
+ # * -v, --version | Print version string and exit
14
+
15
+
16
+ # Set default options
17
+ options = { :threads => 4, :nodes => nil, :environment => nil, :host_file => nil, :user => 'root', :password => false, :command => nil, :quiet => false, :version => false }
18
+
19
+ host_list = []
20
+
21
+ # Setup options
22
+ opts = OptionParser.new #:nodoc:
23
+
24
+ opts.on('-u username', '--username username', String, "Username for SSH connections") { |v| options[:user] = v }
25
+ opts.on('-n nodes', '--nodes x,y,z', Array, "Comma seperated list of nodes. use '-' for a space seperated list piped from another command") { |v| options[:nodes] = v }
26
+ opts.on('-r regex', '--regexp regex', String, "Use Regex to build/search host list") { |v| options[:expression] = v}
27
+ opts.on('-d database', '--database database', String, "Database connection string") { |v| options[:database] = v}
28
+ opts.on('-t threads', '--threads threads', Integer, "Number of threads to run") { |v| options[:threads] = v }
29
+ opts.on('-c <command>', '--command <command>', String, "Quoted string containing the command to be run") { |v| options[:command] = v }
30
+ opts.on('-q', '--quiet', "Suppress stdout of commands. stderr will still be displayed") { |v| options[:quiet] = v }
31
+ opts.on('-v', '--version', "Print what version of the command is in use") { |v| options[:version] = v}
32
+
33
+ # Process options
34
+ begin
35
+ opts.parse!(ARGV)
36
+ unless options[:version]
37
+ mandatory = [:command, :nodes]
38
+ missing = mandatory.select{ |param| options[param].nil? }
39
+ raise OptionParser::MissingArgument, missing.join(', ') unless missing.empty?
40
+ end
41
+ rescue OptionParser::ParseError => e
42
+ $stderr.puts e
43
+ $stderr.puts opts
44
+ exit
45
+ end
46
+
47
+ # Print version and exit if version option chosen
48
+ if options[:version]
49
+ $stdout.puts "Version: #{Rcmd::VERSION}"
50
+ exit
51
+ end
52
+
53
+ # Populate the host list
54
+ if options[:nodes][0] == '-'
55
+ ARGF.read.split().each do |h|
56
+ host_list << h
57
+ end
58
+ else
59
+ host_list = options[:nodes]
60
+ end
61
+
62
+ # abort if host_list is empty
63
+ abort("No hosts to run command on") if host_list.nil?
64
+
65
+ # Set needed variables
66
+ Rcmd.host_list= host_list
67
+ Rcmd.nthreads= options[:threads]
68
+ Rcmd.user= options[:user]
69
+ Rcmd.quiet= options[:quiet]
70
+ Rcmd.command= options[:command]
71
+
72
+ # Execute command on provided hosts
73
+ Rcmd.run_command
@@ -0,0 +1,123 @@
1
+ require "rcmd/version"
2
+ require 'net/ssh'
3
+ require 'thread'
4
+
5
+ =begin rdoc
6
+
7
+ This module is for parellel remote (SSH) execution of a
8
+ single command string on Multiple hosts. The module itself consists of
9
+ one method for execution (Rcmd.run_command) which does not accept any
10
+ arguments. The required arguments are set as variables through the
11
+ use of accessors.
12
+ =end
13
+
14
+ module Rcmd
15
+ STDOUT.sync = true
16
+ STDERR.sync = true
17
+ @queue = Queue.new
18
+
19
+ # Self class for setting up accessors
20
+ class << self
21
+
22
+ # Prefered/requested number of threads to be used. (Manditory)
23
+ attr_accessor :nthreads
24
+
25
+ # What user should we connect as. (Manditory)
26
+ attr_accessor :user
27
+
28
+ # An array of hosts to run the given command on. (Manditory)
29
+ attr_accessor :host_list
30
+
31
+ # String containing the command to be used. (Manditory)
32
+ attr_accessor :command
33
+
34
+ # Boolean for disabling STDOUT output. SDTERR is always displayed. (Optional)
35
+ attr_accessor :quiet
36
+
37
+ # Array containing the current iterations thread objects.
38
+ attr_accessor :threads
39
+ end
40
+
41
+ # Main method for this module which should be called after the correct variables have been set.
42
+ #
43
+ # We iterate over the host list until it is empty, creating all
44
+ # needed threads based upon the prefered number of threads for
45
+ # execution. Before creating the threads, the method first checks
46
+ # if the preferred number of threads is greater then the number of
47
+ # hosts remaining in the host list. If false (threads > num hosts)
48
+ # then the number of remaining hosts becomes the thread count. This
49
+ # prevents spawning of unneeded threads.
50
+ #
51
+ # ==== Manditory values to be set
52
+ #
53
+ # * +:user+ - User to run the command as
54
+ # * +:command+ - Command to be executed
55
+ # * +:host_list+ - Array containing the hosts for command execution.
56
+ # * +:nthreads+ - Preferred max number of threads
57
+ #
58
+ # ==== Optional Values
59
+ #
60
+ # * +:quiet+ - Do not print to STDOUT. STDERR is always printed
61
+ #
62
+ # ==== Specifically for the method only
63
+ #
64
+ # * +:threads+ - Array of the current threads
65
+ #
66
+ # ==== Example
67
+ #
68
+ # require 'rcmd'
69
+ # Rcmd.host_list= ["host1", "host2", "host3", "host4", "host 5", "host6"]
70
+ # Rcmd.user= 'root'
71
+ # Rcmd.command= 'rpm -qa kernel\*'
72
+ # Rcmd.nthreads= 6
73
+ # Rcmd.run_command
74
+ def Rcmd.run_command()
75
+ if not @command
76
+ raise ArgumentError.new("No command set for execution")
77
+ end
78
+ if not @host_list.count >= 1
79
+ raise ArgumentError.new("host_list must contain at least one system")
80
+ end
81
+ @host_list.each do |host|
82
+ @queue << host
83
+ end
84
+ until @queue.empty?
85
+ # Don't start more threads then hosts.
86
+ num_threads = @nthreads <= @queue.length ? @nthreads : @queue.length
87
+ # Prepare threads
88
+ @threads = [ ]
89
+ num_threads.times do |i|
90
+ @threads[i] = Thread.new {
91
+ begin
92
+ conn_options = { :user => @user, :host => @queue.pop, :password => nil, :quiet => @quiet}
93
+ Net::SSH.start(conn_options[:host], conn_options[:user], :password => conn_options[:passwd]) do |session|
94
+ # Open channel for input/output control
95
+ session.open_channel do |channel|
96
+ channel.on_data do |ch, data|
97
+ # Print recieved data if quiet is not true
98
+ STDOUT.print "#{conn_options[:host]} :: #{data}" unless conn_options[:quiet]
99
+ end
100
+ channel.on_extended_data do |ch,type,data|
101
+ # Always print stderr data
102
+ STDERR.print "#{conn_options[:host]} :: ERROR :: #{data}"
103
+ end
104
+ # Execute command
105
+ channel.exec @command
106
+ end
107
+ # Loop until command completes
108
+ session.loop
109
+ end
110
+ rescue
111
+ STDERR.print "#{conn_options[:host]} :: CONNECT ERROR :: Unable to connect to host!\n"
112
+ end
113
+ }
114
+ # Execute threads
115
+ end
116
+ @threads.each { |t| t.join }
117
+ end
118
+ unless @threads.each.map {|t| t.alive?}.none?
119
+ sleep 1
120
+ end
121
+ end
122
+ end
123
+
@@ -0,0 +1,4 @@
1
+ module Rcmd #:notnew:
2
+ # +VERSION+ - Version number string
3
+ VERSION = "1.5.6"
4
+ end
@@ -0,0 +1,46 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "rcmd/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "rcmd"
8
+ spec.version = Rcmd::VERSION
9
+ spec.authors = ["David Rose"]
10
+ spec.email = ["david.rose@starnix.se"]
11
+
12
+ spec.summary = "Parellel command execution through ssh"
13
+ spec.description = "This gem provides a command to execute a command on multiple systems in parallel through ssh"
14
+ spec.homepage =
15
+ 'http://www.gitlab.com/daibhidh/rcmd'
16
+ spec.license = 'GPL2'
17
+
18
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
19
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
20
+ if spec.respond_to?(:metadata)
21
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
22
+ else
23
+ raise "RubyGems 2.0 or newer is required to protect against " \
24
+ "public gem pushes."
25
+ end
26
+
27
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
28
+ f.match(%r{^(test|spec|features)/})
29
+ end
30
+ spec.bindir = "exe"
31
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
32
+ spec.require_paths = ["lib"]
33
+
34
+ spec.add_runtime_dependency('net-ssh')
35
+ spec.add_runtime_dependency('io-console')
36
+ spec.add_runtime_dependency('thread')
37
+ spec.add_runtime_dependency('tty-prompt')
38
+
39
+ spec.add_development_dependency('rspec', '~> 3.0', '>= 2.0.0')
40
+ # spec.add_development_dependency('activerecord', '~>4.0.0')
41
+ # spec.add_development_dependency('sqlite3')
42
+ # spec.add_development_dependency('nokogiri', '~>1.6.0')
43
+ # spec.add_development_dependency('rails', '~>4.0.0')
44
+ spec.add_development_dependency "bundler", "~> 1.15"
45
+ spec.add_development_dependency "rake", "~> 10.0"
46
+ end
metadata ADDED
@@ -0,0 +1,204 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rcmd
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.5.6
5
+ platform: ruby
6
+ authors:
7
+ - David Rose
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-06-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: net-ssh
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: io-console
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: thread
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: tty-prompt
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ - - '>='
77
+ - !ruby/object:Gem::Version
78
+ version: 2.0.0
79
+ type: :development
80
+ prerelease: false
81
+ version_requirements: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: '3.0'
86
+ - - '>='
87
+ - !ruby/object:Gem::Version
88
+ version: 2.0.0
89
+ - !ruby/object:Gem::Dependency
90
+ name: bundler
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ~>
94
+ - !ruby/object:Gem::Version
95
+ version: '1.15'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ~>
101
+ - !ruby/object:Gem::Version
102
+ version: '1.15'
103
+ - !ruby/object:Gem::Dependency
104
+ name: rake
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: '10.0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ~>
115
+ - !ruby/object:Gem::Version
116
+ version: '10.0'
117
+ description: This gem provides a command to execute a command on multiple systems
118
+ in parallel through ssh
119
+ email:
120
+ - david.rose@starnix.se
121
+ executables:
122
+ - rcmd
123
+ extensions: []
124
+ extra_rdoc_files: []
125
+ files:
126
+ - .bundle/config
127
+ - .gitignore
128
+ - .rspec_status
129
+ - .ruby-gemset
130
+ - .ruby-version
131
+ - Gemfile
132
+ - Gemfile.lock
133
+ - README.md
134
+ - Rakefile
135
+ - bin/console
136
+ - bin/setup
137
+ - doc/rdocs/OptionParser.html
138
+ - doc/rdocs/README_md.html
139
+ - doc/rdocs/Rcmd.html
140
+ - doc/rdocs/created.rid
141
+ - doc/rdocs/images/add.png
142
+ - doc/rdocs/images/arrow_up.png
143
+ - doc/rdocs/images/brick.png
144
+ - doc/rdocs/images/brick_link.png
145
+ - doc/rdocs/images/bug.png
146
+ - doc/rdocs/images/bullet_black.png
147
+ - doc/rdocs/images/bullet_toggle_minus.png
148
+ - doc/rdocs/images/bullet_toggle_plus.png
149
+ - doc/rdocs/images/date.png
150
+ - doc/rdocs/images/delete.png
151
+ - doc/rdocs/images/find.png
152
+ - doc/rdocs/images/loadingAnimation.gif
153
+ - doc/rdocs/images/macFFBgHack.png
154
+ - doc/rdocs/images/package.png
155
+ - doc/rdocs/images/page_green.png
156
+ - doc/rdocs/images/page_white_text.png
157
+ - doc/rdocs/images/page_white_width.png
158
+ - doc/rdocs/images/plugin.png
159
+ - doc/rdocs/images/ruby.png
160
+ - doc/rdocs/images/tag_blue.png
161
+ - doc/rdocs/images/tag_green.png
162
+ - doc/rdocs/images/transparent.png
163
+ - doc/rdocs/images/wrench.png
164
+ - doc/rdocs/images/wrench_orange.png
165
+ - doc/rdocs/images/zoom.png
166
+ - doc/rdocs/index.html
167
+ - doc/rdocs/js/darkfish.js
168
+ - doc/rdocs/js/jquery.js
169
+ - doc/rdocs/js/navigation.js
170
+ - doc/rdocs/js/search.js
171
+ - doc/rdocs/js/search_index.js
172
+ - doc/rdocs/js/searcher.js
173
+ - doc/rdocs/rdoc.css
174
+ - doc/rdocs/table_of_contents.html
175
+ - exe/rcmd
176
+ - lib/rcmd.rb
177
+ - lib/rcmd/version.rb
178
+ - rcmd.gemspec
179
+ homepage: http://www.gitlab.com/daibhidh/rcmd
180
+ licenses:
181
+ - GPL2
182
+ metadata:
183
+ allowed_push_host: https://rubygems.org
184
+ post_install_message:
185
+ rdoc_options: []
186
+ require_paths:
187
+ - lib
188
+ required_ruby_version: !ruby/object:Gem::Requirement
189
+ requirements:
190
+ - - '>='
191
+ - !ruby/object:Gem::Version
192
+ version: '0'
193
+ required_rubygems_version: !ruby/object:Gem::Requirement
194
+ requirements:
195
+ - - '>='
196
+ - !ruby/object:Gem::Version
197
+ version: '0'
198
+ requirements: []
199
+ rubyforge_project:
200
+ rubygems_version: 2.6.10
201
+ signing_key:
202
+ specification_version: 4
203
+ summary: Parellel command execution through ssh
204
+ test_files: []