#!/bin/bash
pname=$(basename "$0")
verbose=1

HOSTS=(
    kuiper.lan.informatimago.com
    galatea.lan.informatimago.com
    larissa.lan.informatimago.com
    lassell.lan.informatimago.com
    despina.lan.informatimago.com
    triton.lan.informatimago.com
    galle.lan.informatimago.com
    voyager.informatimago.com
)


function usage(){
    local space="${pname//./ }"
    printf "%s usage:\n" "$pname"
    printf "\n"
    printf "    %s [-s|-h|-v]  command arguments...\n" "$pname"
    printf "    %s [-s|-h|-v]  -f script\n" "$pname"
    printf "\n"
    printf "    %s -s          outputs only the output of command.\n" "$space"
    printf "    %s -h          prefix the output of command by the host name.\n" "$space"
    printf "    %s -v          prefix the output of command by the host name and command.\n" "$space"
    printf "    %s -f script   copies the script to the remote hosts and runs it there.\n" "$space"
    printf "\n"
}

function docmd(){
    if [ $verbose -ge 2 ] ; then
        printf "# %s\n" "$*"
    fi
    "$@"
}

function hostheader(){
    local h="$1"
    case "$verbose" in
    1)
        printf "### %-16s" "${h/\.*/}"
        ;;
    2)
        printf "### %-16s\n" "${h/\.*/}"
        ;;
    esac
}


script=""
command=()
while [ $# -gt 0 ] ; do
    case "$1" in
    -s)
        verbose=0
        shift
        ;;
    -h)
        verbose=1
        shift
        ;;
    -v)
        verbose=2
        shift
        ;;
    -f)
        shift
        script="$1"
        shift
        ;;
    -*)
        usage
        exit 1
        ;;
    *)
        command[${#command[@]}]="$1"
        shift
        ;;
    esac
done

if [ -n "$script" ] ; then
    if [ ${#command[@]} -gt 0 ] ; then
        printf "%s error: cannot give -f script and command arguments at the same time.\n" "$pname"
        usage
        exit 1
    fi
    if [ ! -r "$script" ] ; then
        printf "%s error: cannot read %s.\n" "$pname" "$script"
        usage
        exit 1
    fi
fi


# AHOSTS=
# for h in $HOSTS ; do
#     ping -q -c 1 -w 4 $h >/dev/null 2>&1 \
#         && AHOSTS="$AHOSTS $h"
# done

AHOSTS=(${HOSTS[@]})

quote(){
    for arg ; do
        local slash=${arg//\\/\\\\}
        local quote=\'${slash//\'/\'\\\'\'}\' # no "${...}" here! It would break the \'
        printf "%s " ${quote}
    done
    printf "\n"
}

args=$(quote "${command[@]}")


# printf "script='%s'\n" "$script"
# printf "remtemp='%s'\n" "$remtemp"
# printf "command='%s'\n" "${command[@]}"
# printf "args=%s\n" "$args"
# exit 0

for h in ${AHOSTS[@]} ; do
    hostheader "$h"
    if [ -n "$script" ] ; then
        remtemp="${pname}-${script}-$(hostname)-${h}-$$.sh"
        if [ $verbose -gt 0 ] ; then
            verbose=2
        fi
        docmd scp "$script" "${h}:~/${remtemp}"
        docmd ssh -x "${h}" bash -c "\"( chmod 755 ~/${remtemp} ; ~/${remtemp} > ~/${remtemp}.out 2> ~/${remtemp}.err ; rm ~/${remtemp} )\""
        docmd scp "${h}:~/${remtemp}.out" "${h}:~/${remtemp}.err" /tmp/
        docmd ssh -x "${h}" bash -c "\"( rm ~/${remtemp}.out ~/${remtemp}.err )\""
        docmd cat /tmp/${remtemp}.out /tmp/${remtemp}.err
    else
        docmd ssh -x $h bash -c "$(quote "$args")"
    fi
done

#### END ####
ViewGit