Published on (
 See this if you're having trouble printing code examples

FreeBSD for Linux Users

by Dru Lavigne, author of BSD Hacks

Over the past year, I've had the opportunity to teach introductory Linux and BSD classes. Since BSD users primarily attended the Linux classes and the Linux users primarily attended the BSD classes, both groups had an interest in finding out more about their open source counterparts.

Students expected to find differences, but they often found the particulars surprising. Some of the commands they customarily used had different switches or were missing entirely, and certain features had totally different implementations.

In today's article, I'll cover some of the big-picture differences from the perspective of a Linux user being introduced to FreeBSD. In Part 2, I'll discuss command equivalents between Linux and FreeBSD.

SysV vs. BSD: Runlevels

Most introductory Unix courses start with the differences between SysV and BSD. Students, unimpressed by this fascinating bit of theoretical trivia, tend to jot down a few notes dutifully, and then wait patiently for the hands-on portion of the class. Within the hour, though, someone will make a panicked discovery and shout out, "Where are my runlevels?" There's an inevitable and incredulous follow-up of "What do you mean there aren't any runlevels?" and "Where'd all my startup scripts go?"

Herein lies one of the tangible design differences between a SysV system such as Linux and a BSD system. Both systems manage to start and run just fine--they just do it differently. It's equally difficult convincing a Linux user that a Unix administrator can achieve all of the functionality of runlevels without using runlevels as it is to convince a BSD user that it takes an entire subdirectory structure of symlinks to manage services.

Related Reading

BSD Hacks
100 Industrial Tip & Tools
By Dru Lavigne

While there are some variations in number, most Linux distros will provide runlevels representing shutdown, reboot, single user, multiuser with command line, and multiuser with GUI modes. The /etc/inittab describes these runlevels, and the telinit command allows administrators to tell the init process to change its current runlevel.

Editor's note: The commands described in the next paragraph work on every Linux system I can remember using.

A BSD system is also capable of each of these init states, though it does so without using the inittab file or the telinit command. To reboot, use reboot or shutdown -r. To halt the system, use halt or shutdown -h. To enter single-user mode on a running system, type shutdown now and press Enter when prompted to do so. To return to multiuser mode, type exit.

Whereas /etc/inittab sets the default runlevel on a Linux system, a BSD system uses /etc/ttys to determine whether the system will boot into multiuser command line or multiuser GUI. (Use the boot menu to select single-user mode at boot-up.) Like /etc/inittab, this file configures how many virtual terminals--those that accept keyboard input--to make available. The default configuration allows nine virtual terminals with the GUI residing on ttyv8 (accessible with Alt-F8). By default, the system boots into command-line mode and the user must type startx to start the GUI. However, if you miss having the system boot directly into a GUI login, edit /etc/ttys as the superuser and change the word off to on in the ttyv8 line.

Startup Scripts

On a Linux system, each runlevel has an associated subdirectory: rc0.d for runlevel 0, rc1.d for runlevel 1, and so on. Depending on the distribution, these subdirectories fall under either /etc or /etc/rc.d. Each subdirectory contains symlinks to startup scripts residing in /etc/init.d. The symlink names begin with either S (for start) or K (for kill) and tell init to act accordingly whenever the system enters that runlevel. After the letter comes a number that represents the order in which to run the scripts.

You won't find init.d or any of the runlevel subdirectories on a BSD system. Instead, the system startup scripts live in /etc/rc.d, and the startup scripts for third-party applications stay in /usr/local/etc/rc.d. Instead of using symbolic links beginning with S or K, a handful of scripts in /etc whose names start with rc control which scripts run at startup and shutdown. man rc gives the names of these scripts and describes their operation. As an admin, you'll leave most of those rc scripts as is. To configure which services start at boot-up, instead edit the one file /etc/rc.conf.

Most of the scripts found in Linux's /etc/init.d and BSD's /etc/rc.d share similar behavior. If you type only the script name, you'll receive a syntax message indicating which parameters you can send to that service. Here's an example from a FreeBSD 5.x system:

# /etc/rc.d/named
Usage: /etc/rc.d/named [fast|force] (start|stop|restart|rcvar|reload|status|poll)

You're probably unfamiliar with the rcvar parameter. It helps to determine the current /etc/rc.conf parameters of the service.

The Kernel

Instead of describing the design differences between a Linux and a FreeBSD kernel, I'll concentrate on the differences you'll encounter when recompiling a kernel.

The first thing you'll notice is the different method of numbering stable and unstable releases. Linux kernels use three numbers wherein:

To see which Linux kernel came with your distro, type uname -r.

In FreeBSD, the first number also refers to the major version number. As I write this, version 4 is the stable production release and version 5 is the new technology release. Both versions provide a development kernel known as CURRENT and various stable releases indicated by the second number. FreeBSD Release Engineering describes the release process in more detail.

The steps required to recompile a kernel also differ. Some Linux distros provide a mechanism to download Linux kernel source, or you can download it directly. After uncompressing the source, cd into your system's src directory and choose from one of three front ends available for modifying the kernel configuration file:

Each front end provides an explanation for each kernel configurable and allows you either to compile in that option statically or build it as a loadable module. Once you've saved your changes, use these commands to check for dependencies and to compile the kernel:

Editor's note: this is the process for a 2.4 kernel; the 2.6 kernel is simpler.

# make dep
# make clean
# make bzImage

If you've chosen to create modules, do these two commands next:

# make modules
# make modules_install

Finally, install the kernel and update your boot loader:

# make install

Always double-check the changes to your boot loader configuration file; I've found that make install doesn't always make the modifications required to boot successfully into the new kernel.

On a FreeBSD system, use /stand/sysinstall to download the kernel sources. Better yet, use cvsup to keep your kernel sources up to date.

Once you have the sources, make a copy of /usr/src/sys/i386/conf/GENERIC and use your favorite editor to prepend # (the comment character) to the options you don't want to configure into your kernel. Refer to a file called LINT or NOTES in that same directory to see what each option means and to research other options you may wish to add. Once you've saved your changes, compile and install the new kernel. In this example I've saved the file as NEWFILE. The commands are:

# cd /usr/src
# make buildkernel KERNCONF=NEWFILE
# make installkernel KERNCONF=NEWFILE

By default, this compiles all kernel options as modules. If you prefer to compile everything statically, include this line in your kernel configuration file:

makeoptions	MODULES_OVERRIDE=""

Installing Software

When it comes to installing software on an open source operating system, you usually have three choices available. The first is to install a precompiled binary. The advantage to this method is that it is very quick and usually painless, with the program and its dependencies recorded into a package management system. The disadvantage is that a precompiled binary may not be available for your particular operating system and architecture. If one is, keep in mind that it probably won't take advantage of your particular CPU's features and you will have no control over which features the distributor compiled into the binary. This usually isn't a big deal with desktop applications, but it can be for server applications.

Installing a precompiled binary in Linux depends upon which package management system came with your distro. Examples of popular package management system utilities are Red Hat's rpm, Debian's apt-get, and Gentoo's emerge. Some package management systems require you to find and download the binary and resolve dependency issues, while others fetch the binary and its dependencies for you.

Ease of use and syntax issues aside, having a package management system is always a good thing. It will maintain databases to keep track of which programs you have installed and which programs depend on which others. In theory, this should make it much easier to properly upgrade software without breaking dependencies and to monitor software for outstanding security patches. In reality, your mileage will vary with the package management system used, but it will still be much better than trying to remember what you installed and when.

FreeBSD provides a robust package management system. To install a precompiled binary in FreeBSD, use the pkg_add command with the remote fetch switch. For example, to install curl, type:

# pkg_add -r curl

If there are any missing dependencies available as a precompiled binary, the command will also download and install them for you.

If you prefer to select packages from an ncurses menu, use /stand/sysinstall and choose Configure, then Packages.

The second method for installing software is to compile the binary yourself using your system's package management system. This will track the program itself and all of its dependencies; you also have a pretty good guarantee that the compile should succeed for your CPU and operating system type. Compiling your own binary allows you to take advantage of the program's make options. The assumption is that you've taken the time to research the available options for the particular application you wish to compile. The disadvantage is that it takes time to compile a binary, depending on the size of the binary and how much CPU and RAM is on the compiling system.

As an example, if your distro supports RPMs, you can download and compile a source RPM. These end in src.rpm as opposed to something like i386.rpm. In FreeBSD, you instead use the ports collection. For example, to install Apache:

# cd /usr/ports/www/apache13
# make install clean

Of course, before issuing the make command, experienced admins read the Makefile in that directory to see which options to use for that compile.

The third method is to download and extract a source tarball. This method works on any Unix system but comes with a big disadvantage: the package management system in place usually cannot track the installed files. This means you have to remember what you installed, when you installed it, and what dependencies come with or rely on that program. It will also be very difficult to keep those programs up to date and to remember to check for security fixes on each program.

Sometimes this third method is a necessary evil. Perhaps you need to take advantage of a feature or security fix now and there currently isn't a precompiled binary or source RPM/port for that application for your operating system. Unless you really can't wait, however, you're better off waiting.


One of the biggest improvements to open source operating systems over the past few years has been the proliferation of quality online documentation. Linux has The Linux Documentation Project. While everything here obviously comes from the Linux perspective, many of the articles concern third-party shells or software that apply well to non-Linux systems.

FreeBSD has the FreeBSD Handbook and FreeBSD FAQ. These and other documentation resources also appear on FreeBSD systems in /usr/share/doc. Use cvsup to update them. The documentation describes pretty much anything you could ever want to do with a FreeBSD system.

One of the more noticeable differences between Linux distros and BSD systems is the quality of the man pages. An example that comes up in a Linux+ class is the man page for ls. For the exam, students need to know the -F. Here's the explanation from man ls on a Linux system:

-F, --classify
              append indicator (one of */=@|) to entries

Here's the explanation from a BSD system:

-F      Display a slash (`/') immediately after each pathname that is a
      directory, an asterisk (`*') after each that is executable, an at
      sign (`@') after each symbolic link, an equals sign (`=') after
      each socket, a percent sign (`%') after each whiteout, and a ver-
      tical bar (`|') after each that is a FIFO.

One of the lessons students learn is that if you don't find the information you want from a man page, see if there is a better man page! I've always had good luck with FreeBSD Hypertext Man Pages.

The other man page that students find helpful is man hier, as it describes the file system hierarchy or directory structure layout. This is always a good command to run whenever you find an unfamiliar Unix operating system.

In the next article, I'll move on to particular commands that differ between Linux and FreeBSD.

Dru Lavigne is a network and systems administrator, IT instructor, author and international speaker. She has over a decade of experience administering and teaching Netware, Microsoft, Cisco, Checkpoint, SCO, Solaris, Linux, and BSD systems. A prolific author, she pens the popular FreeBSD Basics column for O'Reilly and is author of BSD Hacks and The Best of FreeBSD Basics.

Return to the BSD DevCenter.

Copyright © 2009 O'Reilly Media, Inc.