When the system starts, it goes through a number of phases.
The first one is your early boot phase, which is rather hardware-dependent, and involves getting your Linux kernel started.
This, on most Linux systems, involves using so-called GRUB, which lets you choose alternative operating systems, kernel options, et cetera, when you start.
And on embedded systems, you'll do something else, such as Das U-Boot.
The next phase has to do with actual initialization of various system services, and that's really a question of system administration, rather than early boot.
The second thing we want to talk about is memory.
We want to talk about how your system uses memory and what it does when it runs out of memory and has to use so-called swap space.
At this point, you may find your OOM killer, Out of Memory killer, invoked, which decides how to deal with things when you've run out of memory.
The third thing we want to talk about is network and network devices.
We want to talk about how you can enable network devices, make sure they go up or go down as needed, and how they are named.
All x86-based physical Linux systems, that includes laptops, most workstations, et cetera, use a software system called GRUB, which stands for GRand Unified Bootloader, that handles the earliest phases of the system startup.
This is not true when you get to embedded devices, such as set-top boxes, medical devices et cetera. They use other platforms, such as Das U-Boot in order to start.
Now, GRUB has a number of important features, you can boot into alternative operating systems, make your choice at boot time. This is called a Bootloader.
So, you might have a computer that has Windows on it, it has more than one Linux distribution on it, it might have Red Hat, it might have Ubuntu, it might have Debian, et cetera. So, you can choose among those when you start
Within a given operating system, you can make choices as to which kernel you want to start with, or you can use different initial ramdisk or you can specify different options that the system should start with.
Furthermore, if you want, you can change things when the system starts by entering an interactive system that lets you change the options and other variables with which the system starts, and you don't have to actually change configuration files on the machine.
To do this, you can do it on the fly. Now, GRUB has been through a number of versions, almost all modern distributions use these days GRUB 2, which is quite different from GRUB 1.
In GRUB 2, there's really only one configuration file in the boot directory that counts and that's called "grub.cfg".
Exactly where it is will depend a little on your kind of system, both in terms of your distribution and your hardware, but it will be there someplace.
Generally, this is not a file you edit by hand, it's a file that's generated for you when you are configuring the system, or installing a new kernel, or compiling a new kernel, et cetera. There's a couple of other directories on our system that matter.
Under "/etc/grub.d", there's a number of files that control how GRUB works, and under "/etc/default", there's a file named "grub", which contains basic parameters that GRUB needs.
These files can be edited by hand and they're used to generate "grub.cfg". So, when the system boots, it begins with the so-called BIOS space, basic input-output system, or CMOS, identifying, initializing the most important system and attach peripheral devices, such as input like a keyboard and initial hard-disk, so that you can actually load the kernel.
You can make choices in the BIOS about booting off a peripheral device, maybe a USB drive, for instance.
Older systems have what's called the Master Boot Record, that contains both the partition table and the bootloader, which is part of GRUB that loads the actual operating system.
The kernel itself can have different names, usually it's "vmlinuz", and then appended with a version number. The "z" indicates that the kernel is compressed, as it loads it decompresses itself.
A /boot directory might look like the one in the screenshot below:
In this example, there are multiple possible kernels to boot into, each of which has four files associated with it:
vmlinuz is the compressed kernel
initramfs contains a complete initial root filesystem which is loaded as a ramdisk, as well as some essential kernel modules (generally, device drivers) and the programs needed to load them, that are required to load the real filesystem, at which point it is discarded
configcontains all the details about how the kernel was compiled; it is not needed for system operation
System.map lists the complete kernel symbol table; it is used only for debugging purposes
Depending on which Linux distribution is being used, there will be variations in the above possible kernels. For example, the initramfs file may actually be called initrd.
The first program which runs on the system is called init.
Generally, it has a process ID of 1, later processes have higher process IDs. Traditionally, this was considered the parent of everything that follows.
Though technically, that's not really true, some processes are started directly by the kernel, rather than being the children.
Indeed, it has a lot of tasks besides configuring the later stages of booting. It configures all aspects of the environment.
It starts all the processes needed for logging into the system and keeping track of things, and it also keeps track of what happens when something terminates to make sure it does it as cleanly as possible.
Historically, all distributions were based on what's called System V init that goes back to early Unix days.
The basic idea was that you went through a sequence of steps as a system started up.
Each step required a completion of the earlier step, until you reached a fully operational step, probably with a complete graphical environment of its own workstation or laptop.
Now, the original target of course was multi-user mainframe systems, and not personal computers or laptops, or the other kinds of systems we have today, and it was only done on a single processor.
One was not that concerned with how often a system was started and shut down, and how long it took was not that important.
It was more important just to get things right.
However, today that's no longer the case. How long it takes to start up is rather important, and we need to take advantage of features of modern systems, such as multiple processors which enable more than one thing to be done at once, instead of just having a serial process.
Upstart was developed by Ubuntu and was first deployed in 2006, and this was an improvement over the earlier methods. Systemd came later. It was first adopted by a major distribution in 2011.
Both these methods take advantage of multiple CPUs and being able to do many things at once. Nowadays, all major distributions have moved to Systemd. Upstart is now considered obsolete and Systemd has been phased out in major distributions.
So, while some of its language still survives, such as runlevel, everything on modern distributions is systemd-based, and so we will concentrate on that.
The only important command there for day-to-day use is "systemctl", which we will see how its used a number of different ways as we continue.
In a SystemV init system, there are different runlevels that run from 0 to 6.
A full graphical system is considered runlevel 5. Runlevel 1 is single user mode or emergency mode, and it's for special purposes, where you have only one user there to repair a system for instance.
Runlevel | Meaning |
---|---|
S, s | Same as 1 |
0 | Shutdown system and turn power off |
1 | Single user mode |
2 | Multiple user, no NFS, only text login |
3 | Multiple user, with NFS and network, only text login |
4 | Not used |
5 | Multiple user, with NFS and network, graphical login with X |
6 | Reboot |
The current runlevel can be simply displayed with the runlevel command, as in:
$ runlevel
N5
where the first character is the previous level; N means unknown.
telinit can be used to change the runlevel of the system. For example, to go from runlevel 3 to runlevel 5, type:
$ sudo /sbin/telinit 5
When the init process is started, the first thing it does is to read /etc/inittab. Historically, this file told init which scripts to run to bring the system up each runlevel, and was done with a series of lines, one for each runlevel:
id:runlevel(s):action:process
where:
id: a unique 1-4 character identification for the entry
runlevel(s): zero or more single character or digit identifiers which identify which runlevel the action will be taken for
action: describes the action to be taken
process: specifies the process to be executed.
However, in more recent systems, the only un-commented line and the only thing being set in this file is the default runlevel with the line:
id:5:initdefault
This is the level to stop at when booting the system. However, if another value is specified on the kernel command line, init ignores the default. This is done by simply appending the right integer to the kernel command line. The default level is usually 5 for a full multi-user, networked graphical system, or 3 for a server without a graphical interface.
systemd-based systems do not use /etc/inittab at all, and just contain a file with no uncommented content, so as to not break outdated scripts. However, some distributions still maintain the notion of runlevels, which are defined in terms of systemd targets, and so you can use commands like the telinit one described earlier.