Skip to content

Instantly share code, notes, and snippets.

@davidlares
Created January 4, 2020 02:24
Show Gist options
  • Save davidlares/d23038fa2c248ec72f31455525f9fc81 to your computer and use it in GitHub Desktop.
Save davidlares/d23038fa2c248ec72f31455525f9fc81 to your computer and use it in GitHub Desktop.
Remote SSH command execution with Vagrant machines
#!/bin/bash
# file with a list of serverr
SERVER_LIST='/vagrant/servers'
# ssh options
SSH_OPTIONS='-o ConnectTimeout=2'
usage() {
echo "Usage: ${0} [-nsv] [-f FILE] COMMAND"
echo "Executes COMMAND as a single command on every server"
echo "-f FILE Use FILE for the list of servers. Default ${SERVER_LIST}"
echo "-n Dry run mode, Display the COMMAND that would have been executed and exit"
echo "-s Execute the COMMAND using sudo on the remote server"
echo "-v Verbose mode, Display the server name before executing COMMAND"
exit 1
}
if [[ "${UID}" -eq 0 ]]
then
echo "Do not execute this cript as root, Use the -s option instead"
usage
fi
# parsing the options
while getopts f:nsv OPTION
do
case ${OPTION} in
f) SERVER_LIST="${OPTARG}" ;;
n) DRY_RUN='true' ;;
s) SUDO='sudo' ;;
v) VERBOSE='true' ;;
esac
done
# remove the options while leaving the remaining args
shift "$(( OPTIND -1 ))"
# check params inserted
if [[ "${#}" -lt 1 ]]
then
usage
fi
# anything that remains is to be threated as a single command
COMMAND="${@}"
# check if the file exists
if [[ ! -e "${SERVER_LIST}" ]]
then
echo "Cannot open ${SERVER_LIST}"
exit 1
fi
EXIT_STATUS='0'
# loop the SERVER_LIST
for SERVER in $(cat ${SERVER_LIST})
do
# checking VERBOSE args set
if [[ "${VERBOSE}" == 'true' ]]
then
echo "${SERVER}"
fi
# performing the ssh command here
SSH_COMMAND="ssh ${SSH_OPTIONS} ${SERVER} ${SUDO} ${COMMAND}"
# Is a dry-run?
if [[ "${DRY_RUN}" = 'true' ]]
then
echo "DRY RUN: ${SSH_COMMAND}"
else
# running command
${SSH_COMMAND}
SSH_EXIT_STATUS="${?}"
# check execution succeded
if [[ "${SSH_EXIT_STATUS}" -ne 0 ]]
then
EXIT_STATUS="${SSH_EXIT_STATUS}"
echo "Execution on ${SERVER} failed"
fi
fi
done
exit ${EXIT_STATUS}
admin02
admin03
Vagrant.configure("2") do |config|
config.vm.box = "jasonc/centos7"
# first machine
config.vm.define "admin01" do |admin01|
admin01.vm.hostname = 'admin01'
admin01.vm.network "private_network", ip: "10.9.8.10"
end
# second machine
config.vm.define "admin02" do |admin02|
admin02.vm.hostname = 'admin02'
admin02.vm.network "private_network", ip: "10.9.8.11"
end
# third machine
config.vm.define "admin03" do |admin03|
admin03.vm.hostname = 'admin03'
admin03.vm.network "private_network", ip: "10.9.8.12"
end
end
@davidlares
Copy link
Author

There's some additional configuration you will have to do in order to make this script work well.

  1. You will need to place the private network IPs file and the hostname inside the /etc/hosts
  2. Make sure that every single machine can be reachable by using the ping command
  3. Generate an ssh key with the ssh-keygen command, and then copy the public key to each VM with ssh-copy-id
  4. Access a machine with ssh [admin01], find the /vagrant directory and run the remote.sh
  5. Check the usage function for instructions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment