Cover V02, I04
Article

jul93.tar


Distributing Local Information with NIS

R. King Ables

NIS (Network Information Service, formerly known as Yellow Pages) is a mechanism for distributing information to other machines on your local network. Originally developed by Sun Microsystems, it has been included in many popular versions of UNIX. It is normally used to distribute local system information found in files like /etc/passwd, /etc/group, and /etc/hosts (among others). The programs that access these files have been modified to also access the information via NIS when available.

However, any file that contains independent lines of information with a unique key can be distributed via NIS. NIS does not guarantee the order of the data being distributed to a client, so files like /etc/printcap or /etc/sendmail.cf cannot easily be distributed this way. However, a file such as a local phone list is well suited for use with NIS.

Some sites use rdist(1) (see "rdist to the Rescue," Sys Admin, Nov./Dec. 1992) to copy these kinds of files to each host or even copy the files manually. While these methods work, they create a "window of vulnerability" between the time the information is updated and the time all hosts receive an updated copy of the file. If the data is maintained on the NIS master server, all other hosts will have access to the updated information as soon as the NIS maps are updated.

Others sites put such information in directories that are mounted via NFS (or other network distributed filesystems) and simply read the file. This, too, will work, but does not scale well in a large network. The larger a local network, the more redundant copies of such a directory you will need to maintain (since 1,000 users accessing the same files on a server will severely impact the performance). Once you have more than one copy of this file around, you're doing more work than is necessary to make an update. In reality, NIS maintains multiple copies of the information as well, but it is taken care of for you.

One of the most common pieces of local information maintained on-line by organizations is a company phone list. Keeping the phone list up to date is trouble enough -- having to copy it out to all of the other machines on your local network each time it is changed just adds to the complexity. By creating an NIS map containing this information, you can provide it to all hosts on the local network. You can then write a shell script to access the information. Then when the phone list is updated, only the master copy need be edited. When the NIS map is updated, all hosts will have access to the updated information. You will not have to modify any other files on any of the other hosts on your network.

How NIS Works

NIS maintains a directory of files in ndbm(3) format. This is a database file format which provides efficient access to the data. A daemon called ypserv runs on the NIS server and services requests for information (the fact that all NIS daemons start with yp is historical -- NIS was originally called Yellow Pages).

Each NIS client and server is part of an NIS domain (not to be confused with an Internet domain, which is something completely different). The name of the domain is a string set with the domainname(8) command on each system. It is usually set by boot scripts when the system is started.

A daemon called ypbind runs on each NIS client host. This daemon binds itself to an NIS server for the same domain. The client will then query that NIS server whenever a request for information is generated on the client. While it is possible to run more than one NIS domain on a local network, in practice, it is rarely necessary.

NIS also has a secondary level of server called a slave server. Slave servers have copies of the maps from the master server, but the maps cannot be updated anywhere but on the master server. When the maps are updated on the master server, they are pushed (with yppush(8)) to all slave servers. With multiple slave servers available, the clients have more than one host to which they can bind (providing redundancy in case one or more servers fails). Most sites use at least one slave server in case the master server fails. If the master server is unavailable, no NIS maps can be modified, but the slave servers still provide the current information to the clients from their own copies.

As an example, let's say you want to add an entry to the passwd file. After modifying the information in /etc/passwd on the NIS master server (the NIS master passwd file may be called something else if you choose), you would next go to the NIS directory and "do a make." The file called Makefile in the /var/yp directory on the master server rebuilds any NIS maps that have been changed.

% vipw    # BSD command used to edit
# /etc/passwd
% cd /var/yp
% make
updated passwd
<blank line>
<blank line>
pushed passwd
%

The passwd file is run through makedbm(8) (after a few modifications) to create the NIS map files in /var/yp/domainname (whatever that domainname is). Then /var/yp/passwd.time is touched (with touch(1) to update the access time) so that unless the passwd file is updated again, another make command will not rebuild the map. Last, the updated maps are pushed out to the slave server(s). The yppush command prints a blank line each time a map is pushed (and the passwd file is actually in two maps indexed on different keys).

Each of the "normal" maps distributed by NIS has a slightly different format and key, so each section of commands in the Makefile is slightly different. Studying the Makefile is an excellent way of learning how each NIS map is built and which part of the information are used as the key.

Creating a New NIS Map

To distribute files other than regular system files, you must create a new NIS map. The example distributes an on-line phone list and names the NIS map phonelist (pretty original, huh?). Let's say I already have a file of phone numbers that looks like this:

Ables, King		Austin		#3494
Letterman, David New York	#2187
King, Stephen		Bangor		#1313

I can construct an NIS map using the telephone extension as a unique key and using the entire line as the value. The steps to create this map are:

1. Create the data file on the NIS master server. 2. Modify the Makefile to build a map from it. 3. Do a make.

I first create /etc/phonelist on the NIS master server with this file just as it looks now. This will be the master source copy of the phone list.

Next, I modify the Makefile in /var/yp and add the information to build the new map. If you are not familiar with the use of make(1), this part might be a challenge -- I suggest enlisting the help of someone who is experienced in the use of make. The Nutshell book on the make command (listed at the end of this article) is also an excellent source of information.

Near the top of the NIS Makefile is a definition for the target "all" (which is invoked when you type make all or just make). This target has each map name listed as a dependency. The new map name (phonelist) is added to this list so that it will be built along with the other maps.

At the end of the Makefile are the targets for each map name. Each map depends on a time marker file (so that a map is not rebuilt unless its source file has been modified). For example, the passwd map has passwd.time as a dependency. For this new map I would add:

phonelist: phonelist.time

in this section.

In the middle of the Makefile are the commands used to build and push each NIS map. This is where I include the commands necessary to build (or rebuild) the phonelist map:

phonelist.time: /etc/phonelist
@(awk 'BEGIN { FS="#"; } { print $$2, $$0 }' /etc/phonelist \

$(CHKPIPE) ) | $(MAKEDBM) - $(YPDBDIR)/$(DOM)/phonelist

@touch phonelist.time;
@echo "updated phonelist";
@if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOM) phonelist; fi

@if [ ! $(NOPUSH) ]; then echo "pushed phonelist"; fi

The first line causes the phonelist.time target to depend on the existence of /etc/phonelist so that the phonelist map will be rebuilt if the modification time of /etc/phonelist is later than that of phonelist.time in /var/yp (i.e. if /etc/phonelist has been modified since phonelist.time was touched the last time the phonelist map was built).

Each command begins with "@" so that it won't be echoed by the make command. The first line of the command runs the awk(1) program to add the phone extension as a key and pipe the phonelist into the makedbm(8) command and put the resulting ndbm(3) format files in /var/yp/domainname. Depending on the format of your phone list, this command could vary somewhat. In the Sun distribution of /var/yp/Makefile, the MAKEDBM symbol is set to the path of the makedbm command, YPDBDIR is /var/yp, and DOM is set to the domain name. The CHKPIPE symbol is set to a command that lets the Makefile terminate with an error message if the part of the pipe preceding it terminates with an error code. If your NIS Makefile doesn't do this (it isn't critical), just leave that symbol out (do not, however, leave out the second right parenthesis which closes the open parenthesis just before awk).

The next step is to touch phonelist.time to update the modification time and print that it was updated. The last two commands check to see if the maps should be pushed and do so if they should. The NOPUSH symbol is generally set to a null string so that the maps are pushed and the YPPUSH symbol is set to the path of the yppush(8) command.

Now it's time to build the new map.

% cd /var/yp
% make phonelist
updated phonelist
<blank line>
pushed phonelist
%

The new map is propagated to all slave servers and is now available to the clients. On any NIS client in the local domain, a user can type:

% ypcat phonelist

and get an unsorted copy of the entire phone list.

The shell script below, called phone, accesses this information for a user in response to text provided on the command line:

#!/bin/sh
#
# phone - search for text in the on-line phone list
#
if [ "$1" = "" ]; then
echo "usage: $0 text"
exit 1
fi
#
ypcat phonelist | grep -i "$1" | sort
# case insensitive search

This allows the user to ask for and receive information in the following format:

% phone dav
Letterman, David		New York	#2187
% phone king
Ables, King			Austin		#3494
King, Stephen			Bangor		#1313
%

I added the sort command after the search because NIS does not deliver the entries in order. In case the string typed by the user caused more than one entry to be returned, the multiple entries will appear in sorted order. The sort might need to be different if the last name does not appear at the beginning of the line in your phone list. Any text used as an argument to the phone script will be used as the search string. You can type "phone 1313" if you want to find out who has that extension.

In order to modify the phone list now, all that is necessary are the following steps:

% vi /etc/phonelist 	# change the
# Letterman entry
% cd /var/yp
% make
update phonelist
pushed phonelist

then on any host on the network:

% phone dav

will return

Letterman, David		New York	#1138
%

References

The man pages for the commands ypbind, ypserv, yppush, makedbm, ypinit, ypxfer, and domainname will explain these parts of NIS for your local version of UNIX. Your local man page for the make command and the O'Reilly Nutshell book on make will also help you understand the NIS Makefile:

Oram, Andrew, and Steve Talbott. Managing Projects with Make. Sebastopol, CA: O'Reilly & Associates, 1991. ISBN 0-937175-18-8.

About the Author

R. King Ables has been a UNIX user since 1980 and has been managing systems or developing system management and networking tools since 1983. He is currently doing system and network management development for HaL Computer Systems in Austin, TX.