linux_wiki:command_many_systems_part2_send_cmd

This is an old revision of the document!


Command Many Systems Part2: Send Cmd

General Information

Script using techniques from Part 1 to send commands in a variety of ways to a different number of systems.

Checklist


Script Usage

Help screen for send-cmd.sh:

./send-cmd.sh -h

==== Send Command ====
 
Description: Execute a command on the specified system(s).
 
--Usage--
send-cmd.sh [SYSTEM-OPTION] -c 'command to send'
 
SYSTEM OPTIONS
-s system             => Single system name(unquoted).
-s 'system1 system2'  => Multiple systems(quoted).
-s filename           => File with system name(s).
-g system-group       => Spacewalk system group.
-a                    => All Spacewalk registered systems.
 
OTHER OPTIONS
-h                    => Display usage.
-c 'command to send'  => Send the quoted command.
-p                    => Send commands in parallel.(max workers=5)
 
--Other Requirements--
-> Spacecmd and config file setup required.(-g or -a only)
-> Run as a user with system list privileges on the Spacewalk server.(-g or -a only)

The Scripts

Main send-cmd.sh script file.

send-cmd.sh
#!/bin/bash
# Name: send-cmd.sh
# Description: Execute a command(s) on the specified system(s)
# Last Updated: 11/25/2016
# Recent Changes:-Added support for sending to multiple system names as an argument
#                -Added support for sending to system names in a file
#                -Added support for parallel processing
################################################################################
 
##### Customize These Variables #####
# Spacecmd command and any default arguments
spacecmd_cmd="spacecmd -q"
 
# Max number of workers at a time
max_workers=5
 
# Worker script
worker_script="/admin/scripts/worker_send-cmd.sh"
##### End of Customize Variables #####
 
#=====================================
# Functions; Main starts after
#=====================================
function show_usage
{
  echo -e "\n==== Send Command ===="
  echo -e "\nDescription: Execute a command on the specified system(s)."
  echo -e "\n--Usage--"
  echo -e "send-cmd.sh [SYSTEM-OPTION] -c 'command to send'"
  echo -e "\nSYSTEM OPTIONS"
  echo -e "-s system             => Single system name(unquoted)."
  echo -e "-s 'system1 system2'  => Multiple systems(quoted)."
  echo -e "-s filename           => File with system name(s)."
  echo -e "-g system-group       => Spacewalk system group."
  echo -e "-a                    => All Spacewalk registered systems."
  echo -e "\nOTHER OPTIONS"
  echo -e "-h                    => Display usage."
  echo -e "-c 'command to send'  => Send the quoted command."
  echo -e "-p                    => Send commands in parallel.(max workers=${max_workers})"
  echo -e "\n--Other Requirements--"
  echo -e "-> Spacecmd and config file setup required.(-g or -a only)"
  echo -e "-> Run as a user with system list privileges on the Spacewalk server.(-g or -a only)"
  echo -e
}
 
#=======================
# Get Script Arguments
#=======================
# Reset POSIX variable in case it has been used previously in this shell
OPTIND=1
 
## Default settings ##
# Do not send to all systems by default
all_systems="no"
 
# Send commands in serial by default
parallel_cmds="no"
 
## Get command line arguments ##
while getopts "hs:g:ac:p" opt; do
  case "${opt}" in
    h) # -h (help) argument
      show_usage
      exit 0
    ;;
    s) # -s system
      system_name="${OPTARG}"
      # Determine if cmd type is single system(s) argument or filename
      if [[ -f ${system_name} ]]; then
        cmd_type="file"
      else
        cmd_type="single"
      fi
    ;;
    g) # -g system-group
      system_group="${OPTARG}"
      cmd_type="group"
    ;;
    a) # -a (all systems)
      all_systems="yes"
      cmd_type="all"
    ;;
    c) # command to send
      send_cmd="${OPTARG}"
    ;;
    p) # send commands in parallel
      parallel_cmds="yes"
    ;;
    *) # invalid argument
      show_usage
      exit 0
    ;;
  esac
done
 
## Argument Sanity Checks ##
# Scenario: No arguments set
if [[ ${all_systems} == "no" ]]; then
  if [[ -z ${system_name} && -z ${system_group} ]]; then
    echo -e "\n>> ERROR! You must decide on what system(s) will be sent the command."
    show_usage
    exit 1
  fi
fi
 
# Scenario: All systems AND single system(s) argument/filename set
if [[ ${all_systems} == "yes" && ${system_name} ]]; then
  echo -e "\n>> ERROR! Incompatible arguments (all systems and a single system(s) argument/file)."
  show_usage
  exit 1
fi
 
# Scenario: All systems AND system group set
if [[ ${all_systems} == "yes" && ${system_group} ]]; then
  echo -e "\n>> ERROR! Incompatible arguments (all systems and a system group)."
  show_usage
  exit 1
fi
 
# Scenario: Single system(s) argument AND system group set
if [[ ${system_name} && ${system_group} ]]; then
  echo -e "\n>> ERROR! Incompatible arguments (single system(s) argument/file and a system group)."
  show_usage
  exit 1
fi
 
# Scenario: No command set
if [[ -z ${send_cmd} ]]; then
  echo -e "\n>> ERROR! You must enter a command to send."
  show_usage
  exit 1
fi
 
## Command Type: Single or Filename ##
 
#===================
# Pre-checks: Ensure dependencies exist
#===================
 
# Only check for Spacewalk dependencies if NOT sending to a single system(s) argument/file
if [[ -z ${system_name} ]]; then
  # Check for Spacecmd
  which spacecmd &> /dev/null
  if [[ $? -ne 0 ]]; then
    echo "\n>> Error! The command 'spacecmd' is not found or not in PATH. Exiting..."
    exit 1
  fi
 
  # Check to see if a spacecmd config file exists
  if [[ ! -f ${HOME}/.spacecmd/config ]]; then
    echo -e "\n>> Error! No spacecmd config file found at: ${HOME}/.spacecmd/config. Exiting..."
    exit 1
  fi
fi
 
#===================
# Main starts here
#===================
 
echo -e "============================="
echo -e "####=== Send Command ====####"
echo -e "============================="
 
echo -e "NOTE: Commands with spaces and multiple system names must be quoted.\n"
 
if [[ ${system_name} ]]; then
  if [[ ${cmd_type} == "file" ]]; then
    echo -e "Send command to these system(s) from file(${system_name}): \n$(cat ${system_name})"
  else
    echo -e "Send command to system(s): ${system_name}"
  fi
elif [[ ${system_group} ]]; then
  echo -e "Send command to systems in this Spacewalk group: ${system_group}"
else
  echo -e "Send command to ALL systems."
fi
 
if [[ ${parallel_cmds} == "yes" ]]; then
  echo -e "Send Mode: Parallel with workers"
else
  echo -e "Send Mode: Serial"
fi
 
echo -e "Command to send: ${send_cmd}"
echo -e "\n=>Continue?[y/n]:\c"
read run_script
 
if [[ ${run_script} != "y" ]]; then
  echo -e "\n>>Will not run the send command script. Exiting..."
  exit 1
fi
 
# If we are using parallel commands, set the current number of workers
if [[ ${parallel_cmds} == "yes" ]]; then
  current_workers=0
fi
 
case ${cmd_type} in
  single)
  ## Single system(s) argument ##
  echo -e "\n>> Sending command(s) to system(s)..."
 
  if [[ ${parallel_cmds} == "yes" ]]; then
    # Parallel Execution
    for node in $(echo ${system_name}); do
 
      # If the current number of workers equals the max, wait for them to complete, then reset to zero
      if [[ ${current_workers} -ge ${max_workers} ]]; then
        wait
        current_workers=0
      fi
 
      # Start a new worker in the background
      (${worker_script} ${node} "${send_cmd}") &
 
      # Increase the number of current workers
      current_workers=$(( ${current_workers} + 1 ))
    done
    # Wait for all remaining workers to complete
    wait
  else
    # Serial Execution
    for node in $(echo ${system_name}); do
      echo "->${node}"
      ssh -qt -o ConnectTimeout=5 ${node} "${send_cmd}"
    done
  fi
 
  ;;
  file)
  ## File with one or more systems ##
  echo -e "\n>> Sending command(s) to system(s) in file (${system_name})..."
 
  if [[ ${parallel_cmds} == "yes" ]]; then
    # Parallel Execution
    for node in $(cat ${system_name}); do
 
      # If the current number of workers equals the max, wait for them to complete, then reset to zero
      if [[ ${current_workers} -ge ${max_workers} ]]; then
        wait
        current_workers=0
      fi
 
      # Start a new worker in the background
      (${worker_script} ${node} "${send_cmd}") &
 
      # Increase the number of current workers
      current_workers=$(( ${current_workers} + 1 ))
    done
    # Wait for all remaining workers to complete
    wait
  else
    # Serial Execution
    for node in $(cat ${system_name}); do
      echo "->${node}"
      ssh -qt -o ConnectTimeout=5 ${node} "${send_cmd}"
    done
  fi
 
  ;;
  group)
  ## Group of systems (Spacewalk Group) ##
  echo -e "\n>> Sending command(s) to a group of systems (${system_group})..."
 
  # Check to see if the Spacewalk group exists; exit if it does not
  ${spacecmd_cmd} group_list | grep ${system_group} > /dev/null
  if [[ $? -ne 0 ]]; then
    echo -e "-> ERROR! Could not find Spacewalk group: ${system_group}"
    exit 1
  fi
 
  if [[ ${parallel_cmds} == "yes" ]]; then
    # Parallel Execution
    for node in $(${spacecmd_cmd} group_listsystems ${system_group}); do
 
      # If the current number of workers equals the max, wait for them to complete, then reset to zero
      if [[ ${current_workers} -ge ${max_workers} ]]; then
        wait
        current_workers=0
      fi
 
      # Start a new worker in the background
      (${worker_script} ${node} "${send_cmd}") &
 
      # Increase the number of current workers
      current_workers=$(( ${current_workers} + 1 ))
    done
    # Wait for all remaining workers to complete
    wait
  else
    # Serial Execution
    for node in $(${spacecmd_cmd} group_listsystems ${system_group}); do
      echo "->${node}"
      ssh -qt -o ConnectTimeout=5 ${node} "${send_cmd}"
    done
  fi
 
  ;;
  all)
  ## All Systems ##
  echo -e "\n>> Sending command(s) to All systems..."
 
  if [[ ${parallel_cmds} == "yes" ]]; then
    # Parallel Execution
    for node in $(${spacecmd_cmd} system_list); do 
 
      # If the current number of workers equals the max, wait for them to complete, then reset to zero
      if [[ ${current_workers} -ge ${max_workers} ]]; then
        wait
        current_workers=0
      fi
 
      # Start a new worker in the background
      (${worker_script} ${node} "${send_cmd}") &
 
      # Increase the number of current workers by one
      current_workers=$(( ${current_workers} + 1 ))
    done
    # Wait for all remaining workers to complete
    wait
  else
    # Serial Execution
    for node in $(${spacecmd_cmd} system_list); do 
      echo "->${node}"
      ssh -qt -o ConnectTimeout=5 ${node} "${send_cmd}"
    done
  fi
 
  ;;
esac
 
echo -e "\n============================="
echo -e "=- Send Command Completed. -="
echo -e "============================="

Worker script file used for parallel commands only.

worker_send-cmd.sh
#!/bin/bash
# Name: worker_send-cmd.sh
# Description: Worker script for the parent "send-cmd.sh"
# Last Updated: 2016-11-25
# Recent Changes:-File rename
##############################################################
 
if [[ -z ${1} ]]; then
  echo -e "ERROR! This worker script requires arguments and is meant to be executed via its parent script."
  echo -e "For usage see: ./send-cmd.sh -h"
  exit 1
fi
 
# Set system name to the first argument
system_name="${1}"
 
# Shift arguments and set the command to send as the remaining arguments
shift
send_cmd="$@"
 
# Send command to system and capture output
echo "-> Working on ${system_name}..."
output="$(ssh -qt -o ConnectTimeout=5 ${system_name} "${send_cmd}")"
 
# Show formatted output
echo -e ">> Returned output from ${system_name}:\n${output}"

  • linux_wiki/command_many_systems_part2_send_cmd.1480392120.txt.gz
  • Last modified: 2019/05/25 23:50
  • (external edit)