For the impatient, here’s a quick primer on how to find out what’s installed on your Linux system and how to obtain and install new software.
Modern operating systems divide their contents into packages that can be installed independently of one another. The default installation includes a range of starter packages that you can expand and contract according to your needs. When adding software, don your security hat and remember that additional software creates additional attack surface. Only install what’s necessary.
Add-on software is often provided in the form of precompiled packages as well, although the degree to which this is a mainstream approach varies widely among systems. Most software is developed by independent groups that release the software in the form of source code. Package repositories then pick up the source code, compile it appropriately for the conventions in use on the systems they serve, and package the resulting binaries. It’s usually easier to install a system-specific binary package than to fetch and compile the original source code. However, packagers are sometimes a release or two behind the current version.
The fact that two systems use the same package format doesn’t necessarily mean that packages for the two systems are interchangeable. Red Hat and SUSE both use RPM, for example, but their filesystem layouts are somewhat different. It’s best to use packages designed for your particular system if they are available.
Our example systems provide excellent package management systems that include tools for accessing and searching hosted software repositories. Distributors aggressively maintain these repositories on behalf of the community, to facilitate patching and software updates. Life is good.
When the packaged format is insufficient, administrators must install software the old-fashioned way: by downloading a tar archive of the source code and manually configuring, compiling, and installing it. Depending on the software and the operating system, this process can range from trivial to nightmarish.
In this book, we generally assume that optional software is already installed rather than torturing you with boilerplate instructions for installing every package. If there’s a potential for confusion, we sometimes mention the exact names of the packages needed to complete a particular project. For the most part, however, we don’t repeat installation instructions since they tend to be similar from one package to the next.
Determining if software is already installed
For a variety of reasons, it can be a bit tricky to determine which package contains the software you actually need. Rather than starting at the package level, it’s easier to use the shell’s which command to find out if a relevant binary is already in your search path. For example, the following command reveals that the GNU C compiler has already been installed on this machine:
If which can’t find the command you’re looking for, try whereis; it searches a broader range of system directories and is independent of your shell’s search path.
Another alternative is the incredibly useful locate command, which consults a precompiled index of the filesystem to locate filenames that match a particular pattern.
FreeBSD includes locate as part of the base system. In Linux, the current implementation of locate is in the mlocate package. On Red Hat and CentOS, install the mlocate package with yum; see this page.
locate can find any type of file; it is not specific to commands or packages. For example, if you weren’t sure where to find the signal.h include file, you could try
locate’s database is updated periodically by the updatedb command (in FreeBSD, locate.updatedb), which runs periodically out of cron. Therefore, the results of a locate don’t always reflect recent changes to the filesystem.
If you know the name of the package you’re looking for, you can also use your system’s packaging utilities to check directly for the package’s presence. For example, on a Red Hat system, the following command checks for the presence (and installed version) of the Python interpreter:
You can also find out which package a particular file belongs to:
Adding new software
If you do need to install additional software, you first need to determine the canonical name of the relevant software package. For example, you’d need to translate “I want to install locate” to “I need to install the mlocate package,” or translate “I need named” to “I have to install BIND.” A variety of system-specific indexes on the web can help with this, but Google is usually just as effective. For example, a search for “locate command” takes you directly to several relevant discussions.
The following examples show the installation of the tcpdump command on each of our example systems. tcpdump is a packet capture tool that lets you view the raw packets being sent to and from the system on the network.
Debian and Ubuntu use APT, the Debian Advanced Package Tool:
The Red Hat and CentOS version is
The package manager for FreeBSD is pkg.
Building software from source code
As an illustration, here’s how you build a version of tcpdump from the source code.
The first chore is to identify the code. Software maintainers sometimes keep an index of releases on the project’s web site that are downloadable as tarballs. For open source projects, you’re most likely to find the code in a Git repository.
The tcpdump source is kept on GitHub. Clone the repository in the /tmp directory, create a branch of the tagged version you want to build, then unpack, configure, build, and install it:
This configure/make/make install sequence is common to most software written in C and works on all UNIX and Linux systems. It’s always a good idea to check the package’s INSTALL or README file for specifics. You must have the development environment and any package-specific prerequisites installed. (In the case of tcpdump, libpcap and its libraries are prerequisites.)
You’ll often need to tweak the build configuration, so use ./configure --help to see the options available for each particular package. Another useful configure option is --prefix=directory, which lets you compile the software for installation somewhere other than /usr/local, which is usually the default.
Installing from a web script
Cross-platform software bundles increasingly offer an expedited installation process that’s driven by a shell script you download from the web with curl, fetch, or wget. These are all simple HTTP clients that download the contents of a URL to a local file or, optionally, print the contents to their standard output. For example, to set up a machine as a Salt client, you can run the following commands:
The bootstrap script investigates the local environment, then downloads, installs, and configures an appropriate version of the software. This type of installation is particularly common in cases where the process itself is somewhat complex, but the vendor is highly motivated to make things easy for users. (Another good example is RVM; see this page.)
This installation method is perfectly fine, but it raises a couple of issues that are worth mentioning. To begin with, it leaves no proper record of the installation for future reference. If your operating system offers a packagized version of the software, it’s usually preferable to install the package instead of running a web installer. Packages are easy to track, upgrade, and remove. (On the other hand, most OS-level packages are out of date. You probably won’t end up with the most current version of the software.)
See this page for details on HTTPS’s chain of trust.
Be very suspicious if the URL of the boot script is not secure (that is, it does not start with https:). Unsecured HTTP is trivial to hijack, and installation URLs are of particular interest to hackers because they know you’re likely to run, as root, whatever code comes back. By contrast, HTTPS validates the identity of the server through a cryptographic chain of trust. Not foolproof, but reliable enough.
A few vendors publicize an HTTP installation URL that automatically redirects to an HTTPS version. This is dumb and is in fact no more secure than straight-up HTTP. There’s nothing to prevent the initial HTTP exchange from being intercepted, so you might never reach the vendor’s redirect. However, the existence of such redirects does mean it’s worth trying your own substitution of https for http in insecure URLs. More often than not, it works just fine.
The shell accepts script text on its standard input, and this feature enables tidy, one-line installation procedures such as the following:
However, there’s a potential issue with this construction in that the root shell still runs even if curl outputs a partial script and then fails—say, because of a transient network glitch. The end result is unpredictable and potentially not good.
We are not aware of any documented cases of problems attributable to this cause. Nevertheless, it is a plausible failure mode. More to the point, piping the output of curl to a shell has entered the collective sysadmin unconscious as a prototypical rookie blunder, so if you must do it, at least keep it on the sly.
The fix is easy: just save the script to a temporary file, then run the script in a separate step after the download successfully completes.