The bootloader as Grub loads the kernel. The kernel is the extracting itself and starts itself.
If something goes wrong the kernel stops with a panic messages. Sometimes the kernel hangs. I this case it is worth to wait, maybe it is just a blocker and the kernel continuous after a while (e.g. after 1 min). If the system comes up, dmesg will show the trouble and its first column is the time, so the hanger can easily be found.
When the kernel comes up in a traditionally SysVinit system it starts /sbin/init. Grub can be configured to let the kernel start any other program than init. Some newer Linux systems have replaced init by the newer systemd. On those system /usr/lib/systemd/systemd will be called instead.
To get a nice boot sequence seeing one tux per processor, you need to enable framebuffer support in the kernel, select therefore VESA VGA graphics and Framebuffer Console support.
SysVinit makes uses init and init reads /etc/inittab
and executes the scripts in /etc/init.d
accordingly. Since this configuration is very flexible and can be easy adapted many versions of the scripts exist. This is one of the main differences between the different Linux distributions. The following is based on the scripts OpenRC https://wiki.gentoo.org/wiki/Project:OpenRC uses. OpenRC is what uses init on a Gentoo Linux system.
Openrc makes use of c programs and allows that script can run in parallel. See: https://wiki.gentoo.org/wiki/OpenRC .
The configuration is in /etc/rc.conf
. It can create a log file (optionally verbose) in /var/log/rc.log
, however during booting no writable file-system might be available and therefore the logger might create an error. A way out might be specify an other path than /var/log
as setting up an initial ram disk.
A option exist and set by default to interrupt the boot process by pressing the I key.
/etc/conf.d/modules
holds the kernel modules to be loaded.
As default the Linux kernel starts the program init as first process.
init is a regular program see man init. init reads the file /etc/inittab
that has a list of instructions for init.
There are usually 7 runlevels (0 to 6). A runlevel is a mode of operation defined in
/etc/inittab
.
The program init can also be called when Linux is running to change the runlevel.
The command init 0 changes to runlevel halt and turns off the computer.
The command init 6 causes a reboot.
The program init creates the binary log files /var/run/utmp
and /var/log/wtmp
.
The file /etc/inittab
contains individual
lines having the following structure:
idcode: runlevel: action: command
The idcode has to be an unique 2 character string.
The runlevel is a number 0 to 6 or a list of runlevel numbers indicating on what runlevels the line has to be interpreted.
The action field defines the purpose of the line (initdefault, ctrlaltdelete, once, respawn, sysinit, wait)
Finally the command is the command executed in the way the line defines it (runlevel and action). As any command the command can also have command line arguments.
The contents of /etc/inittab
is Linux
distribution depending. In Gentoo /etc/inittab
is configured that the script /sbin/rc
is called with
various script parameters (shutdown, boot, sysinit).
Traditional distributions made use of simple bash scripts for the purpose of rc. This is more open,
but has some limitations. Gentoo uses the bash script rc script, however it does not use bash directly it
uses /sbin/runscript
. runscript is a program
written in c that calls runscript.sh (also in /sbin
) both are part of Gentoo's baselayout, both form
a initscript handler that calls bash. As root type runscript help. The source of the c program runscript
is delivered inside baselayout-<version>
.tar.bz2 that can be found in
/usr/portage/distfiles
when not present download it from http://sources.gentoo.org/cgi-bin/viewvc.cgi/baselayout/. There are many copies of runscript on the pc:
whereis runscript
runscript: /usr/bin/runscript /sbin/runscript /usr/share/man/man1/runscript.1.bz2 /usr/share/man/man8/runscript.8.bz2
The /usr/sbin/runscript
will be
taken at boot as seen by the PATH environmental variable:
echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin:
or found by which:
which runscript
/usr/sbin/runscript
To see from where all the other runscripts are coming from:
qfile /usr/bin/runscript
net-dialup/minicom (/usr/bin/runscript)
Or all in one command
qfile $(whereis runscript)
sys-apps/openrc (/usr/share/man/man8/runscript.8.bz2)
sys-apps/openrc (/sbin/runscript)
net-dialup/minicom (/usr/share/man/man1/runscript.1.bz2)
net-dialup/minicom (/usr/bin/runscript)
The script interpreter for minicom is also called runscript, but is a completely different program. If the path and which would point to this binary, then the system would no more to be able to boot!
To see what init is doing, runscript.c
can be hacked. Copy baselayout somewhere and go into the /src
directory. There modify the main by putting some print statements:
int main(int argc, char *argv[]) { " " int debugcounter; printf("\033[33mDebug support in runscript, %i command line parameters\n",argc); for(debugcounter=0;debugcounter<argc;debugcounter++){ printf("%i:%s\n",debugcounter,argv[debugcounter]); } printf("\033[m\n");
Save the file and run make in this directory, now backup the runscript in /sbin and copy over the
new runscript. Now when you boot or do a shutdown, you can observe how init is calling rc and how the
/etc/init.d
routines are called. This is a
temporary hack and will be wiped off when you do a re-emerge baselayout, or just copy over the saved
runscript.
The hack could be expanded to debug further the rc scripts! It would be nice to have something as this not as hack, but as official baselayout feature!
The /sbin/init boots one service after an other. This is quite robust and reliable but not very fast. The PC waits e.g. for a IP address from the DHCP server and continues just after having it receive. Instead of waiting it could initialize other hardware and do other things.
You could work with static IP addresses to avoid waiting for DHCP.
To get some other slight optimization there is also an option in the /etc/conf.d/rc
RC_PARALLEL_STARTUP="yes"
However the bootup messages are drastically reduced and you will not easily see if the system has a problem.
There is also the kernel parameter fastboot that can be added to the grub
title=Gentoo Linux fastboot 2.6.36-gentoo-r5-2010-12-27 root (hd0,0) kernel /kernel-2.6.36-gentoo-r5-2010-12-27 root=/dev/sda2 vga=0x31B fastboot
init is also responsible to read /etc/fstab
and mount the file system. In fact this is one of the first action it does. However it does this not
automatically, it reads this out of /etc/inittab
si::sysinit:/sbin/rc sysinit
After having mounted the file systems, init reads from
/etc/inittab
to start the bootscripts:
rc::bootwait:/sbin/rc boot
after this the default runlevel 3 is read from /etc/inittab
id:3:initdefault:
Then all scripts and login shells from this runlevel are started.
/etc/init.d
holds all the scripts that init starts.
Which boot scripts start depends on the users needs and runlevels. The rc-update program finally configures
what scripts in /etc/init.d
have to run and when.
Type rc-update -s to get the view of the situation. The configuration is stored in
/etc/runlevels
where every runlevel has a directory
and those directories have links to the scripts in /etc/init.d
.
The scripts can also be started, stopped or restarted
/etc/init.d/ntpd stop
/etc/init.d/ntpd start
/etc/init.d/ntpd restart
Instead of typing (or press the tab key) the path and service the command rc-service <service>
can be typed in. This sounds like less work however the service has to be typed in completely and correctly. The first approach pressing the tab key is therefore faster and more reliable.
What init handles can be see by
rc-update -s or full command rc-update show
The /etc/init.d scripts can be linked to init by
rc-update add lircd default
rc-update del lircd
To see what is going on with the run levels:
rc-status boot
rc-status default
rc-status -a or rc-status --all
The command runlevel shows preceding and actual runlevel.
Additional runlevels can be added and even be selected on boot time telling grub to pass a parameter via kernel to init. The runlevel offline can be used with the keyword softlevel (or bootlevel) on a laptop to give an alternative to not start the network.
title Gentoo Linux Offline Usage root (hd0,0) kernel (hd0,0)/kernel-2.4.25 root=/dev/hda3 softlevel=offline
The scripts make use of their configuration data found under /etc/conf.d
The file /etc/conf.d/local.start
is a bit special since commands can be put there that will be started on boot. A cleaner way is writing boot scripts for /etc/init.d
Once OpenRC was a project on its own, but it became an orphaned so Gentoo took it over. Unfortunately the documentation is now a bit vague, The fact that many Linux distributions move away from SysVinit to systemd gives not much hope that the documentation improves. Reverse engineering from scripts under /etc/init.d
as ntpd
and ntp-client
is a way to go however a good documentation can also be found at http://big-elephants.com/2013-01/writing-your-own-init-scripts/
Just on script is required to start and stop the daemons, it should look as follows
#!/sbin/runscript depend(){ } start(){ } stop(){ }
The depend function can have keywords as need,use, before and after and allows to set a startup sequence.
depend(){ need apache2 }
The start function starts the daemon using the start-stop-daemon function (see man start-stop-daemon) with all options as desired
start(){ ebegin "starting my daemon" start-stop-daemon --background --start --exec<daemon>
\ --make-pidfile --pid-file /var/run/<pid file>
.pid eend $? }
Creating a pid file is optional but helps OpenRC to find the process number and to stop the script when desired.
The stop function then could look as
stop(){ ebegin "stop my daemon" start-stop-daemon --stop --execdaemon
\ --pid-file /var/run/pid file
.pid eend $? }
Additionally /etc/inittab
is responsible for
the login. Historically there was one UNIX computer that had many terminals connected via RS232 to it. Now
this is emulated with different console windows (getty). The agetty lines define such a virtual terminal
with the virtual baudrate of 28400.
c1:12345:respawn:/sbin/agetty 38400 tty1 linux
Or if you really want to log in via RS232
#s0:12345:respawn:/sbin/agetty 9600 ttyS0 vt100
There is also mingetty that allows automatic login of users without password. Just emerge mingetty and put a line as
1:3:respawn:/sbin/mingetty --autologin <USER>
tty1
to replace agetty and it parameters.
systemd is a replacement for sysvinit. Unfortunately there is a lot of controversy about it but finally it has made it in most of the Linux distributions as default start up method.
Some links: http://www.h-online.com/open/features/Control-Centre-The-systemd-Linux-init-system-1565543.html or the original German version https://wiki.debian.org/systemd https://wiki.archlinux.org/index.php/systemd https://wiki.archlinux.org/index.php/Network_Configuration, https://www.digitalocean.com/community/tutorials/systemd-essentials-working-with-services-units-and-the-journal
Using systemd makes the different Linux distributions very similar. What stays different is the package handling and management.
/etc/mtab
is handled differently since systemd does mounting. For backward compatibility do or check ln -sf /proc/self/mounts /etc/mtab
systemd does not require a udev package since it includes it (this has put the pressure to distributions using OpenRC to fork udev in a separate package).
systemd replaces ConsoleKit
Dealing with /etc/fstab
additional .mount and .swap units can be automatically created
comment=systemd.automount
can be added to the drives in /etc/fstab
to convert them to automount drives and not have the system waiting until such typically network drives are ready.
Since systemd is running all the time also a gui tool systemadm is available.
systemd-analyze tells how long the boot process was taking
There is support to make a svg graphics as bootchart systemd-analyze plot > plot.svg or systemd-analyze dot | dot -Tsvg > systemd.svg to convert it first to dot format and then having dot making the dependengy graph. Or simply see the ranking of what took long to start systemd-analyze blame
Keyboard layout can be listed as localectl list-keymaps and loaded as root with loadkeys <keymap as sg>
or persistent by localectl set-keymap --no-convert <keymap>
this modifies /etc/vconsole.conf
obviously /etc/vconsole.conf
could also be edited using an editor.
systemctl poweroff turns off the computer and systemctl reboot reboots it. More precise systemctrl calls the unit poweroff.target that is in /usr/lib/systemd/system
Modules not loaded automatically can be listed (one per line) and added to files like /etc/modules-load.d/
<some name>
.conf
The network must probably be started. In case of dhcp start the client daemon dhcpcd eth0 or start it via its unit systemctl start dhcpcd@eth0.service
The kernel must know to start systemd and not init after it has booted. For grub legacy put
kernel /vmlinuz root=/dev/sda2 init=/usr/lib/systemd/systemd
in /boot/grub/grub.conf
and for grub 2 put
GRUB_CMDLINE_LINUX="init=/usr/lib/systemd/systemd"
in /etc/default/grub
The units are text files and have different file extensions as
.service to start a service (e.g a daemon)
.mount to mount a filesystem (there is also .automount)
.socket prepare a socket for a listener and when accessed trigger an action
.path to monitor accesses to a file or directory and trigger an action
systemd handle services as known from sysvinit systems:
systemctl start <name>
.service starts a service
systemctl stop <name>
.service stops a service
systemctl restart <name>
.service stops and then starts a service
systemctl reload <name>
.service similar to restart is reload however normal functionality of the service keeps maintained.
sysemctl status <name>
.service shows the status
systemctl --failed to show what failed
systemctl cat <name>
.service to read the file without dealing with its path
systemctl list-dependencies <name>
.service or systemctl list-dependencies --all <name>
.service to see its dependencies
systemctl show <name>
.service to see the low level details
systemctl edit <name>
.service or systemctl edit --full <name>
.service to edit it without dealing with its path followed by systemctl daemon-reload to have effect
Available units can be seen by
ls /usr/lib/systemd/system
systemctl --all --full
systemctl list-units or simply systemctl
systemctl list-units --all
systemctl list-unit-files
systemctl | grep running
systemctl list-unit-files | grep enabled
Customization can be made by copying and modifying those files to /etc/systemd/system
systemd calls more or less it units in parallel. If a unit calls an other that is not ready, then systemd buffers the request using sockets.
Systemd can create automatically additional units as when devices are plugged in. Therefore it uses in udev rules
TAG+="systemd"
systemd targets are units as well but are used to group units and have them started together and form therefore something similar as runlevels in a sysvinit system.
systemctl list-unit-files --type=target lists the unit files that are targets
Adding a services to the list of being started at boot (the boot.target) is more uniform:
systemctl enable <name>
.service enable automatic start at boot
systemctl disable <name>
.service disable automatic start at boot
systemctl get-default shows the targets that are run at boot
Other targets exist as rescue.target
, multi-user.target
systemctl set-default multi-user.target sets it
Finally everything are links so the same could be achieved by ln -sf /lib/systemd/system/multi-user.target /etc/systemd/system/default.target makes the multiuser-target the default target.
systemctl list-dependencies multi-user.target show what depends on it.
systemctl isolate multi-user.target will stop all targets except the multi-user.target
systemd does not need a logger since it includes the logger journal. It can be configured via /etc/systemd/journald.conf
To have the log stored on the disk /var/log/journal
Storage=persistent
or mkdir -p /var/log/journal
To set maximum size on disk
SystemMaxUse=50M
Limits to 50MByte if this is missing it will be limited to 10% of the partition size.
The log is binary and not ASCII and can be read via journalctl, for just the current boot journalctl -b or for the kernel messages journalctl -k.
journalctl -u <name>
.service
will show what has been logged for a service.
The journal can feed a classic logger by systemctl enable syslog-ng so the log becomes ASCII again.