module Rcmd
This module is for parellel remote (SSH) execution of a single command string on Multiple hosts. The module itself consists of one method for execution (Rcmd.run_command) which does not accept any arguments. The required arguments are set as variables through the use of accessors.
Constants
- VERSION
VERSION
- Version number string
Attributes
String containing the command to be used. (Manditory)
Boolean for debug output
An array of hosts to run the given command on. (Manditory)
Prefered/requested number of threads to be used. (Manditory)
Boolean for disabling STDOUT output. SDTERR is always displayed. (Optional)
Array containing the current iterations thread objects.
What user should we connect as. (Manditory)
Public Class Methods
Main method for this module which should be called after the correct variables have been set.
We iterate over the host list until it is empty, creating all needed threads based upon the prefered number of threads for execution. Before creating the threads, the method first checks if the preferred number of threads is greater then the number of hosts remaining in the host list. If false (threads > num hosts) then the number of remaining hosts becomes the thread count. This prevents spawning of unneeded threads.
Manditory values to be set¶ ↑
-
:user
- User to run the command as -
:command
- Command to be executed -
:host_list
- Array containing the hosts for command execution. -
:nthreads
- Preferred max number of threads
Optional Values¶ ↑
-
:quiet
- Do not print to STDOUT. STDERR is always printed
Specifically for the method only¶ ↑
-
:threads
- Array of the current threads
Example¶ ↑
require 'rcmd' Rcmd.host_list= ["host1", "host2", "host3", "host4", "host 5", "host6"] Rcmd.user= 'root' Rcmd.command= 'rpm -qa kernel\*' Rcmd.nthreads= 6 Rcmd.run_command
# File lib/rcmd.rb, line 77 def Rcmd.run_command() if not @command raise ArgumentError.new("No command set for execution") end if not @host_list.count >= 1 raise ArgumentError.new("host_list must contain at least one system") end @host_list.each do |host| @queue << host end until @queue.empty? # Don't start more threads then hosts. num_threads = @nthreads <= @queue.length ? @nthreads : @queue.length # Prepare threads @threads = [ ] num_threads.times do |i| @threads[i] = Thread.new { begin conn_options = { :user => @user, :host => @queue.pop, :password => nil, :quiet => @quiet, :debug => @debug } STDERR.print "DEBUG :: Connecting to #{conn_options[:host]}\n" if conn_options[:debug] Net::SSH.start(conn_options[:host], conn_options[:user], :password => conn_options[:passwd]) do |session| # Open channel for input/output control session.open_channel do |channel| channel.on_data do |ch, data| # Print recieved data if quiet is not true STDOUT.print "#{conn_options[:host]} :: #{data}" unless conn_options[:quiet] end channel.on_extended_data do |ch,type,data| # Always print stderr data STDERR.print "#{conn_options[:host]} :: ERROR :: #{data}" end # Execute command channel.exec @command end # Loop until command completes session.loop end rescue STDERR.print "#{conn_options[:host]} :: CONNECT ERROR :: Unable to connect to host!\n" end } # Execute threads end @threads.each { |t| t.join } end unless @threads.each.map {|t| t.alive?}.none? sleep 1 end end