Unix Insider –
How often does this happen to you? You add a new Web server to the network, inserting its IP address in /etc/hosts with plenty of time to spare before the Demo For Big People. At T-minus one hour to demo, your browser can't resolve the hostname. Neither can anyone else's.
Frantic, you check everything before finally coming back to /etc/hosts. Your change is gone, probably because someone else edited the file around the same time and overwrote or removed your edits. You either need some strong configuration control, or a truly loud warning bell that signals anyone's attempt to modify a critical file.
Text editors aren't databases -- they don't impose transactional consistency or concurrency control for multiple updates. This doesn't affect you one bit if you're the sole system manager at your site, but as soon as two or more people are chartered to maintain the environment, you need some sort of control system to serialize and document configuration changes. The downside is that you'll spend a non-trivial amount of time deciphering changes made by your peers or un-doing valid work that conflicts with items on your own task list.
This month, we'll look at the source code control system, or SCCS, bundled into nearly every Unix operating system and a staple of simple configuration control.
After explaining the basics of SCCS file administration, we'll look at the more difficult issues of merging changes and dealing with files owned by root. Our goal is to reduce the mystery and annoyance factor of SCCS, and make it a viable tool for producing an electronic version of your "site book" documenting the who, what, and why of system-configuration changes.
SCCS is really a collection of tools that control updates to ASCII files. You can use SCCS with binary data, which will be converted into ASCII form using uuencode, but we'll limit this discussion to ASCII data since that's the source for most configuration files. SCCS lets you put files under configuration control, check out read-only copies, acquire write locks for updates, check in and document changes, print histories, and identify and combine specific updates. Any text file can be put under SCCS's control, making it useful for managing plain text documentation and meeting notes.
Before going into the functional details, here's a bit of terminology:
- History files contain the source for the file under control, as well as a log of all changes made to the file, information about revision numbers, and access controls. History files are prefixed with an "s.", and generally live in a subdirectory called SCCS.
- Deltas are specific changes made to a file. Changing a few characters, adding a line, or removing a line constitute deltas to a file. Deltas are numbered as minor release numbers from the main or major release. A particular version of a file, reflecting the cumulative effect of many deltas, is referred to as an SCCS delta ID, or SID. Most SCCS commands take an SID as an argument when a specific version of the file history is needed.
- Branches are subdivisions of deltas. While deltas are used to track the main changes to a file, branches let you create special-purpose minor variations in a file. Branches may or may not be merged back together at some point; a typical branch file might be created when you update your network configuration to host some demo or loaner machines, and plan to remove those edits in a few days or weeks. Branches are a convenient form of short-term memory.
When you place a file under SCCS control, SCCS creates the history file. To change the file, you check it out for editing, and then each subsequent change to the file is annotated in the history file when you check the modified version back in. SCCS locks the history file while one user is editing it to prevent concurrent updates.
Bones of contention
Let's walk through some basic SCCS operations to see how the components fit together, and then get into the grittier problems that make SCCS more of a benefit than an added burden. First, you'll need to have /usr/ccs/bin in your path, since that's where the SCCS commands live (in SunOS, they're part of /usr/bin).
You can call the individual SCCS commands, or use the sccs front-end tool to simplify life. We'll use the front-end for illustrative purposes, but you can also call the SCCS subcommands directly. Make sure you have an obvious place to store history files, such as a subdirectory called SCCS. SCCS commands look for this subdirectory if you don't give an explicit history file location.
Take a vanilla ASCII file and put it under SCCS control, using the admin command:
<font face="Courier">huey% sccs admin -ihosts hosts </font>
This creates an SCCS history file called hosts initialized with the content of the file named hosts. You want the history file and the actual file to be namesakes unless you're particularly good at associating strange path names with your /etc files. You can choose any file you want for the initialization; if you've just sorted your hosts file into /tmp/hosts.sorted, the above command line might be:
<font face="Courier">huey% sccs admin -i/tmp/hosts.sorted hosts </font>
If all goes well, sccs admin returns quietly to the shell prompt. The most common complaint is that the initial file doesn't contain any ID keywords, which are magic strings filled in by SCCS with the file name, delta numbers, and date and time stamps. We'll talk about the keywords and how to maximize your enjoyment of them shortly. Successful submission of a file to SCCS creates a new s-file in the SCCS directory. The file is primarily ASCII text, with SCCS records marked with an ASCII SOH (start of header) character, showing up as control-A in most editors. All revisions, delta histories and access control information goes into the s-file.
When you're ready to use the file, check out a read-only copy:
<font face="Courier">huey% sccs get hosts 1.2 10 lines </font>
SCCS tells us the current SID of the file and its size. The
<font face="Courier">get</font>operation produces a read-only file in the current directory, and it will complain if there's a writeable version of the file already present. After you initialize a history file, be sure to rename or remove the initial file to prevent problems on your first check-out operation.
Edit the file by checking out a writeable version, using
<font face="Courier">sccs get -e</font>or the shorthand
<font face="Courier">sccs edit</font>:
<font face="Courier">huey% sccs edit hosts 1.2 new delta 1.3 10 lines </font>
This time, we're told the new delta number to be created by our editing session. If someone else is editing the file at the time, SCCS produces an error:
<font face="Courier">huey% sccs edit hosts 1.2 ERROR [SCCS/s.hosts]: being edited: `1.2 1.3 stern 95/06/16 17:41:22' (ge17) </font>
Our first contention point is removed: any request to edit a file that is already being consumed by another system administrator is met with a cryptic yet gentle slap on the keyboard. If you want to find out who is currently editing SCCS-controlled files, use the
<font face="Courier">huey% sccs info hosts: being edited: 1.2 1.3 stern 95/06/16 17:41:22 aliases: being edited: 1.45 1.46 wendyt 95/06/17 14:50:33 </font>
Make your changes a part of the file's permanent record using
<font face="Courier">sccs delta</font>:
<font face="Courier">huey% sccs delta hosts comments? added two new host entries 1.3 2 inserted 0 deleted 10 unchanged </font>
Your writeable source file is removed when you file the deltas, so you have to do another
<font face="Courier">sccs get</font>to fetch the latest, read-only copy, or merge the
<font face="Courier">get</font>operations together with
<font face="Courier">sccs delget hosts</font>.
At this point, you can feed the read-only file into whatever system management step comes next: running an NIS
<font face="Courier">make</font>, executing
<font face="Courier">newaliases</font>, or restarting a daemon with its new configuration file.
Letters of intent
How can you determine the version number of a file, or if it's even SCCS controlled? When you check a file out, the
<font face="Courier">get</font>subcommand fills in SCCS keywords with values such as the SID, pathname of the history file, date, and time. The SCCS magic cookie indicating a keyword is a single, capital letter between percent signs, such as %Z%. Put the SCCS keywords in a comment header in your file, and you have a built-in identification scheme. Here's a sample header for a configuration file that uses the pound sign (#) as a comment character:
<font face="Courier"># %M% %I% %H% %T% </font>
This set of keywords gives you the filename (M), the file revision or SID (I), the current date (H), and the time of checkout (T). You may also choose to insert the pathname to the s-file (P). The %W% keyword generates the filename and SID prefixed with the string @(#), which is assumed to be unique to the SCCS system. The
<font face="Courier">what</font>utility searches for the SCCS prefix and prints any information after it, allowing you to quickly identify any number of files.
To include other information to be picked up by
<font face="Courier">what</font>, use the %Z% keyword to insert an SCCS cookie and then build your own identification string. A more verbose version of the example above is easily found by
<font face="Courier"># %Z% common hosts file revision %I% of %H% at %T% </font>
<font face="Courier">what</font>is smart enough to look in the string tables of executables and libraries, so it will identify the SCCS versions of each object component. Bundle an SCCS string into a C program with a global definition like this:
<font face="Courier">char *sccs_id = "%Z% %I% %H% %T%"; </font>
While peeking at the SID and file origins is useful for quick sanity checks, reviewing the delta history of a file is more likely to tell you who changed something and why. When you create the delta, SCCS asks for a comment which is then recorded with your login in the history file. Dump the delta history using
<font face="Courier">sccs prs</font>:
<font face="Courier">huey% sccs prs hosts SCCS/s.hosts: D 1.2 95/06/16 16:49:32 stern 2 1 00002/00002/00008 COMMENTS: added alias for wind, new host shower D 1.1 95/06/16 16:43:30 stern 1 0 00010/00000/00000 COMMENTS: date and time created 95/06/16 16:43:30 by stern </font>
The line introducing each delta shows you the SID, date and time of change, and the login of the person making the change. The slash-separated numbers are the line counts of new, deleted and unchanged lines. The manual pages for the
<font face="Courier">prs</font>subcommand also list all of the possible SCCS keywords and their expanded values.
We still haven't tackled two of the hardest problems in change management: how do you get multiple users to access SCCS files, particularly when the files are owned by root, and how do you merge changes together? The first problem doesn't have an easy solution. You can keep all of your SCCS history files in /etc/SCCS, and insist that system administrators include their user names when making changes as root. Since this is fairly unlikely, the next step is to make the SCCS history files group-writeable by members of your system management group (creating a new user group if you need to). Create private SCCS work areas for each system manager using symbolic links to the actual history file location:
<font face="Courier">huey% mkdir ~stern/etc huey% ln -s /etc/SCCS ~stern/etc/SCCS huey% cd ~stern/SCCS huey% sccs edit hosts </font>
Within ~stern/SCCS, an
<font face="Courier">sccs edit hosts</font>picks up the s-file /etc/SCCS/s.hosts, giving me a private copy of the hosts file to work on.
When I check it back in, the single host-specific copy is returned where other managers (and the system) can find it, but it has my user name attached to changes instead of root. To publicize the changes, I need to su to root, cd into /etc, and then do an
<font face="Courier">sccs get hosts</font>to fetch my latest changes and install the file. Note that the symbolic link points to a machine-specific location, which means I have to be logged on to the machine on which I want to make the edits before doing the checkout. I can always move SCCS files around, as long as files get installed on the appropriate machines.
If you're worried about giving up some measure of security regarding permissions on /etc/hosts, remember that only root can install the file in /etc and rebuild NIS maps or restart daemons. For an added layer of safety, using the SCCS access control feature, explicitly name allowed users with
<font face="Courier">sccs admin -a</font>:
<font face="Courier">huey% sccs admin -astern huey% sccs admin -awendyt </font>