rcmd 1.5.6

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.
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: []