BSD Hacks

Hack 79 Safely Merge Changes to /etc

Use a three-way merge to deal with upgraded configuration files.

Even though you probably run cvsup on a daily basis, you likely run make world only a few times a year, whenever a new version of the OS is released. The steps required to upgrade your system are well documented and fairly straightforward. That is, it's easy until it's time to run mergemaster.

mergemaster is an important step, as it integrates changes to /etc. For example, occasionally a core utility such as Sendmail will require a new user or group in /etc/passwd. Problems can occur if those changes aren't integrated.

If you've used mergemaster before, you know it's not the most user-friendly utility out there. Misinterpret a diff, and you might lose your configuration file changes or, worse, miss a necessary change. You might even end up blowing away your own users in /etc/passwd not the most convenient way to start off a new upgrade.

8.4.1 Initial Preparations

An alternative is to use etcmerge (/usr/ports/sysutils/etcmerge). This utility does most of the work for you. Unlike the two-way diff used by mergemaster, this utility can compare the changes between three sets of edits:

  • The /etc from your original version of FreeBSD

  • Any changes you've made to /etc since then

  • The /etc for your new version of FreeBSD

Before any upgrade, you definitely want a fresh, tested backup of all of your data, including /etc.

Once you've installed etcmerge, ensure you have a backup copy of /etc:

# tar czvf etc.tgz /etc

Here, I've saved a copy only to the local hard drive. Be sure to copy it to another location as well, just to be safe: to another system, a removable media, or even your email account.

The next step is to locate a copy of /etc that is original to your current operating system and save it to /var/db/etc. (This is a good step to add to your regime when you install a new system.) Assuming this isn't a fresh install and you've made changes to /etc, you can get the original, unmodified /etc for your operating system version at http://people.freebsd.org/~eivind/etc/.

Here, I've downloaded the 5.1-RELEASE version and untarred it to the correct place:

# tar -C /var/db -zxvpf etc-5.1-RELEASE.tar.gz # ls /var/db/etc/

So, now you have a copy of the original /etc, as well as your own customized /etc. You'll receive the /etc for a newer version of FreeBSD once you've changed your cvs-supfile to reflect the newer tag [Hack #80] .

For example, I'm currently running 5.1-RELEASE, so my custom supfile contains this line:

*default tag=RELENG_5_1_0_RELEASE

When I'm ready to upgrade to 5.2, I'll change that line to reflect the new tag:

*default tag=RELENG_5_2_0_RELEASE

My next cvsup will grab the sources for the new operating system version.

None of the changes to /usr/src will be integrated until you make buildworld and make installworld as per the instructions in the handbook. Simply downloading the changes does not upgrade your operating system.

Once cvsup has finished downloading all of the changes, take the time to read /usr/src/UPDATING, which lists all of the known gotchas for this release. For example, there may be mandatory options for the kernel process of the upgrade, certain stages may require a reboot before the next stage works, or perhaps directory structures such as /etc have seen major changes.

Once you've made your necessary preparations, ensure these steps have succeeded before using etcmerge:

  • make buildworld

  • make buildkernel

  • make installkernel

  • make installworld

8.4.2 Using etcmerge

Now that you have a new world, use etcmerge to integrate any changes to /etc. As per its manpage, start with the initialization step:

# etcmerge init

The script will perk along for a moment or two before producing a screen full of lines that start with ETCMERGE. Here's the beginning of that output:

ETCMERGE: >>> Finding classes of files ETCMERGE: >>> Working from ETCMERGE: >>> Active: /etc ETCMERGE: >>> Reference: /var/db/etc ETCMERGE: >>> New: /root/etc-work/200401191624/etc-new

Note the name of the directory in the last line. It contains the working files that are ready for your review.

You'll then receive lines for different classes see man etcmerge for a description of each conflict class. Here's a sample output from a system I recently upgraded:

ETCMERGE: >>>> Class 7: 3 conflict(s)

A class 7 conflict means a file existed for all three versions of /etc. Any differences will appear with diff-style markers. This particular system has three files containing conflicts. Their names are in the file called 7.conflicts:

# more /root/etc-work/200401191624/7.conflicts ./manpath.config ./pwd.db ./spwd.db

The etc-merged subdirectory contains copies of those files with the differences marked. Look there and examine each file listed as containing conflicts:

# cd /root/etc-work/200401191624/etc-merged # vi manpath.config

Don't send pwd.db or spwd.db to an editor these are the database versions of your password files. Instead, use diff to see if the conflict is because you've added users or because FreeBSD has added a new user:

# diff etc-new/master.passwd /etc/master.passwd

Remove the two .db lines from 7.conflicts manually so etcmerge is aware that you've resolved the conflicts to your password databases.

As you review your own files, the angle bracket markers indicate which lines have changed. Next to each angle bracket marker is the name of the file containing the conflicting lines. For example, if the name of the file includes the /etc-new directory, the lines in question belong to the new version of the file. Once you've decided which version of the lines you wish to keep, remove the angle bracket lines as well as the unwanted version of the lines.

Once you're finished your edits, this command will integrate them:

# etcmerge install /etc/mail/aliases: 24 aliases, longest 10 bytes, 246 bytes total Install done - removing copies of old /etc/ and old reference. Done. #

Congratulations! You've successfully upgraded your operating system while maintaining your customizations to /etc.

8.4.3 See Also

  • [Hack #92]

  • man mergemaster

  • man etcmerge

  • man build

  • The makeworld section of the FreeBSD Handbook, which includes directions for using mergemaster (http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/makeworld.html)

Категории