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. 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
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 $?
}
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.