Search the Catalog
LPI Linux Certification in a Nutshell

LPI Linux Certification in a Nutshell

Covers General Linux Exams 101 and 102

By Jeffrey Dean
May 2001
1-56592-748-6, Order Number: 7486
570 pages, $39.95

Part 2, Chapter 4
Linux Installation and Package Management (Topic 2.2)

Many resources describe Linux installation.[1] Despite its title, however, this section's Topic and Objectives do not provide an overview for the installation of any particular Linux distribution. Rather, they focus on four installation topics and two packaging tools as required for LPI Exam 102:

Objective 1: Design a Hard Disk Layout
The layout and partitioning of disks is a fundamental concept for almost all computer platforms. Unlike other operating systems though, Linux uses multiple partitions in a unified filesystem. This Objective covers this filesystem layout. Weight: 2.

Objective 2: Install a Boot Manager
Booting Linux is a process started by a boot manager. This Objective covers the use of LILO. Weight: 2.

Objective 3: Make and Install Programs from Source
The unique advantages of open source software allow the distribution of programs in source code form. This Objective covers compiling and installing programs from source code. (Objectives 5 and 6 deal with binary package management.) Weight: 2.

Objective 4: Manage Shared Libraries
One of the efficiencies of modern operating systems is the concept of shared libraries of system software. This Objective provides an overview of shared libraries and their configuration. Weight: 3.

Objective 5: Use Debian Package Management.
This topic covers the management of Debian Linux binary packages. Weight: 5.

Objective 6: Use Red Hat Package Manager (RPM)
This topic covers the management of RPM binary packages. Weight: 8.

Objective 1:

Design a Hard Disk Layout

Part of the installation process for Linux is the design of the hard disk partitioning scheme. If you're used to systems that reside on a single partition, this step may seem to complicate installation. However, there are advantages to splitting the filesystem into multiple partitions, potentially on multiple disks. Details about disks, partitions, and Linux filesystem top-level directories are provided in . This Topic covers considerations for implementing Linux disk layouts.

System Considerations

A variety of factors influence the choice of a disk layout plan for Linux, including:

Limited disk space

Except for read-only filesystems (such as CD-ROMs or a shared /usr partition), most Linux filesystems should have some free space available. Filesystems holding user data should be maintained with a generous amount of free space to accommodate user activity. Unfortunately, if there are many filesystems and all of them contain free space, a significant portion of disk space could be considered wasted. This presents a tradeoff between the number of filesystems in use and the availability of free disk space. Finding the right configuration depends on system requirements and available disk resources.

When disk space is limited, it is desirable to reduce the number of filesystems, thereby combining free space into a single contiguous pool. For example, installing Linux on a PC with only 1 GB of available disk space might best be implemented using only a few partitions:

/boot
50 MB. A small /boot filesystem in the first partition ensures that all kernels are below the 1024-cylinder limit.

/swap
100 MB.

/
850 MB. A large root partition holds everything on the system that's not in /boot.

The /boot partition could be combined with the root partition as long as the entire root partition fits within the 1024-cylinder limit (see ").

On older systems with smaller hard drives, Linux is often installed by spreading the directory tree across multiple physical disks. This is no different in practice than using multiple partitions on a single disk and often encourages the reuse of older hardware. An additional disk might be dedicated to /home in order to allow a larger work area for the users' home directories.

Larger systems

On larger platforms, functional issues such as backup strategies and required filesystem sizes can dictate disk layout. For example, suppose a file server is to be constructed serving 100 GB of executable datafiles to end-users via NFS. Such as system will have enough resources to compartmentalize various parts of the directory tree into separate filesystems and might look like this:

/boot
50 MB. Keep kernels under the 1024-cylinder limit.

/swap
100 MB.

/
100 MB.

/usr
1 GB. All of the executables in /usr are shared to workstations via read-only NFS.

/var
500 MB. By placing log files in their own partition, they won't threaten system stability if the filesystem is full.

/tmp
100 MB. By placing temporary files in their own partition, they won't threaten system stability if the filesystem is full.

/home
98 GB. This is the big filesystem, offered to users for their home directories.

On production servers, much of the system is often placed on redundant media, such as mirrored disks. Large filesystems, such as /home, may be stored on some form of disk array using a hardware controller.

System role

The role of the system also can dictate disk layout. In a traditional Unix-style network with NFS file servers, most of the workstations won't necessarily need all of their own executable files. In the days when disk space was at a premium, this represented a significant savings in disk space. While space on workstation disks isn't the problem it once was, keeping executables on a server still eliminates the administrative headache of distributing updates to workstations.

Backup

Some backup schemes use disk partitions as the basic unit of system backup. In such a scenario, each of the filesystems listed in /etc/fstab is backed up separately, and they are arranged so that each filesystem fits within the size of the backup media. For this reason, the available backup device capabilities can play a role in determining the ultimate size of partitions.

Swap Space

When you install Linux, you're asked to configure a swap, or virtual memory, partition. This special disk space is used to temporarily store portions of main memory containing programs or program data that is not needed constantly, allowing more processes to execute concurrently. An old rule of thumb for Linux is to set the size of the system's swap space to be equal to the amount of physical RAM in the machine. For example, if your system has 64 MB of RAM, it would be reasonable to set your swap size to at least 64 MB. Another rule of thumb that predates Linux says swap space should equal three times the main memory size. These are just guidelines, of course, because a system's utilization of virtual memory depends on what the system does and the number and size of processes it runs. Using the size of main memory, or thereabouts, is a good starting point.

Spreading swap space across multiple disk drives can allow better swap performance because multiple accesses can occur concurrently when multiple devices are used. For even better performance, place those disks on separate controllers, increasing bandwidth. For example, you could place half of your planned swap space on each of two IDE disks in your system. Those disks could be attached to the two separate IDE interfaces.

General Guidelines

Here are some guidelines for partitioning a Linux system:

Objective 2:

Install a Boot Manager

While it is possible to boot Linux from a floppy disk, most Linux installations boot from the computer's hard disk.[2] This is a two-step process that begins after the system BIOS is initialized and ready to run an operating system. Starting Linux consists of the following two basic phases:

Run lilo from the boot disk
It is Linux loader's (LILO's) job to find the selected kernel and get it loaded into memory, including any user-supplied options.

Launch the Linux kernel and start processes
LILO starts the loaded kernel. LILO's job at this point is complete and the hardware is placed under the control of the running kernel, which sets up shop and begins running processes.

LILO

The Linux Loader (LILO) is a small utility designed to load the Linux kernel (or the boot sector of another operating system) into memory and start it. A program that performs this function is commonly called a boot loader. While other boot loaders exist, LILO is the most popular and is installed as the default boot loader on most Linux distributions. LILO consists of two parts:

The boot loader
This part of LILO is a two-stage program intended to find and load a kernel.[3] The first stage of LILO usually resides in the Master Boot Record (MBR) of the hard disk. This is the code that is started at boot time by the system BIOS. It locates and launches a second, larger stage of the boot loader that resides elsewhere on disk. The second stage offers a user prompt to allow boot-time and kernel image selection options, finds the kernel, loads it into memory, and launches it.

The lilo command
Also called the map installer, lilo is used to install and configure the LILO boot loader. The lilo command reads a configuration file, which describes where to find kernel images, video information, the default boot disk, and so on. It encodes this information along with physical disk information and writes it in files for use by the boot loader.

The boot loader

When the system BIOS launches, LILO presents you with the following prompt:

LILO:

The LILO prompt is designed to allow you to select from multiple kernels or operating systems installed on the computer and to pass parameters to the kernel when it is loaded. Pressing the Tab key at the LILO prompt yields a list of available kernel images. One of the listed images will be the default as designated by an asterisk next to the name:

LILO: <TAB>
linux*    linux_586_smp   experimental

Under many circumstances, you won't need to select a kernel at boot time because LILO will boot the kernel configured as the default during the install process. However, if you later create a new kernel, have special hardware issues, or are operating your system in a dual-boot configuration, you may need to use some of LILO's options to load the kernel or operating system you desire.

The LILO map installer and its configuration file

Before any boot sequence can complete from your hard disk, the boot loader and associated information must be installed by the LILO map installer utility. The lilo command writes the portion of LILO that resides in the MBR, customized for your particular system. Your installation program will do it, then you'll repeat it manually if you build a new kernel yourself.

lilo

Syntax

lilo [options]

The lilo map installer reads a configuration file and writes a map file, which contains information needed by the boot loader to locate and launch Linux kernels or other operating systems.

Frequently used options

-C config_ file
Read the config_ file file instead of the default /etc/lilo.conf.

-m map_file
Write map_ file in place of the default as specified in the configuration file.

-q
Query the current configuration.

-v
Increase verbosity.

LILO's configuration file contains options and kernel image information. An array of options is available. Some are global, affecting LILO overall, while others are specific to a particular listed kernel image. Most basic Linux installations use only a few of the configuration options. Example 2-1 shows a simple LILO configuration file.

Example 2-1: Sample /etc/lilo.conf File

boot = /dev/hda
timeout = 50
prompt
read-only
map=/boot/map
install=/boot/boot.b
image = /boot/vmlinuz-2.2.5-15
  label = linux
  root = /dev/hda1

Each of these lines is described in the following list:

boot
The boot directive tells lilo the name of the hard disk partition device that contains the boot sector. For PCs with IDE disk drives, the devices will be /dev/hda, /dev/hdb, and so on.

timeout
The timeout directive sets the timeout in tenths of a second (deciseconds) for any user input from the keyboard. To enable an unattended reboot, this parameter is required if the prompt directive is used.

prompt
This directive instructs the boot loader to prompt the user. This behavior can be stimulated without the prompt directive if the user holds down the Shift, Ctrl, or Alt key when LILO starts.

read-only
This directive specifies that the root filesystem should initially be mounted read-only. Typically, the system startup procedure will remount it later as read/write.

map
The map directive specifies the location of the map file, which defaults to /boot/map.

install
The install directive specifies the file to install as the new boot sector, which defaults to /boot/boot.b.

image
An image line specifies a kernel image to offer for boot. It points to a specific kernel file. Multiple image lines may be used to configure LILO to boot multiple kernels and operating systems.

label
The optional label parameter is used after an image line and offers a label for that image. This label can be anything and generally describes the kernel image. Examples include linux, or perhaps smp for a multiprocessing kernel.

root
This parameter is used after each image line and specifies the device to be mounted as root for that image.

There is more to configuring and setting up LILO, but a detailed knowledge of LILO is not required for this LPI Objective. It is important to review one or two sample LILO configurations to make sense of the boot process. A discussion on using LILO to boot multiple kernels is presented in .

LILO locations

During installation, LILO can be placed either in the boot sector of the disk or in your root partition. If the system is intended as a Linux-only system, you won't need to worry about other boot loaders, and LILO can safely be placed into the boot sector. However, if you're running another operating system such as Windows, you should place its boot loader in the boot sector.[4]

TIP: It is important to understand the distinction between lilo, the map installer utility run interactively by the system administrator, and the boot loader, which is launched by the system BIOS at boot time. Both are parts of the LILO package.

Objective 3:

Make and Install Programs from Source

Open source software is credited with offering value that rivals or even exceeds that of proprietary vendors' products. While binary distributions make installation simple, you sometimes won't have access to a binary package. In these cases, you'll have to compile the program from scratch.

Getting Open Source and Free Software

Source code for the software that makes up a Linux distribution is available from a variety of sources. Your distribution media contain both source code and compiled binary forms of many software projects. Since much of the code that comes with Linux originates from the Free Software Foundation (FSF), the GNU web site contains a huge array of software.[5] Major projects, such as Apache (http://www.apache.org), distribute their own code. Whatever outlet you choose, the source code must be packaged for your use, and among the most popular packaging methods for source code is the tarball.

What's a tarball?

Code for a significant project that a software developer wishes to distribute is originally stored in a hierarchical tree of directories. Included are the source code (in the C language), a Makefile, and some documentation. In order to share the code, the entire tree must be encapsulated in a way that is efficient and easy to send and store electronically. A common method of doing this is to use tar to create a single tarfile containing the directory's contents, and then use gzip to compress it for efficiency. The resulting compressed file is referred to as a tarball. This method of distribution is popular because both tar and gzip are widely available and understood, ensuring a wide audience. A tarball is usually indicated by the use of the multiple extensions .tar and .gz, put together into .tar.gz. A combined single extension of .tgz is also popular.

Opening a tarball

The contents of a tarball is obtained through a two-step process. The file is first uncompressed with gzip and then extracted with tar. Following is an example, starting with tarball.tar.gz:

# gzip -d tarball.tar.gz
# tar xvf tarball.tar

The -d option to gzip indicates "decompress mode." If you prefer, you can use gunzip in place of gzip -d to do the same thing:

# gunzip tarball.tar.gz
# tar xvf tarball.tar

You can also avoid the intermediate unzipped file by piping the output of gzip straight into tar:

# gzip -dc tarball.tar.gz | tar xv

In this case, the -c option to gzip tells it to keep the compressed file in place. By avoiding the full-sized version, disk space is saved. For even more convenience, avoid using gzip entirely and use the decompression capability in tar:[6]

# tar zxvf tarball.tar.gz

TIP: All of these methods achieve the same result. Be sure you understand that tar can archive directly to files (not just to a tape drive) and that a compressed version of a tarfile is made with gzip. Be familiar with the various ways you could extract files from a tarball, including gzip -d; tar, gunzip; tar, gzip -d | tar; and tar z. You should be comfortable using tar and gzip and their more common options.

Compiling Open Source Software

Once you've extracted the source code, you're ready to compile it. You'll need to have the appropriate tools available on your system, namely a configure script, the GNU C compiler, gcc, and the dependency checker, make.

configure

Most larger source code packages include a configure script[7] located at the top of the source code tree. This script needs no modification or configuration from the user. When it executes, it examines your system to verify the existence of a compiler, libraries, utilities, and other items necessary for a successful compile. It uses the information it finds to produce a custom Makefile for the software package on your particular system. If configure finds that something is missing, it fails and gives you a terse but descriptive message. configure succeeds in most cases, leaving you ready to begin the actual compile process.

make

make is a utility for compiling software. When multiple source-code files are used in a project, it is rarely necessary to compile all of them for every build of the executable. Instead, only the source files that have changed since the last compilation really need to be compiled again.

make works by defining targets and their dependencies. The ultimate target in a software build is the executable file or files. They depend on object files, which in turn depend on source-code files. When a source file is edited, its date is more recent than that of the last compiled object. make is designed to automatically handle these dependencies and do the right thing.

To illustrate the basic idea, consider this trivial and silly example. Suppose you're writing a program with code in two files. The C file, main.c, holds the main( ) function:

int main(  ) {
  printit(  );
}

and printit.c contains the printit( ) function, which is called by main( ):

#include <stdio.h>
void printit(  ) {
  printf("Hello, world\n");
}

Both source files must be compiled into objects main.o and printit.o, and then linked together to form an executable application called hw. In this scenario, hw depends on the two object files, a relationship that could be defined like this:

hw: main.o printit.o

Using this syntax, the dependency of the object files on the source files would look like this:

main.o: main.c
printit.o: printit.c

With these three lines, there is a clear picture of the dependencies involved in the project. The next step is to add the commands necessary to satisfy each of the dependencies. Compiler directives are added next:

gcc -c main.c
gcc -c printit.c
gcc -o hw main.o printit.o

To allow for a change of compilers in the future, a variable can be defined to hold the actual compiler name:

CC = gcc

To use the variable, use the syntax $(variable) for substitution of the contents of the variable. Combining all this, the result is:

CC = gcc
 
hw: main.o printit.o
      $(CC) -o hw main.o printit.o
 
main.o: main.c
      $(CC) -c main.c
 
printit.o: printit.c
      $(CC) -c printit.c

This illustrates a simple Makefile, the default control file for make. It defines three targets: hw (the application), and main.o and printit.o (the two object files). A full compilation of the hw program is invoked by running make and specifying hw as the desired target:

# make hw
gcc -c main.c
gcc -c printit.c
gcc -o hw main.o printit.o

make automatically expects to find its instructions in Makefile. If a subsequent change is made to one of the source files, make will handle the dependency:

# touch printit.c
# make hw
gcc -c printit.c
gcc -o hw main.o printit.o

This trivial example doesn't illustrate a real-world use of make or the Makefile syntax. make also has powerful rule sets that allow commands for known dependency relationships to be issued automatically. These rules would shorten even this tiny Makefile.

Installing the compiled software

Most mature source-code projects come with a predetermined location in the filesystem for the executable files created by compilation. In many cases, they're expected to go to /usr/local/bin. To facilitate installation to these default locations, many Makefiles contain a special target called install. By executing the make install command, files are copied and set with the appropriate attributes.

WARNING: The default installation directory included in a project's Makefile may differ from that defined by your Linux distribution. If you upgrade software you are already using, this could lead to confusion over versions.

TIP: A basic understanding of make is sufficient for Exam 102. In addition, be prepared to add to or modify the contents of variables in a Makefile, such as include directories or paths. This could be necessary, for example, if additional libraries must be included in the compilation or if a command must be customized.

Example: Compiling bash

GNU's bash shell is presented here as an example of the process of compiling. You can find a compressed tarball of the bash source at the GNU FTP site, ftp://ftp.gnu.org/gnu/bash/. Multiple versions might be available. Version 2.03 is used in this example (you will find more recent versions). The compressed tarball is bash-2.03.tar.gz. As you can see by its name, it is a tar file that has been compressed with gzip. To uncompress the contents, use the compression option in tar:

# tar zxvf bash-2.03.tar.gz
bash-2.03/
bash-2.03/CWRU/
bash-2.03/CWRU/misc/
bash-2.03/CWRU/misc/open-files.c
bash-2.03/CWRU/misc/sigs.c
bash-2.03/CWRU/misc/pid.c
... (extraction continues) ...

Next move into the new directory, take a look around, and read some basic documentation:

# cd bash-2.03
# ls
AUTHORS        NEWS
CHANGES        NOTES
COMPAT         README
COPYING        Y2K
CWRU           aclocal.m4
INSTALL        alias.c
MANIFEST       alias.h
Makefile.in    ansi_stdlib.h
... (listing continues) ...
# less README

The build process for bash is started by using the dot-slash prefix to launch configure:

# ./configure
creating cache ./config.cache
checking host system type... i686-pc-linux-gnu
Beginning configuration for bash-2.03 for i686-pc-linux-gnu
checking for gcc... gcc
checking whether the C compiler (gcc  ) works... yes
checking whether the C compiler (gcc  ) is a 
  cross-compiler... no
checking whether we are using GNU C... yes
checking whether gcc accepts -g... yes
checking whether large file support needs explicit 
  enabling... yes
checking for POSIXized ISC... no
checking how to run the C preprocessor... gcc -E # make
... (configure continues) ...

Next, compile:

# make
/bin/sh ./support/mkversion.sh -b -s release -d 2.03 \
  -p 0 -o newversion.h && mv newversion.h version.h
 
***********************************************************
*                                                         *
* Making Bash-2.03.0-release for a i686 running linux-gnu
*                                                         *
***********************************************************
 
rm -f shell.o
gcc  -DPROGRAM='"bash"' -DCONF_HOSTTYPE='"i686"' \
  -DCONF_OSTYPE='"linux-gnu"' -DCONF_MACHTYPE='"i686
-pc-linux-gnu"' -DCONF_VENDOR='"pc"' -DSHELL \
  -DHAVE_CONFIG_H  -D_FILE_OFFSET_BITS=64  -I.  -I. -I./
lib -I/usr/local/include -g -O2 -c shell.c
rm -f eval.o
... (compile continues) ...

If the compile yields fatal errors, make terminates and the errors must be addressed before installation. Errors might include problems with the source code (unlikely), missing header files or libraries, and other problems. Error messages will usually be descriptive enough to lead you to the source of the problem.

The final step of installation requires that you are logged in as root in order to copy the files to the system directories:

# make install
/usr/bin/install -c -m 0755 bash /usr/local/bin/bash
/usr/bin/install -c -m 0755 bashbug /usr/local/bin/bashbug
( cd ./doc ; make  \
        man1dir=/usr/local/man/man1 man1ext=1 \
        man3dir=/usr/local/man/man3 man3ext=3 \
        infodir=/usr/local/info install )
make[1]: Entering directory `/home/ftp/bash-2.03/doc'
test -d /usr/local/man/man1 || /bin/sh ../support/mkdirs /usr/local/man/man1
test -d /usr/local/info || /bin/sh ../support/mkdirs 
  /usr/local/info
/usr/bin/install -c -m 644 ./bash.1 
  /usr/local/man/man1/bash.1
/usr/bin/install -c -m 644 ./bashbug.1 
  /usr/local/man/man1/bashbug.1
/usr/bin/install -c -m 644 ./bashref.info 
  /usr/local/info/bash.info
if /bin/sh -c 'install-info --version' 
  >/dev/null 2>&1; then \
  install-info --dir-file=/usr/local/info/dir 
  /usr/local/info/bash.info; \
else true; fi
make[1]: Leaving directory `/home/ftp/bash-2.03/doc'

The installation places the new version of bash in /usr/local/bin. Now, two working versions of bash are available on the system:

# which bash
/bin/bash
# /bin/bash -version
GNU bash, version 1.14.7(1)
# /usr/local/bin/bash -version
GNU bash, version 2.03.0(1)-release (i686-pc-linux-gnu)
Copyright 1998 Free Software Foundation, Inc. 

TIP: Familiarize yourself with the acquisition, configuration, compilation, and installation of software from source. Be prepared to answer questions on make and Makefile, the function of the configure utility, gzip, and tar.

Objective 4:

Manage Shared Libraries

When a program is compiled under Linux, many of the functions required by the program are linked from system libraries that handle disks, memory, and other functions. For example, when printf( ) is used in a program, the programmer doesn't provide the printf( ) source code, but instead expects that the system already has a library containing such functions. When the compiler needs to link the code for printf( ), it can be found in a system library and copied into the executable. A program that contains executable code from these libraries is said to be statically linked because it stands alone, requiring no additional code at runtime.

Statically linked programs can have a few liabilities. First, they tend to get large, because they include executables for all of the library functions linked into them. Also, memory is wasted when many different programs running concurrently contain the same library functions. To avoid these problems, many programs are dynamically linked. Such programs utilize the same routines but don't contain the library code. Instead, they are linked into the executable at runtime. This dynamic linking process allows multiple programs to use the same library code in memory and makes executable files smaller. Dynamically linked libraries are shared among many applications and are thus called shared libraries. A full discussion of libraries is beyond the scope of the LPIC Level 1 exams. However, a general understanding of some configuration techniques is required.

Shared Library Dependencies

Any program that is dynamically linked will require at least a few shared libraries. If the required libraries don't exist or can't be found, the program will fail to run. This could happen, for example, if you attempt to run an application written for the GNOME graphical environment but haven't installed the required GTK+ libraries. Simply installing the correct libraries should eliminate such problems. The ldd utility can be used to determine which libraries are necessary for a particular executable.

ldd

Syntax

ldd programs

Description

Display shared libraries required by each of the programs listed on the command line. The results indicate the name of the library and where the library is expected to be in the filesystem.

Example

In Objective 3, a trivial executable called hw was created. Despite its small size, however, hw requires two shared libraries:

# ldd /home/jdean/hw
/home/jdean/hw:
     libc.so.6 => /lib/libc.so.6 (0x40018000)
     /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

The bash shell requires three shared libraries:

# ldd /bin/bash
/bin/bash:
     libtermcap.so.2 => /lib/libtermcap.so.2 (0x40018000)
     libc.so.6 => /lib/libc.so.6 (0x4001c000)
     /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

Linking Shared Libraries

Dynamically linked executables are examined at runtime by the shared object dynamic linker, ld.so. This program looks for dependencies in the executable being loaded and attempts to satisfy any unresolved links to system-shared libraries. If ld.so can't find a specified library, it fails, and the executable won't run.

To illustrate this, let's assume that the printit( ) function from the hw example in Objective 3 is moved to a shared library instead of being compiled into the program. The custom library is called libprintit.so and stored in /usr/local/lib. hw is reconfigured and recompiled to use the new library.[8] By default, ld.so doesn't expect to look in /usr/local/lib for libraries, and fails to find printit( ) at runtime:

# ./hw
./hw: error in loading shared libraries: libprintit.so: 
   cannot open shared object file: No such file or directory

To find the new library, ld.so must be instructed to look in /usr/local/lib. There are a few ways to do this. One simple way is to add a colon-separated list of directories to the shell environment variable LD_LIBRARY_PATH, which will prompt ld.so to look in any directories it finds there. However, this method may not be appropriate for system libraries, because users might not set their LD_LIBRARY_PATH correctly.

To make the search of /usr/local/lib part of the default behavior for ld.so, files in the new directory must be included in an index of library names and locations. This index is /etc/ld.so.cache. It's a binary file, which means it can be read quickly by ld.so. To add the new library entry to the cache, its directory is first added to the ld.so.conf file, which contains directories to be indexed by the ldconfig utility.

ldconfig

Syntax

ldconfig [options] lib_dirs

Description

Update the ld.so cache file with shared libraries specified on the command line in lib_dirs, in trusted directories /usr/lib and /lib, and in the directories found in /etc/ld.so.conf.

Frequently used options

-p
Display the contents of the current cache instead of recreating it.

-v
Verbose mode. Display progress during execution.

Example 1

Examine the contents of the ld.so library cache:

# ldconfig -p
299 libs found in cache `/etc/ld.so.cache' (version 1.7.0)
    libzvt.so.2 (libc6) => /usr/lib/libzvt.so.2
    libz.so.1 (libc6) => /usr/lib/libz.so.1
    libz.so.1 (ELF) => /usr/i486-linux-libc5/lib/libz.so.1
    libz.so (libc6) => /usr/lib/libz.so
    libx11amp.so.0 (libc6) => /usr/X11R6/lib/libx11amp.so.0
    libxml.so.0 (libc6) => /usr/lib/libxml.so.0 
(... listing continues ...)

Example 2

Look for a specific library entry in the cache:

# ldconfig -p | grep "printit"
    libprintit.so (libc6) => /usr/local/lib/libprintit.so

Example 3

Rebuild the cache:

# ldconfig

After /usr/local/lib is added, ld.so.conf might look like this:

/usr/lib
/usr/i486-linux-libc5/lib
/usr/X11R6/lib
/usr/local/lib

Next, ldconfig is run to include libraries found in /usr/local/lib in /etc/ld.so.cache :

# ldconfig
# ./hw
Hello, world

Now the hw program can execute correctly because ld.so can find libprintit.so in /usr/local/lib. It is important to run ldconfig after any changes in system libraries to be sure that the cache is up-to-date.

Objective 5:

Use Debian Package Management

The Debian package management system is a versatile and automated suite of tools used to acquire and manage software packages for Debian Linux. The system automatically handles many of the management details associated with interdependent software running on your system.

Debian Package Management Overview

Each Debian package contains program and configuration files, documentation, and noted dependencies on other packages. The names of Debian packages have three common elements, including:

Package name
A Debian package name is short and descriptive. When multiple words are used in the name, they are separated by hyphens. Typical names include binutils, kernel-source, and telnet.

Version number
Each package has a version number. Most package versions are the same as that of the software they contain, thus the format of package versions varies from package to package. Most are numeric, with major, patch, and release numbers, but other information may appear as well. Typical versions are 0.6.7-7, 0.96a-14, 6.05, 80b2-8, and 2.0.7.19981211. The version is separated from the package name with an underscore.

A file extension
By default, all Debian packages end with .deb file extension.

Figure 2-1 illustrates a Debian package name.

Figure 2-1. The structure of a Debian GNU/Linux package name

 

Managing Debian Packages

The original Debian package management tool is dpkg, which operates directly on .deb package files and can be used to automate the installation and maintenance of software packages. The alternative apt-get tool operates using package names, obtaining them from a predefined source (such as CD-ROMs, FTP sites, etc.). Both tools work from the command line.

The dselect command offers an interactive menu that allows the administrator to select from a list of available packages and mark them for subsequent installation. The alien command allows the use of non-Debian packages, such as the Red Hat RPM format.

For complete information on Debian package management commands, see details in their respective manpages.

dpkg

Syntax

dpkg [options] action

Description

The Debian package manager command, dpkg, consists of an action that specifies a major mode of operation as well as zero or more options, which modify the action's behavior.

The dpkg command maintains package information in /var/lib/dpkg. Two files located there of particular interest are:

available
The list of all available packages.

status
Contains package attributes, such as whether it is installed or marked for removal.

These files are modified by dpkg, dselect, and apt-get, and it is unlikely that they will ever need to be edited.

Frequently used options

-E
Using this option, dpkg will not overwrite a previously installed package of the same version.

-G
Using this option, dpkg will not overwrite a previously installed package with an older version of that same package.

-R (also --recursive)
Recursively process package files in specified subdirectories. Works with -i, --install, --unpack, and so on.

Frequently used actions

--configure package
Configure an unpacked package. This involves setup of configuration files.

-i package_ file (also --install package_ file)
Install the package contained in package_ file. This involves backup of old files, unpacking and installation of new files, and configuration.

-l [pattern] (also --list [pattern])
Display information for installed package names that match pattern.

-L package (also --listfiles package)
List files installed from package.

--print-avail package
Display details found in /var/lib/dpkg/available about package.

---purge package
Remove everything for package.

-r package (also --remove package)
Remove everything except configuration files for package.

-s package (also --status package)
Report the status of package.

-S search_pattern (also --search search_ pattern)
Search for a filename matching search_ pattern from installed packages.

--unpack package_ file
Unpack package_ file, but don't install the package it contains.

Example 1

Install a package using dpkg -i with the name of an available package file:

# dpkg -i ./hdparm_3.3-3.deb
(Reading database ... 54816 files and directories 
  currently installed.)
Preparing to replace hdparm 3.3-3 (using hdparm_3.3-3.deb)
Unpacking replacement hdparm ...
Setting up hdparm (3.3-3) ...

Alternatively, use apt-get install with the name of the package. In this case, the package comes from the location or locations configured in /etc/apt/sources.list. For this example, the location is http://http.us.debian.org:

# apt-get install elvis
Reading Package Lists... Done
Building Dependency Tree... Done
The following extra packages will be installed:
  libncurses4 xlib6g
The following NEW packages will be installed:
  elvis
2 packages upgraded, 1 newly installed, 0 to remove 
  and 376 not upgraded.
Need to get 1678kB of archives. After unpacking 2544kB 
  will be used.
Do you want to continue? [Y/n] y
Get:1 http://http.us.debian.org stable/main 
  libncurses4 4.2-9 [180kB]
Get:2 http://http.us.debian.org stable/main 
  xlib6g 3.3.6-11 [993kB]
Get:3 http://http.us.debian.org stable/main 
  elvis 2.1.4-1 [505kB]
Fetched 1678kB in 4m11s (6663B/s)
(Reading database ... 54730 files and directories 
  currently installed.)
Preparing to replace libncurses4 4.2-3 (using 
  .../libncurses4_4.2-9_i386.deb) ...
Unpacking replacement libncurses4 ...
(installation continues...)

Example 2

Upgrading a package is no different from installing one. However, you should use the -G option when upgrading with dpkg to ensure that the installation won't proceed if a newer version of the same package is already installed.

Example 3

Use dpkg -r or dpkg --purge to remove a package:

# dpkg --purge elvis
(Reading database ... 54816 files and directories 
  currently installed.)
Removing elvis ...
(purge continues...)

Example 4

Use the dpkg -S command to find a package containing specific files. In this example, apt-get is contained in the apt package:

# dpkg -S apt-get
apt: /usr/share/man/man8/apt-get.8.gz
apt: /usr/bin/apt-get

Example 5

Obtain package status information, such as version, content, dependencies, integrity, and installation status, using dpkg -s:

# dpkg -s apt
Package: apt
Status: install ok installed
Priority: optional
Section: admin
Installed-Size: 1388
(listing continues...)

Example 6

List the files in a package using dpkg -L and process the output using grep or less:

# dpkg -L apt | grep '^/usr/bin'
/usr/bin
/usr/bin/apt-cache
/usr/bin/apt-cdrom
/usr/bin/apt-config
/usr/bin/apt-get

Example 7

List the installed packages using dpkg -l; if you don't specify a pattern, all packages will be listed:

# dpkg -l xdm
ii  xdm             3.3.2.3a-11    X display manager

Example 8

Use dpkg -S to determine the package from which a particular file was installed with the filename:

# dpkg -S /usr/bin/nl
textutils: /usr/bin/nl

apt-get

Syntax

apt-get [options] [command] [package_name ...]

Description

The apt-get command is part of the Advanced Package Tool (APT) management system. It does not work directly with .deb files like dpkg, but uses package names instead. apt-get maintains a database of package information that enables the tool to automatically upgrade packages and their dependencies as new package releases become available.

Frequently used options

-d
Download files, but do not install. This is useful when you wish to get a large number of package files but delay their installation to prevent installation errors from stopping the download process.

-s
Simulate the steps in a package change, but do not actually change the system.

-y
Automatically respond "yes" to all prompts, instead of prompting you for a response during package installation/removal.

Frequently used commands

dist-upgrade
This command is used to automatically upgrade to new versions of Debian Linux.

install
The install command is used to install or upgrade one or more packages by name.

remove
This command is used to remove the specified packages.

update
Running apt-get update fetches a list of currently available packages. This is typically done before any changes are made to existing packages.

upgrade
The upgrade command is used to safely upgrade a system's complete set of packages to current versions. It is conservative and will not process upgrades that could cause a conflict or break an existing configuration; it also will not remove packages.

Additional commands and options are available. See the apt-get manpage for more information.

apt-get uses /etc/apt/sources.list to determine where packages should be obtained. This file is not in the Objectives for Exam 102.

Example

Remove the elvis package using apt-get.

# apt-get remove elvis
Reading Package Lists... Done
Building Dependency Tree... Done
The following packages will be REMOVED:
  elvis
0 packages upgraded, 0 newly installed, 1 to remove 
  and 376 not upgraded.
Need to get 0B of archives. After unpacking 1363kB 
  will be freed.
Do you want to continue? [Y/n] y
(Reading database ... 54816 files and directories 
  currently installed.)
Removing elvis ...
(removal continues...)

In this example, the user is required to respond with y when promted to continue. Using the -y option to apt-get would eliminate this interaction.

dselect

Syntax

dselect

Description

dselect is an interactive, menu-driven, frontend tool for dpkg and is usually invoked without parameters. The dselect command lets you interactively manage packages by selecting them for installation, removal, configuration, and so forth. Selections are made from a locally stored list of available packages, which may be updated while running dselect. Package actions initiated by dselect are carried out using dpkg.

alien

Syntax

alien [--to-deb] [--patch=patchfile] [options] file

Description

Convert to or install a non-Debian (or "alien") package. Supported package types include Red Hat .rpm, Stampede .slp, Slackware .tgz, and generic .tar.gz files. rpm must also be installed on the system in order to convert an RPM package into a .deb package. The alien command produces an output package in Debian format by default after conversion.

Frequently used option

-i
Automatically install the output package and remove the converted package file.

Example

Install a non-Debian package on Debian system using alien with the -i option:

alien -i package.rpm

TIP: dselect, apt-get, and alien are important parts of Debian package management, but detailed knowledge of dpkg is of primary importance for Exam 102.

Objective 6:

Use Red Hat Package Manager (RPM)

The Red Hat Package Manager is among the most popular methods for the distribution of software for Linux and is installed by default on many distributions. It automatically handles many of the management details associated with interdependent software running on your system.

RPM Overview

RPM automates the installation and maintenance of software packages. Built into each package are program files, configuration files, documentation, and dependencies on other packages. Package files are manipulated using the rpm command, which maintains a database of all installed packages and their files. Information from new packages is added to this database, and it's consulted on a file-by-file basis for dependencies when packages are removed, queried, and installed.

As with Debian packages, RPM filenames have three common elements:

Name
An RPM package name is short and descriptive. If multiple words are used, they are separated by hyphens (not underscores, as you might expect). Typical names include binutils, caching-nameserver, cvs, gmc, kernel-source, and telnet.

Version
Each package has a version. Most package versions are the same as that of the software they contain, thus the format of package versions varies from package to package. Most are numeric, with major, patch, and release numbers, but other information may appear as well. Typical versions are 3.0beta5-7, 1.05a-4, 2.7-5, 1.10.5-2, 1.1.1pre2-2, 1.14r4-4, 6.5.2-free3-rsaref, and 0.9_alpha3-6. The version is separated from the name by a hyphen.

Architecture
Packages containing binary (compiled) files are by their nature specific to a particular type of system. For PCs, the RPM architecture designation is i386, meaning the Intel 80386 and subsequent line of microprocessors and compatibles. For Sun and Sun-compatible processors, the architecture is sparc. The architecture is separated from the version with a dot.

A .rpm extension
All RPM files end with .rpm extension by default.

An RPM filename is constructed by tying these elements together in one long string, as shown in Figure 2-2.

Figure 2-2. The structure of an RPM package name

 

As you can see, there are three uses for hyphens in RPM filenames. They appear as word separators in package names, as a delimiter between names and versions, and as part of the version. This may be confusing at first, but the version is usually obvious, making the use of hyphens unambiguous.[9]

Running rpm

The rpm command provides for the installation, removal, upgrade, verification, and other management of RPM packages and has a bewildering array of options. Some are of the traditional single-letter style, while others are the --option variety. In most cases, both styles exist and are interchangeable. At first glance, configuring rpm may appear to be a bit daunting. However, its operation is segmented into modes, which are enabled using one (and only one) of the mode options. Within a mode, additional mode-specific options become available to modify the behavior of rpm. The major modes of rpm and some of the most frequently used mode-specific options follow. For complete information on how to use and manage RPM packages, see the rpm manpage or the synopsis offered by rpm --help.

rpm

Syntax

rpm -i (also rpm -- install), 
rpm -U (also rpm --upgrade)
rpm -e (also --uninstall)
rpm -q (also --query)
rpm -V

Install/Upgrade mode

The install mode ( rpm -i) is used to install new packages. A variant of install mode is the upgrade mode ( rpm -U), where an installed package is upgraded to a more recent version.

Frequently used install- and upgrade-mode options

--force
This option allows the replacement of existing packages and of files from previously installed packages; for upgrades, it allows the replacement of a newer package with an older one.

-h (also --hash)
This option adds a string of 50 hash marks (#) during installation as a sort of progress indicator.

--nodeps
rpm will skip dependency checking with this option enabled. This allows you to install a package without regard to dependencies.

--test
This option will run through all the motions except for actually writing files; it's useful to verify that a package will install correctly prior to making the attempt. Note that verbose and hash options cannot be used with --test, but -vv can.

-v
This option sets verbose mode.

-vv
This sets really verbose mode. The manpage describes this as "print lots of ugly debugging information."

Example 1

To install a new package, simply use the rpm -i command with the name of a package file. If the new package depends upon another package, the install fails, like this:

# rpm -iv netscape-communicator-4.72-3.i386.rpm
error: failed dependencies:
        netscape-common = 4.72 is needed by 
        netscape-communicator-4.72-3

To correct the problem, the dependency must first be satisfied. In this example, netscape-communicator is dependent on netscape-common, which is installed first:

# rpm -iv netscape-common-4.72-3.i386.rpm
netscape-common             
# rpm -iv netscape-communicator-4.72-3.i386.rpm
netscape-communicator

Example 2

Upgrading an existing package to a newer version can be done with the -U option. Upgrade mode is really a special case of the install mode, where existing packages can be superseded by newer versions. Using -U, a package can be installed even if it doesn't already exist, in which case it behaves just like -i:

# rpm -U netscape-common-4.72-3.i386.rpm

Uninstall mode

This mode is used to remove installed packages from the system. By default, rpm uninstalls a package only if no other packages are dependent on it.

Frequently used uninstall-mode options

--nodeps
rpm skips dependency checking with this option enabled.

--test
This option runs through all the motions except for actually uninstalling things; it's useful to verify that a package can be uninstalled correctly without breaking other dependencies prior to making the attempt. Note that verbose and hash options cannot be used with --test, but -vv can.

Example

Package removal is the opposite of installation and has the same dependency constraints:

# rpm -e netscape-common
error: removing these packages would break dependencies:
        netscape-common = 4.72 is needed by 
        netscape-communicator-4.72-3

Query mode

Installed packages and raw package files can be queried using the rpm -q command. Query-mode options exist for package and information selection.

Frequently used query-mode package selection options

-a (also --all)
Display a list of all packages installed on the system. This is particularly useful when piped to grep if you're not sure of the name of a package or when you want to look for packages that share a common attribute.

-f filename (also --file)
Display the package that contains a particular file.

-p package_ filename
Query a package file. Most useful with -i, described next.

Frequently used query-mode information selection options

-c (also --configfiles)
List only configuration files.

-d (also --docfiles)
List only documentation files.

-i package
Not to be confused with the install mode. Display information about an installed package, or when combined with -p, about a package file. In the latter case, package is a filename.

-l package (also --list)
List all of the files contained in package. When used with -p, the package is a filename.

-R (also --requires)
List packages on which this package depends.

Example 1

To determine the version of the software contained in an RPM file, use the query and package information options:

# rpm -qpi xv-3.10a-13.i386.rpm | grep Version 
Version     : 3.10a                Vendor: Red Hat Software

For installed packages, omit the -p option and specify a package name instead of a package filename:

# rpm -qi kernel-source | grep Version
Version     : 2.2.5                Vendor: Red Hat Software

Example 2

Enter query mode and list the files contained in a package:

# rpm -qlp gnucash-1.3.0-1.i386.rpm
/usr/bin/gnc-prices
/usr/bin/gnucash
/usr/bin/gnucash.gnome
/usr/doc/gnucash
/usr/doc/gnucash/CHANGES
 (...output continues ...)

For an installed package, enter query mode and use the -l option along with the package name:

# rpm -ql kernel-source
/usr/src/linux-2.2.5/COPYING
/usr/src/linux-2.2.5/CREDITS
/usr/src/linux-2.2.5/Documentation
/usr/src/linux-2.2.5/Documentation/00-INDEX
/usr/src/linux-2.2.5/Documentation/ARM-README
(...output continues ...)

Example 3

List the documentation files in a package:

# rpm -qd at      
/usr/doc/at-3.1.7/ChangeLog
/usr/doc/at-3.1.7/Copyright
/usr/doc/at-3.1.7/Problems
/usr/doc/at-3.1.7/README
/usr/doc/at-3.1.7/timespec
/usr/man/man1/at.1
/usr/man/man1/atq.1
/usr/man/man1/atrm.1
/usr/man/man1/batch.1
/usr/man/man8/atd.8
/usr/man/man8/atrun.8

Use -p for package filenames.

Example 4

List configuration files or scripts in a package:

# rpm -qc at 
/etc/at.deny
/etc/rc.d/init.d/atd

Example 5

Determine the package from which a particular file was installed. Of course, not all files originate from packages:

# rpm -qf /etc/issue 
file /etc/issue is not owned by any package

Those that are package members look like this:

# rpm -qf /etc/aliases
sendmail-8.9.3-10

Example 6

List the packages that have been installed on the system (all or a subset):

# rpm -qa
(... hundreds of packages are listed ...)

To search for a subset with kernel in the name, pipe the previous command to grep:

# rpm -qa | grep kernel
kernel-headers-2.2.5-15
kernel-2.2.5-15
kernel-pcmcia-cs-2.2.5-15
kernel-smp-2.2.5-15
kernel-source-2.2.5-15
kernelcfg-0.5-5
kernel-ibcs-2.2.5-15
kernel-doc-2.2.5-15

Verify mode

Files from installed packages can be compared against their expected configuration from the RPM database by using rpm -V. The output is described in ."

Frequently used verify-mode options

--nofiles
Ignores missing files.

--nomd5
Ignores MD5 checksum errors.

--nopgp
Ignores PGP checking errors.

Additional operational modes

There are also modes in RPM for building, rebuilding, signing, and checking the signature of RPM files; however, these are beyond the scope of the LPIC Level 1 exams.

TIP: Make certain that you are aware of RPM's major operational modes and their commonly used mode-specific options. Knowledge of specific options will be necessary. Read through the rpm manpage at least once.


1. One excellent resource is Running Linux, Third Edition, by Matt Welsh, Matthias Kalle Dalheimer, and Lar Kaufman (O'Reilly & Associates).

2. This isn't to say that you can't boot from other media such as floppies--many people do.

3. It's a two-stage operation because the boot sector of the disk is too small to hold the entire boot loader program. The code located in the boot sector is compact because its only function is to launch the second stage, which is the interactive portion.

4. Multiple-boot and multiple-OS configurations are beyond the scope of the LPIC Level 1 exams.

5. Not just for Linux, either. Although Linux distributions are largely made up of GNU software, that software runs on many other Unix and Unix-like operating systems, including the various flavors of BSD (e.g., FreeBSD, NetBSD, and OpenBSD).

6. GNU tar offers compression; older tar programs didn't.

7. configure is produced for you by the programmer using the autoconf utility. autoconf is beyond the scope LPIC Level 1 exams.

8. Though not complicated, the compilation of libprintit.so and hw is beyond the scope of the LPIC Level 1 exams.

9. Perhaps this won't be clear at first glance, but once you're used to RPM names you'll know what to expect.

Back to: LPI Linux Certification in a Nutshell


O'Reilly Home | O'Reilly Bookstores | How to Order | O'Reilly Contacts
International | About O'Reilly | Affiliated Companies

© 2001, O'Reilly & Associates, Inc.
webmaster@oreilly.com