Skip to content

Instantly share code, notes, and snippets.

@ddwang
Last active March 14, 2017 18:53
Show Gist options
  • Save ddwang/a453b5277feec45ac1322f451d1648b2 to your computer and use it in GitHub Desktop.
Save ddwang/a453b5277feec45ac1322f451d1648b2 to your computer and use it in GitHub Desktop.
bash script to sync/merge a local `hosts` file with the one on remote machine
#!/bin/bash
# title : sync_host.sh
# description : sync/merge a local `hosts` file with one on a remote server
# author : Daniel Wang // @ddwang // ZING
# usage : bash sync_host.sh <host_file> <user@remote_addr> <ssh_key_file>
# notes : the remote user (user@remote_addr) must have `sudo` privilege
#
# Copyright (c) 2017 ZING
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
if [ "$3" = "" ]
then
echo "Usage: $0 <host_file> <user@remote_addr> <ssh_key_file>"
exit
fi
HOSTS_FILE="$1"
REMOTE_CREDENTIALS="$2"
SSH_KEY_FILE="$3"
function func_max_host_entry_len() {
local __RET=$1
while read -r line || [[ -n "$line" ]]; do
read -a array <<< "$line"
local __IP="${array[0]}"
local __HOST="${array[1]}"
local __LEN=$((${#__IP} + ${#__HOST} + 4))
eval $__RET=$(( $2 > $__LEN ? $2 : $__LEN ))
done < "$HOSTS_FILE"
}
function func_pretty_host_entry() {
local __RET=$1
local __FORTY_SPACES=" "
local __GAP_LEN=$(($2 - ${#3} - ${#4}))
eval $__RET="\"$3${__FORTY_SPACES:0:$__GAP_LEN}$4\""
}
# calculate the max len of a host entry
func_max_host_entry_len MAX_HOST_ENTRY_LEN 0 "$HOSTS_FILE"
# re-read the host file into an array
IFS=$'\n' read -d '' -r -a lines < "$HOSTS_FILE"
for line in "${lines[@]}"
do
read -a array <<< "$line"
IP="${array[0]}"
if [ "$IP" = "" ]
then
echo "invalid line in $HOSTS_FILE: '$line'"
exit -1
fi
HOST="${array[1]}"
if [ "$HOST" = "" ]
then
echo "invalid line in $HOSTS_FILE: '$line'"
exit -1
fi
func_pretty_host_entry HOST_ENTRY $MAX_HOST_ENTRY_LEN $IP $HOST
ssh -i $SSH_KEY_FILE $REMOTE_CREDENTIALS "grep -q '$HOST' /etc/hosts && exit 42"
rc=$?; if [ $rc -eq 42 ]; then
echo "[INFO] host entry for [$HOST] already exist, patching ..."
ssh -i $SSH_KEY_FILE $REMOTE_CREDENTIALS "sudo sed -i 's/^.*$HOST\$/$HOST_ENTRY/' /etc/hosts || exit -1"
rc=$?; if [ $rc -ne 0 ]; then
echo "[ERROR] patching /etc/hosts failed $rc"
exit $rc
fi
else
echo "[INFO] appending host entry for [$HOST] ..."
ssh -i $SSH_KEY_FILE $REMOTE_CREDENTIALS "echo '$HOST_ENTRY' | sudo tee -a /etc/hosts || exit -1"
rc=$?; if [ $rc -ne 0 ]; then
echo "[ERROR] appending to /etc/hosts failed $rc"
exit $rc
fi
fi
done
echo "[INFO] done."
echo
echo "~~~ /etc/hosts ~~~"
echo
ssh -i $SSH_KEY_FILE $REMOTE_CREDENTIALS "cat /etc/hosts"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment