Alchemist.Digital

// Jeffrey Reeves

Part 5 – Booting Linux and Editing Files

October 22, 2017

Booting Linux and Editing Files

Exam Objectives

  • 101.2 – Boot the system
  • 101.3 – Change runlevels and shutdown or reboot system
  • 102.2 – Install a boot manager
  • 103.8 – Perform basic file editing operations using vi

Installing Boot Loaders

The machine’s boot process begins with a program called a boot loader.

Boot loaders work in different ways depending on the firmware used and the OS being booted.

The most used boot loader for Linux is the Grand Unified Boot Loader (GRUB).

GRUB is available in two versions:

  1. GRUB Legacy (versions 0 – 0.97)
  2. GRUB 2 (versions 1.9x – 2.xx)

An older Linux boot loader also exists, called the Linux Loader (LILO).

Boot Loader Principles

The computer’s firmware reads the boot loader into memory from the hard disk and executes it.

The boot loader is responsible for loading the Linux kernel into memory and starting it.

Note: Although the exam objectives only mention the Basic Input/Output System (BIOS) firmware, the Extensible Firmware Interface (EFI) and Unified EFI (UEFI) are becoming increasingly important.

BIOS Boot Loader Principles

The BIOS boot process varies depending on its many options.

The BIOS first selects a boot device to use (hard disk, USB stick, etc.).

If a hard disk is selected, the BIOS loads code from the Master Boot Record (MBR).

The MBR is located within the first sector (512 bytes) of a hard disk. This 512 bytes is broken up into:

  • Bootloader assembly code – 446 bytes.
  • Partition table for four (4) primary partitions – 64 bytes (16 bytes each).
  • Sentinel value – 2 bytes (with a value of 0xAA55 if bootable).

The MBR contains the primary boot loader code.

The primary boot loader does one of two things:

  1. Examines the partition table, locates the partition that’s marked as bootable, and loads the boot sector from that partition to execute it. 
  2. Locates an OS kernel, loads it, and executes it directly.

In the first instance, the boot sector contains a secondary boot loader, which ultimately locates an OS kernel to load and execute.

Linux’s most popular BIOS boot loaders (LILO and GRUB) can be installed in either the MBR or the boot sector of a boot partition.

Windows systems come with a boot loader that is installed directly to the MBR.

Note: Installing Windows alongside a Linux system will result in replacement of the MBR-based boot loader. To reactivate the Linux boot loader, Windows’ FDISK utility can be used to mark the Linux partition as the boot partition.

On an MBR partitioning system, a primary partition must be used for storing a Linux partition’s boot sector. If the boot sector is located within a logical partition it can only be accessed via a separate boot loader in the MBR or a primary partition.

On disks that use the GUID Partition Table (GPT) partitioning system, GRUB stores part of itself within a special partition, known as the BIOS boot partition. On MBR disks, the equivalent code is stored in the sectors immediately following the MBR (which are officially unallocated in the MBR scheme).

Note: Occasionally a reference is made to the “superblock” when discussing BIOS boot loaders. The superblock is part of the filesystem; and describes basic filesystem features, such as the filesystem’s size and status. On BIOS-based computers, the superblock may hold a portion of the boot loader, and damage to it can cause boot problems. The debugfs and dump2efs commands can provide some superblock information.

EFI Boot Loader Principles

EFI is much more complex than the older BIOS.

Instead of relying on code stored within the boot sectors of a hard disk, EFI relies on boot loaders stored as files in a disk partition known as the EFI System Partition (ESP) — which uses the File Allocation Table (FAT) filesystem.

Within Linux, the ESP is typically mounted at /boot/efi.

Inside of /boot/efi/EFI are subdirectories named after the OS or boot loader being used (ex. ubuntu, suse, fedora, etc.).

Those subdirectories contain boot loaders as .efi files.
For example, /boot/efi/EFI/ubuntu/grub.efi or /boot/efi/EFI/suse/elilo.efi.

This configuration allows the option to store a separate boot loader for each OS that is installed on the machine.

EFI includes a boot manager to help select which boot loader to launch.

Note: The exam objectives use the terms boot loader and boot manager interchangeably. A boot loader loads a kernel into memory and passes control to it. A boot manager presents a menu of boot options. GRUB (and other programs) combine both functions, which may be the reason why many sources don’t differentiate between the two terms.

Boot loaders must be registered in order for EFI to use them. This can be done by either using a utility built into the firmware’s own user interface or by using a tool such as Linux’s efibootmgr program.

Most x86-64 EFI implementations will use a boot loader called EFI/boot/bootx64.efi on the ESP as a default if no others are registered. Removable disks typically store their boot loader using this name as well.

GRUB Legacy

GRUB is the default boot loader for most Linux distributions.

Configuring GRUB Legacy

/boot/grub/menu.lst is the usual location for GRUB Legacy’s configuration file on a BIOS-based computer.

Some distributions (ex. Fedora, Red Hat, and Gentoo) use the filename grub.conf in place of menu.lst

The GRUB configuration file can be broken into global and per-image sections.

Note: GRUB Legacy officially supports BIOS but not EFI. A heavily patched version, maintained by Fedora, provides support for EFI. If using this version of GRUB, its configuration file is located in the same directory on the ESP that houses the GRUB Legacy binary, such as /boot/efi/EFI/redhat for a standard Fedora or Red Hat installation.

GRUB Nomenclature and Quirks

The following is an example GRUB configuration file:

# grub.conf/ menu.lst
#
# Global Options:
#
default=0
timeout=15
splashimage=/grub/bootimage.xpm.gz
#
# Kernel Image Options:
#
title Fedora (3.4.1)
    root (hd0,0)
    kernel /vmlinuz-3.4.1 ro root=/dev/sda5 mem=4096M
    initrd /initrd-3.4.1
title Debian (3.4.2-experimental)
    root (hd0,0)
    kernel (hd0,0)/bzImage-3.4.2-experimental ro root=/dev/sda6
#
# Other operating systems
#
title Windows
    rootnoverify (hd0,1)
    chainloader +1

In the above example, Fedora exists on /dev/sda5, Debian exists on /dev/sda6, and Windows exists on /dev/sda2. Debian and Fedora share a /boot partition on /dev/sda1, where the GRUB configuration resides.

GRUB doesn’t refer to disk drives by device filename the way Linux does. Instead, GRUB numbers drives (i.e. /dev/hda or /dev/sda becomes (hd0), and /dev/hdb or /dev/sdb becomes (hd1)).

Note: GRUB also doesn’t distinguish between PATA, SATA, SCSI, and USB drives. On mixed systems, ATA drives are typically given the lowest drive numbers, but that is not guaranteed.

GRUB Legacy’s drive mappings can be found in the /boot/grub/device.map file.

GRUB Legacy separates partition numbers from drive numbers with a comma. For example, (hd0,0) for the first partition of the first hard disk (typically /dev/sda1 or /dev/hda1 in Linux), and (hd0,4) for the first logical partition of the first hard disk (normally /dev/sda5 or /dev/hda5).

Global GRUB Legacy Options

GRUB’s global section precedes its per-image configurations.

Common options in the global section:

Feature Option Description
Default OS default=<num> Specifies a default OS for GRUB to boot.

Note: Index starts at 0. 

Timeout

timeout=<seconds>

The seconds GRUB will wait for user input before booting the default OS.
Background Graphic

splashimage=<file>

Sets the <file> as the background graphic.

Note: The file and path are relative to the GRUB root partition. If /boot is on a separate partition, that portion of the path is omitted. The path may also begin with a GRUB device specification instead (ex. (hd0,5), to refer to a file on that partition.

Global GRUB Legacy Per-Image Options

By convention, GRUB Legacy’s per-image options are often indented after the first line.

The options start with an identification followed by options that tell GRUB how to handle the image.

Common options in the per-image section:

Feature Option Description
Title title <label> The label to display on the boot loader menu.

<label> can accept spaces.

GRUB Root root <drive-nums> The location of GRUB Legacy’s root partition — which is the /boot partition if a separate partition is made for it.

ex. root (hd0,0)

Kernel Specification kernel <path> <options>

The location of the Linux kernel, and any kernel options to be passed to it.

The <path> is relative to GRUB Legacy’s root partition. Alternatively, GRUB drive number syntax can be used (ex. kernel (hd0,2)/vmlinux ro root=/dev/sda2)

Note: Because the <options> are being passed to the Linux kernel, the root option listed must refer to a Linux-style device identifier.

Initial RAM Disk initrd <path> The <path> specifies the location of the initial RAM disk — which holds a minimal set of drivers, utilities, and configuration files that the kernel uses to mount its root filesystem before the kernel can fully access the hard disk.

Note: <path> is relative to GRUB Legacy’s root partition.

Non-Linux Root rootnoverify <drive-nums> Similar to the root option, but GRUB Legacy will not try to access files on this partition.

This option is used to specify a boot partition for operating systems that GRUB Legacy can’t directly load a kernel for, such as Windows.

ex. rootnoverify (hd0,1)

Chainloading chainloader +<sector-num> Tells GRUB Legacy to pass control to another boot loader.

The <sector-num> defines the sector of the target OS’s root partition (which is usually specified with rootnoverify).

Note: Chainloading on an EFI-enabled version of GRUB Legacy requires specifying the ESP as the root (typically root (hd0,0)), and passing the name of an EFI boot loader file (ex. chainloader /EFI/Microsoft/boot/bootmgfw.efi).

To add a kernel to GRUB:

  1. As root, open menu.lst or grub.conf in a text editor.
  2. Copy a working configuration for a Linux kernel.
  3. Modify the title line with a unique name.
  4. Modify the kernel line to point to the new kernel, and specify any kernel options.
  5. Make appropriate changes to the initrd line (if adding, deleting, or changing an initramfs RAM disk).
  6. Change the global default line to point to the new kernel (if desired).
  7. Save changes and exit the text editor.

New kernel options in GRUB will appear in the menu after a reboot.

Installing GRUB Legacy

To install GRUB Legacy on a BIOS-based machine: 
grub-install <device>

To install GRUB Legacy into the MBR (first sector of the first hard drive), <device> can be set with either a Linux or GRUB style device identifier (/dev/sda or '(hd0)').

To install GRUB Legacy into the boot sector of a partition instead, a partition identifier must be included with either the Linux or GRUB style device identifier (ex. /dev/sda1 or (hd0,0)).

To install Fedora’s EFI-enabled version of GRUB Legacy, copy the grub.efi file to a suitable directory in your ESP (ex. /boot/efi/EFI/redhat), copy grub.conf to the same location, and run the efibootmgr utility to add the boot loader to the EFI’s list:

# efibootmgr -c -l [[backslash backslash]]EFI[[backslash backslash]]redhat[[backslash backslash]]grub.efi -L GRUB

The above command adds GRUB Legacy, stored in the ESP’s /EFI/redhat directory, to the EFI’s boot loader list. Double backslashes ([[backslash backslash]]) must be used instead of Linux style forward slashes (/). 

Note: If using Fedora’s grub-efi RPM file, the grub.efi file should be placed in this location by default.

Interacting with GRUB Legacy

GRUB Legacy will show a list of all of the operating systems that were specified with the title option in the GRUB configuration file.

If the timeout expires, a default operating system will be booted.

To select an alternative to the default, use the arrow keys to highlight the operating system desired and press the Enter key.

To pass additional options to an operating system:

  1. Use the arrow keys to highlight the operating system.
  2. Press e to edit the entry.
  3. Use the arrow keys to highlight the kernel option line.
  4. Press e to edit the kernel options.
  5. Edit the kernel line to add any options (such as 1 to boot to single-user mode)2. GRUB Legacy passes the extra option to the kernel.
  6. Press Enter to complete the edits.
  7. Press b to start booting.

Note: Any changes can be made during step 5. For example, if a different init program is desired, it can be changed by appending init=<program> (ex. init=/bin/bash) to the end of the kernel line.

Note2: To get to single-user mode when booting Linux, 1, S, s, or single can be passed as an option to the kernel by the boot loader.

GRUB 2

The GRUB 2 configuration file is /boot/grub/grub.cfg.

Note: Some distributions place the file in /boot/grub2 to allow simultaneous installations of GRUB Legacy and GRUB 2.

GRUB 2 adds features, such as:

  • Support for loadable modules for specific filesystems and modes of operation.
  • Conditional logic statements (enabling loading modules or displaying menu entries only if particular conditions are met).

The following is a GRUB 2 configuration file based on the previous example:

# grub.cfg 
#
# Kernel Image Options:
#
menuentry "Fedora (3.4.1)" { 
    set root=(hd0,1)
    linux /vmlinuz-3.4.1 ro root=/dev/sda5 mem=4096M
    initrd /initrd-3.4.1
}

menuentry "Debian (3.4.2-experimental)" { 
    set root=(h0,1)
    linux (hd0,1)/bzImage-3.4.2-experimental ro root=/dev/sda6
}

#
# Other operating systems
#
menuentry "Windows" { 
    set root=(hd0,2)
    chainloader +1
}

Compared to GRUB Legacy, the important changes are:

  • title changed to menuentry.
  • Menu titles are enclosed in quotes.
  • Each entry has its options enclosed in curly braces ({}).
  • set is added before the root keyword, and an = is needed to assign the root value to the partition specified.
  • rootnoverify has been eliminated, root is used instead.
  • Partition numbers start from 1 rather than 0. However, a similar change is not implemented for disk numbers.

Note: GRUB 2 also supports a more complex partition identification scheme to specify the partition table type (ex. (hd0,gpt2) for the second GPT partition, or (hd1,mbr3) for the third MBR partition).

GRUB 2 makes use of a set of scripts and other tools to help automatically maintain the /boot/grub/grub.cfg file.

Rather than edit the grub.cfg file manually, files in /etc/grub.d/ and the /etc/default/grub file should be edited. After making changes, the grub.cfg file should be recreated explicitly with one of the following (depending on OS):

update-grub > /boot/grub/grub.cfg
grub-mkconfig > /boot/grub/grub.cfg

grub2-mkconfig > /boot/grub/grub.cfg

Note: The update-grub, grub-mkconfig, and grub2-mkconfig scripts all output directly to STDOUT, which is why their output must be redirected to the /boot/grub/grub.cfg file manually.

Files in /etc/grub.d/ control particular GRUB OS probers. These scripts scan the system for particular operating systems and kernel, and add GRUB entries to /boot/grub/grub.cfg to support them. 

Custom kernel entries can be added to the 40_custom file — enabling support for locally compiled kernels or unusual operating systems that GRUB doesn’t automatically detect.

The /etc/default/grub file controls the defaults created by the GRUB 2 configuration scripts.

To adjust the timeout:
GRUB_TIMEOUT=30

Note: A distribution designed to use GRUB 2, such as Ubuntu, will automatically run the configuration scripts after certain actions (ex. installation of a new kernel via the distribution’s package manager).

GRUB 2 is designed to work with both BIOS and EFI based machines.

Similar to GRUB Legacy, grub-install is run after Linux is installed to set up GRUB correctly.

Note: On EFI-based machines, the GRUB 2 EFI binary file should be placed appropriately automatically. However, if there are problems, efibootmgr can be used to fix them.

Alternative Boot Loaders

Although GRUB Legacy and GRUB 2 are the most dominant boot loaders for Linux (and the only ones covered on the exam), several other boot loaders are available:

Syslinux

The Syslinux Project (http://www.syslinux.org/) is a family of BIOS-based boot loaders, each of which is much smaller and more specialized than GRUB Legacy and GRUB 2.

The most notable member of this family is ISOLINUX, which is a boot loader for use on optical discs (which have unique boot requirements). 

The EXTLINUX boot loader is another member of this family. It can boot Linux from an ex2, ext3, or ext4 filesystem.

LILO

The Linux Loader was the most common Linux boot loader in the 90s.

It works only on BIOS-based machines, and is quite limited and primitive by today’s standards.

If a Linux system uses LILO it will have a /etc/lilo.conf configuration file present on the system.

The Linux Kernel

Since version 3.3.0, the Linux kernel itself has incorporated an EFI boot loader for x86 and x86-64 systems.

On an EFI-based machine, this feature enables the kernel to serve as its own boot loader, eliminating the need for a separate tool such as GRUB 2 or ELILO.

rEFIt

Technically a boot manager, and not a boot loader.

It presents an attractive graphical interface, which allows users to select operating systems using icons rather than text.

It’s popular on Intel-based Macs, but some builds can be used on UEFI-based PCs as well. 

This program can be found at http://refit.sourceforge.net/, but has been abandoned since development stopped in 2010.

rEFInd

A fork of rEFIt, designed to be more useful on UEFI-based PCs with extended features.

It also provides features that are designed to work with the Linux kernel’s built-in EFI boot loader, to make it easier to pass options required to get the kernel to boot.

The homepage for the project is http://www.rodsbooks.com/refind/.

gummiboot

An open-source EFI boot manager that’s similar to rEFIt and rEFInd, but uses a text-mode interface with fewer options.

The project page is http://freedesktop.org/wiki/Software/gummiboot.

Secure Boot

Microsoft requires the use of a firmware feature called Secure Boot, which has an impact on Linux boot loaders.

With Secure Boot enabled, an EFI-based machine will launch a boot loader only if it has been cryptographically signed by a key whose counterpart is stored in the computer’s firmware.

The goal of Secure Boot is to make it harder for malware authors to take over a computer by placing malware programs early in the boot process.

The problem for Linux is use of Secure Boot requires one of the following:

  • The signing of a Linux boot loader with Microsoft’s key (since it’s the only one guaranteed to be on most machines).
  • The addition of a distribution-specific or locally generated key to the machine’s firmware.
  • The disabling of Secure Boot.

Currently, both Fedora and Ubuntu can use Secure Boot.

Note: It may be necessary to generate a key, or disable Secure Boot, to boot an arbitrary Linux distribution or a custom-built kernel.

The Boot Process

Extracting Information About the Boot Process

The kernel ring buffer stores some Linux kernel and module log information in memory.

Linux displays messages destined for the kernel ring buffer during the boot sequence (those messages that scroll by way too fast to be read).

To inspect the information in the kernel ring buffer:

# dmesg

Note: Many Linux distributions store the kernel ring buffer in /var/log/dmesg after the system boots.

Another important source for logging information is the system logger (syslogd), which stores log files in /var/log.

Some of the most important syslogd files are:

  • /var/log/messages
  • /var/log/syslog

Note: Some Linux distributions also log boot-time information to other files. Debian uses a daemon called bootlogd that logs any messages that go to /dev/console to the /var/log/boot file. Fedora and Red Hat use syslogd services to log information to /var/log/boot.log.

The Boot Process

The boot process of an x86 machine from its initial state to a working operating system is:

  1. The system is powered on, and a special hardware circuit causes the CPU to look at a predefined address and execute the code stored in that location — which is the firmware (BIOS or EFI).
  2. The firmware checks hardware, configures it, and looks for a boot loader.
  3. When the boot loader takes over, it loads a kernel or chainloads another boot loader.
  4. Once the Linux kernel takes over, it initializes devices, mounts the root partition, and executes the initial program for the system — giving it a process ID (PID) of 1. By default, the initial program is /sbin/init.

Loading Kernels and initramfs

When the kernel is being loaded it needs to load drivers to handle the hardware, but those drivers may not yet be accessible if the hard drive isn’t mounted yet.

To avoid this issue, most Linux distributions utilize an initramfs file — which contains the necessary modules to access the hardware.

The boot loader mounts the initramfs file into memory as a virtual root filesystem for the kernel to use during boot.

Once the kernel loads the necessary drivers, it unmounts the initramfs filesystem and mounts the real root filesystem from the hard drive.

The Initialization Process

The first program that is started on a Linux machine (init) is responsible for starting the initialization process.

The initialization process is ultimately responsible for starting all programs and services that a Linux system needs to provide for the system.

There are three popular initialization process methods used in Linux:

  • Unix System V (SysV)
  • Upstart
  • systemd

The original Linux init program was based on the Unix System V init program, and became commonly referred to as SysV.

The SysV init program uses a series of shell scripts, divided into separate runlevels, to determine what programs should run at what times.

Each program uses a separate shell script to start and stop the program.

The system administrator sets the runlevel at which the Linux system starts, which in turn determines which set of programs to run.

The system administrator can also change the runlevel at any time while the system is running.

The Upstart version of the init program was developed as part of the Ubuntu distribution.

Upstart uses separate configuration files for each service, and each service configuration file sets the runlevel in which the service should start.

This method makes it so that there is just one service file that’s used for multiple runlevels.

The systemd program was developed by Red Hat, and also uses separate configuration files.

Using the SysV Initialization Process

The key to SysV’s initialization process is runlevels.

The init program determines which service to start based on the current runlevel of the system.

Runlevel Functions

Runlevels are numbered from 0 to 6, and each one is assigned a set of services that should be active for that runlevel.

Note: While most systems only allow runlevels 0 to 6, some systems may have more. The /etc/inittab file will define all runlevels on a system.

Runlevels 0, 1, and 6 are reserved for special purposes; and the remaining runlevels can be used for whatever purposes the Linux distribution decides:

Runlevel Description
0 Shuts down the system.
1 (s, S, single) Single-user mode.
2 Multi-user mode on Debian (and derivatives).
Graphical login screen with X running.

Most other distributions do not define anything for this runlevel.

3 Multi-user mode on Red Hat, Fedora, Mandriva, etc.
Non-graphical (console) login screen.
4 Undefined typically, and available for customization.
5 Multi-user mode on Red Hat, Fedora, Mandriva, etc.
Graphical login screen with X running.
6 Reboots the system.

Identifying the Services in a Runlevel

One way to affect what programs run when entering a new SysV runlevel is to add or delete entries in the /etc/inittab file.

Basics of the /etc/inittab File

The entries within the /etc/inittab file follow a simple format.

Each line consists of four colon-delimited fields:

<id>:<runlevels>:<action>:<process>

Field Description
Identification Code The <id> field consists of a sequence of one to four characters that identifies its function.
Applicable Runlevels The <runlevels> field consists of a list of runlevels that applies for this entry (ex. 345 would apply to runlevels 3, 4, and 5).
Action to Take

Specific codes in the <action> field tell init how to treat the process.

See man inittab for details on the available codes.

Example codes:

wait tells init to start the process once when entering the runlevel and to wait for the process’s termination.

respawn tells init to restart the process whenever it terminates.

Process to Run

The <process> field is the process to be run on this entry, including any options / arguments that are required.

Note: This field is omitted when using the initdefault action.

The part of /etc/inittab that tells init how to handle each runlevel looks like:

l0:0:wait:/etc/init.d/rc 0
l1:0:wait:/etc/init.d/rc 1
l2:0:wait:/etc/init.d/rc 2
l3:0:wait:/etc/init.d/rc 3
l4:0:wait:/etc/init.d/rc 4
l5:0:wait:/etc/init.d/rc 5
l6:0:wait:/etc/init.d/rc 6

Each line begins with the letter l, followed by the runlevel number.

These lines specify scripts or programs that are to be run when the specific runlevel is entered.

In the above example, all scripts are the same (/etc/init.d/rc), but some distributions call specific programs for certain runlevels, such as shutdown for runlevel 0.

The SysV Startup Scripts

The /etc/init.d/rc or /etc/rc.d/rc script performs the crucial task of running all the scripts associated with the runlevel.

The runlevel-specific scripts are stored in one of the following locations:

  • /etc/init.d/rc?.d/
  • /etc/rc.d/rc?.d/
  • /etc/rc?.d/

The ? represents the runlevel number.

When entering a runlevel, rc passes the start parameter to all of the scripts with names that begin with a capital S, and it passes the stop parameter to all of the scripts with names that begin with a capital K.

These scripts are also numbered (ex. S10network, K35smb), and rc executes the scripts in numeric order — allowing distributions to control the order in which scripts run.

The files in the SysV runlevel directories are actually symbolic links to the main scripts, which are typically stored in one of the following locations:

  • /etc/init.d/
  • /etc/rc.d/
  • /etc/rc.d/init.d/

These original SysV startup scripts do not have the leading S or K and number (ex. smb instead of K35smb).

Note: Services can also be started and stopped by hand. For example, /etc/init.d/smb start will start the Samba server, and /etc/init.d/smb stop will stop the Samba server. Other options such as restart and status can be used as well.

Managing Runlevel Services

The SysV startup scripts in the runlevel directories are symbolic links back to the original script.

This prevents the need to copy the same script into each runlevel directory, and allows the user to modify the original script in just one location.

By editing the link filenames, a user can modify which programs are active in a runlevel.

Various utilities are available to help manage these links:

  • chkconfig
  • update-rc.d
  • rc-update
chkconfig

To list the services and their applicable runlevels:

# chkconfig --list

The output will show each service’s runlevels with either an on or off state for each runlevel.

To check a specific service:

# chkconfig --list <service-name>

To modify the runlevels of a service:

# chkconfig --level <numbers> <service-name> <state>

<numbers> is the runlevels desired.

<state> is either onoff, or reset — which sets the value to its default value.

If a new startup script has been added to the main SysV startup script directory, chkconfig can be used to inspect the startup script for special comments that indicate default runlevels, and then add appropriate start and stop links in the runlevel directories:

# chkconfig --add <service-name>

Checking and Changing the Default Runlevel

On a SysV-based system, the default runlevel can be found by inspecting the /etc/inittab file and looking for initdefault.

An easy way to do this is with:

# grep :initdefault: /etc/inittab
id:3:initdefault:

To change the default runlevel for the next boot, edit the initdefault line in /etc/inittab.

Note: If a system lacks an /etc/inittab file, one can be created manually that only has an initdefault line to specify the desired default runlevel.

Determining the Current Runlevel

On a running system, the current runlevel can be found with:

# runlevel

The output will display either a number representing the system’s previous runlevel (ex. 5), or the letter N if no change has been made since boot time, followed by a number displaying the current runlevel.

An alternative option to finding the runlevel is:

# who -r

Changing Runlevels on a Running System

Changing runlevels on a running system can be done with the init, telinit, shutdown, halt, reboot, and poweroff commands.

Changing Runlevels with init or telinit

A user can have the system reread the /etc/inittab file to implement any changes made, or to change to a new runlevel.

To change to a specific runlevel:

# init <runlevel>

For example, rebooting can be done with init 6, and changing to single-user mode can be done with init 1.

A variant of init is telinit.

telinit works similarly to the way init does, but it also takes a Q / q option to reread the /etc/inittab file and implement any changes it finds:

# telinit q

Note: telinit is sometimes just a symbolic link to init, and in practice, init responds just like telinit to the Q / q options.

Changing Runlevels with shutdown

Rebooting or shutting down a machine with init can have problems:

  • The command is unintuitive for these actions.
  • The action is immediate and provides no warning to other users.

The shutdown command is preferred in this case:

# shutdown [<options>] <time> [<message>]

The most common options are:

Option Description
-r Reboot
-H Halt (terminate operation but do not power off).
-P Power off
-c Cancel pending shutdown

The <time> parameter can set with: 

  • now 
  • hh:mm (a time on a 24-hour clock)
  • +<minutes>

The optional <message> is placed within double quotes, and will display a message to all logged in users.

Note: The messages are sent using the wall command behind the scenes. This command can be used manually by either piping output into it (ex. echo "this is a message" | wall), or by entering the wall command, followed by the text to display, and finally a ^d character.

Once the desired time is reached, shutdown will run init to set the appropriate runlevel.

Note: If shutdown is run without any options it will change runlevel to 1 (single-user mode).

Changing Runlevels with halt, reboot, and poweroff

halt will terminate operation without powering down.

reboot will restart the system.

poweroff will terminate operation and power down.

Note: In most cases, reboot and poweroff are symbolic links to halt.

Using the systemd Initialization Process

The systemd initialization process is becoming the preferred method in the Linux world; and is currently the default option for Red Hat, Fedora, CentOS, etc.

Instead of using many small initialization shell scripts, systemd uses one big program that uses individual configuration files for each service.

Units and Targets

Instead of using shell scripts and runlevels, the systemd method uses units and targets.

A systemd unit defines a service or action on the system

Each unit consists of a name, a type, and a configuration file.

There are eight different types of systemd units:

  • automount
  • device
  • mount
  • path
  • service
  • snapshot
  • socket
  • target

The systemd program identifies units by their name and type using the format: name.type.

The systemctl command can be used to list the units currently loaded in a Linux system:

# systemctl list-units

The systemd method uses service-type units to manage the daemons on the Linux system.

The target-type units are important in grouping multiple units together, so that they can be started at the same time (ex. network.target groups all units required to start the network interfaces for a system).

The systemd initialization process uses targets similarly to the way SysV uses runlevels.

Each target represents a different group of services that should be running on the system.

Instead of changing runlevels to alter what is running on a system, a user can change targets.

Note: To make the transition from SysV to systemd easier, there are targets that mimic the standard 0 to 6 SysV runlevels, called runlevell0.target to runlevell6.target.

Configuring Units

Each unit requires a configuration file that defines what program it starts and how it should start the program.

The systemd system stores unit configuration files in /lib/systemd/system/.

This is an example configuration file for a sshd.service file on CentOS 7:

[Unit]
Description=OpenSSH server daemon
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target sshd-keygen.service
Wants=sshd-keygen.service

[Service]
Type=forking
PIDFile=/var/run/sshd.pid
EnvironmentFile=/etc/sysconfig/sshd
ExecStart=/usr/sbin/sshd $OPTIONS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=42s

[Install]
WantedBy=multi-user.target

Here is a brief breakdown of some of the lines in the above example file:

ExecStart defines which program to start.

After specifies what services should run before the sshd service starts.

WantedBy defines what target level the system should be in to run the service.

Restart determines what conditions need to be present to trigger reloading the program.

Target units also use configuration files — defining which service units to start.

This is an example of the graphical.target configuration file on CentOS 7:

[Unit]
Description=Graphical Interface
Documentation=man:systemd.special(7)
Requires=multi-user.target
Wants=display-manager.service
Conflicts=rescue.service rescue.target
After=multi-user.target rescue.service rescue.target display-manager.service
AllowIsolate=yes

To breakdown the above example file:

After determines which targets should be loaded first.

Requires defines what targets are required for this target to start.

Conflicts states which targets conflict with this target.

Wants sets the required targets or services this target needs in order to run.

Setting the Default Target

The default target used when the system boots is defined in the default.target file of the /etc/systemd/system/ directory.

The systemd program looks for this file whenever it starts up.

Normally this file is a link to a standard target file in the /lib/systemd/system/ directory. For example:

[root@mg-ray-centos7 system]# ls -al default.target
lrwxrwxrwx. 1 root root 16 Dec 5 2016 default.target -> graphical.target

The systemctl Program

The systemctl program is used to control services and targets within the systemd method.

systemctl accepts several commands to define what action it will take:

Command  Description
list-units Displays the current status of all configured units.
default Changes the default target unit.
isolate Starts the named unit and stops all others.
start <name> Starts the named unit.
stop <name> Stops the named unit.
reload <name> The named unit reloads its configuration file.
restart <name> Stops and starts the named unit.
status <name/PID> Displays the status of the named unit.
enable <name> Configures the unit to start on boot.
disable <name> Prevents the unit from starting on boot.

To change the target that is currently running, use the isolate command:

# systemctl isolate rescue.target
# systemctl isolate graphical.target

Note: The systemd initialization process doesn’t use the standard Linux syslogd log filesystem. Instead, it uses its own log files that are not stored in text format. To view the systemd log files use journalctl.

Boot Details

The systemd-analyze command can be used to analyze how long each step of the boot process has taken:

$ systemd-analyze

To determine which services were loaded, and how long each individual service took to load:

$ systemd-analyze blame

Using the Upstart Initialization Process

Ubuntu and several other modern Linux distributions use an init process called Upstart (http://upstart.ubuntu.com/).

Upstart provides SysV compatibility features; however, it also uses its own unique scripts and differs in some ways from SysV.

Upstart no longer uses a /etc/inittab file, as it uses its own integrated set of startup scripts.

Upstart scripts also support starting and stopping services based on a wider variety of actions than SysV startup scripts. For example, Upstart can launch a service whenever a particular hardware device is attached.

Using Upstart-Native Methods

Upstart and its native scripts are located in the /etc/init/ (formerly /etc/event.d/) directory — which replaces both the /etc/inittab and runlevel-specific SysV startup script directory.

Note: Upstart is still under heavy development and its configuration file format is subject to change.

To change the runlevels in which a particular service runs, its configuration file will need to be edited.

Configuration files are typically found using the format /etc/init/<name>.conf.

The start on and stop on lines within the configuration file determine when the service should be started and stopped.

To start or stop a service with Upstart, use the start or stop command (ex. start httpd or stop smb).

The initctl reload command and option can be used to have Upstart reload its configuration files. This is useful before changing runlevels.

Using SysV Compatibility Methods

Because a large number of software packages still include SysV startup scripts, Upstart provides a compatibility mode.

Upstart can run SysV startup scripts in the usual locations (i.e. /etc/rc.d/rc?.d, /etc/init.d/rc?.d, /etc/rc?.d, etc.)

This allows packages without Upstart configuration scripts to still start the way they used to on a SysV enabled system. Additionally, chkconfig can be used to manage any SysV-based services.

Editing Files with vi

vi was the first full-screen text editor written for Unix.

It is available by default with nearly every Linux distribution, and is often the only editor available on emergency boot systems.

It was designed to be small and simple, but it can be a bit unintuitive when coming from standard GUI text editors.

vi uses three modes to operate. Once these modes are understood, using vi becomes much easier. 

Note: Many Linux distributions come with a variant of vi called vim (Vi IMproved). It supports more features than the original vi, but their operation is largely the same.

Understanding vi Modes

Mode Description
Command Accepts commands, usually entered as single letters:

i and a enters Insert mode.
o opens a line below the current one.

Ex Used to manipulate files (ex. saving, running external programs, etc.).

Ex mode is entered by typing a color (:), followed by the ex-mode command.

After running an ex-mode command, vi returns to Command mode automatically.

Insert Allows text to be entered. 

Almost all keys are entered on screen, except the Esc key — which exits insert mode and returns to Command mode.

Note: The terminology for vi modes can be inconsistent. For example, Command mode is sometimes referred to as Normal mode, and Insert mode is sometimes called Edit mode or Entry mode. Ex mode may also be just referred to as colon commands instead of being called a mode.

Text-Editing and Saving

To open a file with vi:

$ vi <file>

If tildes (~) are present, they represent the end of a file; and are not blank lines.

The bottom line of the vi editor window shows the status of the last command used.

Note: In vim, the bottom line shows the status of the last command used, the current line and column number (<line>,<col>), and the status of what is being displayed (Top if the first line of the document is visible, Bot if the last line of the document is visible, and All if both the first and last line are visible).

Command mode commands:

Command Keys Description
Change Case ~ Cycles through cases for the current character.
Yank yy

yw

Yanks current line to buffer.

Yanks the current word to buffer.

Paste Line p

P
Pastes buffer to current line.

Pastes buffer before current line.

Delete dd

dw

Deletes the current line.

Deletes the current word.

Change cc

cw

Changes the entire line.

Changes a word.

Undo u Undo last change.
Open Text o Inserts a new line below the current one, and enters Insert mode.
Insert Text i

a
Changes to Insert mode at current position.

Appends a space to the end of the current position and changes to Insert mode.

Search /

?

Search forward.

Search behind.

Go to Line G<num> Go to a specific line number.
Go to First Line H Go to the first (home) line.
Go to Last Line L Go to the last line.

Ex mode commands:

Feature Command Description
Edit New File :e <file> Loads a new file.

Note: Only loads a new file if the existing one has been saved since its last change, or if using :e! to force the command.

Include Existing File :r <file> Includes the contents of an old file in an existing one.
Execute External Command :!<command> Executes the external command.

Ex. :!ls -al

Regex Replace (Global) :%s/original/replacement/g Replaces <original> with <replacement> throughout the file, starting on line <s>.
Save :w Writes / saves the file.
Quit :q Quits / exits the file.
Save and Quit :wq
:ZZ
Saves and quits the file.

Booting Linux and Editing Files Essentials

  • Describe how GRUB Legacy is configured and used.
    • GRUB Legacy uses the menu.lst or grub.conf configuration file in /boot/grub/.
    • This file contains global and per-image options.
    • The grub-install program can be used to install this boot loader.
    • When GRUB boots, it presents a menu of OS options for selection using the arrow keys.
  • Describe how GRUB 2 is configured and used.
    • GRUB 2 uses the /boot/grub/grub.cfg configuration file.
    • Instead of editing configuration files directly, automatic configuration scripts should be used.
    • System-specific defaults can be set in /etc/default/grub and /etc/grub.d/.
    • GRUB 2 can be installed using the grub-install program (same as GRUB Legacy).
  • Describe the boot process.
    • The CPU runs the firmware, firmware loads a boot loader, boot loader may chainload another boot loader, final boot loader loads a Linux kernel, kernel runs the initial system program init, and init starts the rest of the system services via startup scripts that are specific to the startup system (SysV, systemd, Upstart, etc.).
    • BIOS-based computers look for boot loaders in various boot sectors, include the MBR of the hard disk, or the boot sector of a disk partition.
    • EFI-based machines look for boot loaders in files on the ESP.
  • Summarize where to look for boot-time log information.
    • The dmesg command prints out logs from the kernel ring buffer, which holds boot-time and other kernel messages.
    • Other useful log information can be found in /var/log/messages and other files in /var/log/.
  • Summarize the role of /sbin/init.
    • The init program is responsible for starting many programs and services on the Linux operating system.
  • Explain the SysV init system.
    • The SysV init system uses a default runlevel specified with a line such as id:3:initdefault: in the /etc/inittab file.
    • Commands such as chkconfig, update-rc.d, ntsysv, and systemctl can be used to change which services are started when switching to specific runlevels.
    • Runlevels 0, 1, and 6 are reserved for shutdown, single-user mode, and rebooting (respectively).
    • Runlevels 3, 4, and 5 are common runlevels on Red Hat-based distributions.
    • Runlevel 2 is the usual runlevel on Debian-based systems.
  • Describe how to change SysV init runlevels.
    • The init program and telinit program can be used to change to other runlevels.
    • The shutdown, halt, poweroff, and reboot commands are also useful to change runlevels for shutting off, halting, and rebooting a machine.
  • Explain the systemd init system.
    • The systemd init system uses units and targets to control services.
    • Targets are groups of services.
    • The default target is specified by the /etc/systemd/system/default.target file, which is a symbolic link to a target file in the /lib/systemd/system/ directory.
  • Describe how to change systemd init targets.
    • The systemctl program can be used to start and stop services, as well as change the target level of the system.
  • Describe vi‘s three editing modes.
    • Insert mode allows the user to enter text.
    • Command mode is used to perform complex commands.
    • Ex mode is mostly used for saving files, but is also useful for some advanced features such as regular expression replacement and executing external commands.