Jordan Hubbard, formerly one of the core developers of FreeBSD (now working at Apple as an architect of Mac OS X), is responsible for most of the initial work on the package system. FreeBSD's system has been adopted by NetBSD and other platforms and refined over the years, with the best of the independent development efforts being rolled back into FreeBSD. By its simplest definition, a package system is a way of bundling up software (including config files, shared libraries, and documentation) and extracting it again onto another machine, in which its configuration will be valid enough that the software can run properly on the new machine. Early package managers did little more than direct the bundling and extraction processes. RPM and FreeBSD's packagers both have numerous additional features:
The major difference between the two packagers is related very closely to the different development philosophies of FreeBSD and Linux. Linux has a number of different distributions, with different versions of glibc (a set of core shared libraries not relevant to FreeBSD) and a nearly infinite variety of hardware on which the operating system can run. RPM package files are usually retrieved from any of thousands of developer sites all over the Web, not just a single central repository. RPM must necessarily be quite complex in order to handle all this diversityand indeed it is. Its command-line interface is fairly arcane and requires a lot of documentation to be used properly. FreeBSD, however, benefits from a centralized development model and a single supported hardware platform, so the package model can be much simpler, both in architecture and usage. As we discussed in Chapter 12, "The FreeBSD Filesystem," the /usr/local hierarchy is reserved for items that you install yourself, which refers specifically to software you install from the ports and packages. Table 16.1 shows the /usr/local directory structure (although your installation may vary slightly, especially if you've installed software already).
In other words, /usr/local has the same basic hierarchy as the one found directly within /usr (with the exception that man pages are found at /usr/local/man rather than /usr/local/share/man, as you might expect). FreeBSD's package system keeps anything you install in the /usr/local TRee and out of the /usr tree, thus maintaining the seamless but strict separation between base and user-installed software. Shared Libraries and DependenciesA shared library is a centralized file that provides precompiled function calls. Using a shared library, a program can access certain functions without having to have those functions built into itself. This technique, known as dynamic linking, reduces file size and redundancy in the executable binaries in comparison to static linking, which compiles all necessary functions into every program. Shared libraries exist on nearly all platforms, although they have different namesfor instance, Windows calls them Dynamic Link Libraries (DLLs). FreeBSD already has a large number of shared libraries installed in the base systemenough to support all the software that's part of FreeBSD itselfand provides hooks for software that you might install later. Nevertheless, you're almost certain to run across a program that needs a shared library that doesn't exist in the base FreeBSD. In FreeBSD, basic shared libraries are stored in /usr/lib, and any shared libraries that you install go into /usr/local/lib. All programs know automatically to look first in /usr/lib for the shared libraries they need, and they then look in /usr/local/lib (as well as a couple of other places). You can control this search path in /etc/rc.conf, as you saw in Chapter 14, "System Configuration and Startup Scripts." Every package has a listing of dependencies (packages that must already be installed for the package in question to run) that includes both shared libraries and executables (programs). If a dependency isn't already installed, the package system automatically hunts it down and installs it before proceeding with the installation. If you later remove some program or library (via the package tools) that is a dependency for some other installed package, the tools tell you about this and refuse to proceed. Obtaining Information on Installed PackagesThe first step toward getting to know the packages is to explore the information about the packages you have already installed. Chances are you've installed some packages as you read earlier sections of this book, or you may have indirectly installed some as part of a custom installation (for example, if you chose to install X11 during the FreeBSD installation process). If not, don't worrythe information here will be just as useful to you later. The tools you use to manage packages are pkg_add, pkg_delete, pkg_info, pkg_update, pkg_version, and pkg_create. Each one does pretty much what you would expect it to do; one hallmark of FreeBSD's style is to use differently named programs rather than obscure switches and parameters on the same program. Each of these tools interacts with a filesystem database at /var/db/pkg, which you can consult by simply using ls to take a quick glance at your system's package status. This repository has a directory for each installed package that includes information about the packing list (the manifest of files in the package) and the dependencies. pkg_info uses this database to print out the short descriptions of every package you currently have installed, as you can see in Listing 16.1. Listing 16.1. Sample Output from pkg_info
You can also get lots of information on any single package by using its name as an argument, and even more information by adding the -v (verbose) switch. As with RPM, packages in FreeBSD have names with multiple parts separated by dashesthe package name, followed by the version. However, RPM files tend to be geared toward multiple platforms, and often contain the name of the intended platform in the package name. Instead, because FreeBSD is almost exclusively used on x86 hardware, a FreeBSD package file simply takes the form name-version.tbz. Here's an example: elm-2.5.8.tbz Packages are generally .tbz files (called tarballs), which is shorthand for .tar.bz2. Using tarballs is the traditional way of archiving a directory structure under UNIXyou first pack the directory into one file using tar and then compress it using bzip. To use tools such as pkg_info -v, you need to specify the full package name, including the version, as shown in Listing 16.2. Note FreeBSD's packages have recently been changed over to .tbz format from the previous .tgz (.tar.gz) format because the bzip2 compressor achieves better results than the traditional gzip compressor. Listing 16.2. Verbose Output of pkg_info
This listing tells you everything you need to know about the packagefrom its long description, to its dependencies, to its packing list (with the MD5 "fingerprint" checksum for each file, listed in its Comment field), and even the install script that was used during its installation, to help you track down where its component files are. Not shown in this listing is the complete mtree file, a map of all directories containing components for the selected package. The information in the packing list is more than a simple list of component files: it also contains UNEXEC commands that are used during the deinstallation process for any package, so that if you use pkg_delete to remove the package, it simply executes these commands to cleanly remove all appropriate files and directories. In this example, the default sudoers.sample file in the /etc subdirectory of the script's working directory (/usr/local, represented by the token %D) is removed as part of the default packing list. Additionally, in an UNEXEC command, the /usr/local/etc/sudoers file is compared to the default sudoers.sample file in the same directory; if they match, you never made any changes to the sudoers file since installing it, and it is deleted as well. Otherwise, pkg_delete knows you've made your own changes to the file, and it leaves it alone. As you can see, a well-written and well-behaved package (and just about all packages are well behaved) will erase cleanly off your system when removed, leaving nary a trace of itself behind, but leaving your locally changed files untouched. How do you know that this version of the package is current? You can determine this easily by using the pkg_version tool. It works only if the ports collection has been installedand it should be installed unless you're severely short on disk space. You learn more about the ports collection later in this chapter, but all you need to know for understanding pkg_version is that the ports collection (if kept up to date) has a listing of the current version of every package. The pkg_version tool compares the versions of every installed package to the version found in the ports collection, and it tells you whether your packages are up to date (see Listing 16.3). Listing 16.3. Sample Output of pkg_version
Without the -v option, pkg_version wouldn't print the third column; you'd just get the icon in the second column. The version string would also not be appended to the package names in the first column. Either way, this provides you with a quick, at-a-glance method for telling where your maintenance efforts are needed. |