SysVinit

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

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.

Inittab

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

  1. The idcode has to be an unique 2 character string.

  2. The runlevel is a number 0 to 6 or a list of runlevel numbers indicating on what runlevels the line has to be interpreted.

  3. The action field defines the purpose of the line (initdefault, ctrlaltdelete, once, respawn, sysinit, wait)

  4. 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!

Improving the boot time

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

Mounting the file systems

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

Boot script and default runlevel

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.

Initscripts

/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. eselect rc help shows also an alternative way to deal with the init scripts.

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

Writing OpenRC scripts

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 --exec daemon \ 
  --pid-file /var/run/pid file.pid
  eend $?
}

Login at startup

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.


Linurs startpage