====== Command Many Systems: Part1 Basics ======
**General Information**
Introduction to sending commands in serial and parallel to a large number of systems.
**Checklist**
* Distro(s): Any
* Other: Use of [[linux_wiki:ssh_pub_priv_keys|SSH Public/Private keys]] so nothing prompts for a password in the loop.
----
====== Systems in Serial ======
For some things, it is better to do a rolling serial change...such as restarting a web server.
This example restarts the Apache webserver on a list of systems serially, and sleeps 10 seconds in between each.
1) Populate a text file with the list of systems, one per line. Example:
host_list.txt
webserver01
webserver02
webserver03
...
2) Execute a for loop through that list:
for NODE in $(cat host_list.txt)
do echo -e "\nWorking on ${NODE}..."
ssh admin@${NODE} 'service httpd restart'
echo "---- Done with ${NODE} ----"
sleep 10
done
----
====== Systems in Parallel ======
If you would rather get something done very quickly, commands can be sent in parallel.
1) Create a script that will operate on 1 system.
This script takes 1 argument; a system hostname.
#!/bin/bash
HOST=$1
echo "Executing on ${HOST}..."
ssh admin@${HOST} 'command1;command2;command3'
2) Create a script that will call that script.
This script takes two+ arguments:
* Max Number of forks
* Hostnames (space seperated)
#!/bin/bash
MAX_FORKS=$1
shift
FORKS=0
for HOST in $@; do
if [ ${FORKS} -ge ${MAX_FORKS} ]; then
wait
FORKS=0
fi
(single_host.sh ${HOST}) &
FORKS=$(( ${FORKS} + 1 ))
done
wait
3) Call the parallel_hosts.sh script.
In this example, parallel_hosts.sh will spawn a max of 10 processes at a time:
parallel_hosts.sh 10 $(cat host_list.txt)
===== Parallel Explanation =====
* parallel_hosts.sh is called with two arguments: 10 and an expanded list of host names
* The first argument (10) is assigned to MAX_FORKS
* shift (with no number) moves all arguments down a position, so the 10 drops off, and now $1 is the first host name from the text file.
* The for loop goes through each argument ($@) starting at $1
* If FORKS is ever equal to the MAX_FORKS, wait is used to pause until all child processes have completed.
* Otherwise, call single_host.sh ${HOST}, creating a child process and sending it the current host in the loop to execute on.
* Finally, after the loop is complete, a final wait is used to ensure that any other single_host.sh child processes can finish cleanly.
----