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

Distributing Software Modules Using rsync

Ed Schaefer and John Spurgeon

Distributing software packages to all of our servers is a tedious task. Currently, a release manager makes a connection to each server and transfers files using ftp. This involves entering passwords multiple times, waiting for transfers to complete, changing directories, and keeping files organized. We developed a shell script, distribute_release (Listing 1), that makes the job easier.

Our script has some advantages over the ftp process:

  • Directory trees can be used to organize release modules.
  • A distribution network defines how files are transferred from server to server.
  • When a release module is ready to be distributed, it is replicated to all of the servers in the network using rsync, which helps minimize network traffic.
  • Various authentication methods can be used to avoid entering passwords for each server.

We’ll describe the directory structures including creating the distribution network. Then we’ll talk about the scripts. Finally, we’ll discuss an example.

Directory Structures

Each release module is stored in the directory /var/spool/pkg/release/[module]/. A module directory can be flat, or it can contain subdirectories. Hidden directory trees under the ./release/ directory define the distribution network. Therefore, the names of these directories cannot be used as module names.

Transport protocols supported by distribute_release include nfs, rsh, and ssh. If a release module is distributed using nfs, then the directory /var/spool/pkg/release/.nfs/[module]/ contains symbolic links corresponding to the hosts in the server’s distribution network:

/var/spool/pkg/release/.nfs/[module]/[host] -> \
 /net/[host]/var/spool/pkg/release/
When using nfs, rsync functions like an improved copy command, transferring files between the directories /var/spool/pkg/release/[module]/ and /var/spool/pkg/release/.nfs/[module]/[host]/[module].

When using rsh or ssh, the directory structures are similar. With rsh, for example, empty files of the form /var/spool/pkg/release/.rsh/[module]/[host] define the hosts in the distribution network.

The Scripts

Before distribute_release can be called, the directory structures and the distribution network must be created. The script create_distribution (Listing 2) facilitates these tasks.

One argument, the name of a release module, must be passed to create_distribution. When no options are used, the local host functions as a terminal node in the distribution network. In other words, the system may receive updates from another host, but it will not propagate those updates to downstream hosts. Downstream hosts and transport protocols may be specified with the -h and -t options respectively.

When using distribute_release, the name of a release module must be passed to the script. The -q and -v options may be used to control the amount of information displayed to the user. Hosts to be included or excluded from the distribution may be specified using the -i and -e options. The -r option may be used to determine how many times the program will recursively call itself to distribute the module to successive levels in a distribution hierarchy. When using nfs, the recursive calls are made locally. With rsh and ssh, the program calls itself on a remote server.

Distribute_release first gets the argument and any command-line options. Then, for each transport protocol, the script builds a distribution list and executes the appropriate rsync command for each host in the list. If a recursion depth is specified, then another instance of distribute_release is executed in a detached screen session, allowing the parent instance to continue running while the child processes propagate the module to other hosts.

An Example

Our example network (see Figure 1) contains five servers -- bambi, pongo, pluto, nemo, and goofy. One of the release modules is named TS1 (located on bambi) and the module is named TS2 (located on pluto). By executing the create_distributions script (Listing 3) on each server, the complete distribution network for both modules is built using the proper create_distribution calls.

Consider the TS1 release module; after the module has been distributed to all of the systems in the network, the directory /var/spool/pkg/release/TS1/ contains the following files and subdirectories:

 ./README
./v1/TS1-v1.pkg
./v2/TS1-v2.pkg
./beta/TS1-v3.pkg
On bambi, the directory /var/spool/pkg/release/.ssh/TS1/ contains a file named pongo. So, executing "distribute_release TS1” on bambi synchronizes the TS1 module with pongo using ssh as the transport protocol. The TS1 module can be distributed from pongo to all servers in the network using the -r option:

distribute_release -r 2 TS1
When using ssh, passwords can be avoided by using public/private key pairs with empty passphrases. When using rsh, you can update /etc/hosts.equiv or the appropriate .rhosts file. Obviously, passwords are not an issue with nfs. Deciding which protocol to use depends on security concerns, potential performance issues, and configuration complexity.

John Spurgeon is a software developer and systems administrator for Intel’s Factory Information Control Systems, IFICS, in Hillsboro, Oregon. He is currently preparing to ride a single-speed bicycle in Race Across America in 2007.

Ed Schaefer is a frequent contributor to Sys Admin. He is a software developer and DBA for Intel’s Factory Information Control Systems, IFICS, in Hillsboro, Oregon. Ed also hosts the monthly Shell Corner column on UnixReview.com. He can be reached at: shellcorner@comcast.net.