Article Figure 1 Listing 1 Listing 2 Listing 3 feb2007.tar

Listing 1 distribute_release

#!/bin/ksh
# Listing 1

#====================================================================
# Name: distribute_release
#
# Description:
#
# distribute_release uses rsync to syncronize files in local
# directory trees with the same directories on remote hosts.
# A distribution network determines which servers may be
# updated (see create_distribution). ssh, rsh, or nfs may be
# used to communicate with remote hosts.
#
# The pathname of a release "module" containing files to
# be replicated is /var/spool/pkg/release/[module]/.
#
# Remote host names corresponding to a particular module are
# stored in the directory:
#
# /var/spool/pkg/release/[transport]/[module]/
#
# where transport may be one of nfs, rsh, or ssh.
#
# Author: John Spurgeon
#====================================================================

# set your own environment
. /etc/setenv_path

# release_dir is the root of a directory tree containing
# files to be distributed to remote hosts.

release_dir=/var/spool/pkg/release/

# $command and $options are used to make recursive calls.
# $command is the name of this program.
# $options is a list of the options to be passed when calling $command.

command=$0
options=""

# Options:
#
# -d dir     Specifies an alternate $release_dir (for internal use).
# -e hosts   Specifies a list of hosts to be excluded from the
#            distribution (-e overrides -i).
# -i hosts   Specifies the hosts to be included in the distribution.
# -r depth   Specifies the recusion depth (an integer).
# -q         Quiet mode.
# -v         Verbose mode.

recursion_depth=0
rsync_options=""
include_hosts=""
exclude_hosts=""
my_echo="echo"

while getopts d:e:i:qr:v OPTION
do
    case $OPTION in
    d) release_dir=$OPTARG ;;
    e)
        exclude_hosts=$OPTARG
        options="-e $OPTARG $options"
        ;;
    i)
        include_hosts=$OPTARG
        options="-h $OPTARG"
        ;;
    q)
        my_echo=": #"
        options="-q $options"
        ;;
    r)
        recursion_depth=$OPTARG ;;
    v)
        rsync_options="$rsync_options -v --stats --progress"
        options="-v $options"
        ;;
    esac
done

# Check for the required argument. $module is the name of a directory
# in $release_dir, the contents of which will be replicated to the
# hosts in the distribution.

shift $(($OPTIND-1))
module=$1

if [[ -z $module ]]
then
    $my_echo "Missing module name."
    exit 1
fi

module_dir="$(basename $module)/"

# If $transport is nfs, then distrib_dir should contain symbolic links
# of the form $distrib_dir/[host] -> /net/[host]/$release_dir.
# Each link in the $distrib_dir points to $release_dir on
# another host. The remote directories are nfs shares.

for transport in nfs rsh ssh
do
    distrib_dir=${release_dir}.${transport}/${module_dir}

    # Identify the candidate hosts.

    candidate_hosts=""

    if [[ -n $include_hosts ]]
    then
        for host in $include_hosts
        do
            if [[ -L ${distrib_dir}$host ]] \
            || [[ -f ${distrib_dir}$host ]]
            then
                candidate_hosts="$host $candidate_hosts"
            fi
        done
    else
        if [[ -d $distrib_dir ]]
        then
            candidate_hosts=$(ls -1 $distrib_dir)
        fi
    fi

    # Use $candidate_hosts to build $distribution.
    # Eliminate hosts in $exclude_hosts in the process.

    distribution=""

    for host in $candidate_hosts
    do
        exclude=FALSE
        for exclude_host in $exclude_hosts
        do
            if [[ $host == $exclude_host ]]
            then
                exclude=TRUE
                break
            fi
        done
        if [[ $exclude == FALSE ]]
        then
            distribution="$host $distribution"
        fi
    done

    # Distribute the module to the hosts in the distribution.

    for host in $distribution
    do
        host_dir="$(basename $host)/"

        $my_echo
        $my_echo "#### START $host ####"

        case $transport in
        nfs)

            # If using nfs, then update /etc/dfs/dfstab with the
            # appropriate share command. For example:
            #
            # share  -F nfs  -o rw=pongo  -d "release dir"  \
            # /var/spool/pkg/release

            if [[ -w ${distrib_dir}${host_dir} ]]
            then
                rsync $rsync_options -t -r --force \
                ${release_dir}${module_dir} \
                ${distrib_dir}${host_dir}${module_dir}
                $my_echo "#### FINISH $host ####"

                # By default, do not recurse. If a recursion depth
                # is specified, recurse $recursion_depth times.

                if (( $recursion_depth > 0 ))
                then
                    # Put the command in a detached screen and continue.
                    eval screen -m -d $command -r $(($recursion_depth-1)) \
                    -d ${distrib_dir}${host_dir} $options $module
                fi

            else
                $my_echo "${distrib_dir}${host_dir} is not writable."
                $my_echo "#### SKIP $host ####"
            fi
            ;;

        rsh|ssh)

            # If using rsh, then update /etc/hosts.equiv or
            # /home/[user]/.rhosts accordingly.
            #
            # If using ssh, then create the appropriate public/private
            # key pairs. Put the private key in /home/[user]/.ssh/
            # on the local system, and put the public key in
            # the file /home/[user]/.ssh/authorized_keys on the remote
            # system.
            #
            # See also: rsh(1), ssh(1), ssh-keygen(1), sshd(1M), etc.

            rsync -e $transport $rsync_options -t -r --force \
            ${release_dir}${module_dir}* \
            $host:${release_dir}${module_dir}
            $my_echo "#### FINISH $host ####"

            if (( $recursion_depth > 0 ))
            then
                # Put the command in a detached screen and continue.
                eval screen -m -d $transport $host $command \
                -r $(($recursion_depth-1)) $options $module
            fi
            ;;
        esac
    done
done
# End distribute_release