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.
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.
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
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
shutdown -r. To halt
the system, use
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
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
on in the
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
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
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
K, a handful of scripts in /etc whose
names start with
rc control which scripts run at startup and
man rc gives the names of these scripts and describes
their operation. As an admin, you'll leave most of those
scripts as is. To configure which services start at boot-up, instead edit the
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.
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
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:
make configis a text-based series of many, many questions.
make menuconfigprovides an
ncursesmenu from the command line.
make xconfigprovides a menu from an X session.
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
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,
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
# (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:
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
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
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
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
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
-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
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.