File distribution via udpcast
Written by Eric Schwimmer
Okay, lets push a bunch of files to remote servers. But let's just do it once to reduce bandwidth contention/consumption. None of this BitTorrent crap. You'll either need a flat network (i.e. a single broadcast domain) or multicast routing set up, and you'll need DSH from the ClusterIt tools package. And udpcast of course :)
#!/bin/bash
fatal() {
echo FATAL: $1
shift
for f in "$@"; do cat $f; done
cleanup
exit 1
}
cleanup() {
exit
[[ -n $DSH_PID ]] && kill -9 $DSH_PID
rm -f $CLIENT_OUT_FILE $SERVER_OUT_FILE $TAR_OUT_FILE
}
usage() {
echo "Usage: sendfile_udpcast <comma-delimited host list> " \
"<comma-delimited local file list> <remote directory>"
exit 1
}
client() {
LOCAL_DIR=$1
BASE_PORT=$2
UDP_RCV=$(which udp-receiver) || UDP_RCV=/sbin/udp-receiver
[[ -e $UDP_RCV ]] || fatal "udp-sender binary missing or not executable."
udp-receiver --portbase $BASE_PORT --nokbd --start-timeout 15 \
--receive-timeout 5 | tar x -C $LOCAL_DIR || echo ERROR
exit 0
}
# Check to see if we are running in client mode
[[ $1 == "client" ]] && client $2 $3
# Make sure that we receive the correct # of arguments
[[ $# == 3 ]] || usage
# Verify our DSH binary
DSH_BIN=$(which dsh) || DSH_BIN=/usr/bin/dsh
[[ -e $DSH_BIN ]] || fatal "DSH binary missing or not executable."
UDP_SND=$(which udp-sender) || UDP_SND=/sbin/udp-sender
[[ -e $UDP_SND ]] || fatal "udp-sender binary missing or not executable."
# Set our globals
HOST_LIST=$1
FILE_LIST=${2//,/ }
REMOTE_DIR=$3
FILE_ROOT=/tmp/$(basename $0).$$
CLIENT_OUT_FILE=${FILE_ROOT}.client
TAR_OUT_FILE=${FILE_ROOT}.tar
SERVER_OUT_FILE=${FILE_ROOT}.server
BASE_PORT=$(( ( RANDOM + RANDOM ) % 64510 + 1024 ))
# Silence STDERR. We'll output error messages as required
exec 2> /dev/null
# Fire off our udp-receivers
echo -n "Starting receivers... "
$DSH_BIN -t -e -w $HOST_LIST -s $0 client $REMOTE_DIR $BASE_PORT &> \
$CLIENT_OUT_FILE && echo COMPLETED >> $CLIENT_OUT_FILE &
DSH_PID=$!
# Sleep to sanity check udp-receiver startup
sleep 2
grep -q ERROR $CLIENT_OUT_FILE || ! kill -0 $DSH_PID && \
fatal "Unable to start udp receivers!" $CLIENT_OUT_FILE
# Now start that sweet, sweet udp-sender
echo -n "starting file copy... "
(tar c $FILE_LIST 2> $TAR_OUT_FILE || echo ERROR >> $TAR_OUT_FILE) | \
$UDP_SND --portbase $BASE_PORT --nokbd --max-wait 1 &> $SERVER_OUT_FILE || \
echo ERROR >> $SERVER_OUT_FILE
grep -q ERROR $TAR_OUT_FILE $SERVER_OUT_FILE && \
fatal "Unable to start udp sender!" $TAR_OUT_FILE $SERVER_OUT_FILE
# Sleep a bit to ensure that things are cleaned up
sleep 1
grep -q ERROR $CLIENT_OUT_FILE || ! grep -q COMPLETED $CLIENT_OUT_FILE ||
kill -0 $DSH_PID && \
fatal "UDP receiver did not finish cleanly!" $CLIENT_OUT_FILE
echo "finished successfully!"
cleanup