LDP/LDP/guide/docbook/Pocket-Linux-Guide/phase5.xml

519 lines
17 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<chapter id="phase5">
<title>Automating Startup &amp; Shutdown</title>
<sect1>
<title>Analysis</title>
<para>The root disk from the last chapter is looking pretty good. It has
about seventy percent of the commands that the Filesystem Hierarchy
Standard (FHS) document requires for the root filesystem. Plus it has
commands for checking and mounting filesystems. But even with all of this
the root disk is far from perfect. The list below outlines three things
that could use some improvement if the Pocket Linux system is to stand up
next to the more professional looking distributions.</para>
<orderedlist>
<listitem>
<para>The system currently requires the kernel parameters to be typed
at the <prompt>grub&gt;</prompt> prompt in order to start properly. On
any other GNU/Linux system this is only done in an emergency situation
when the system is corrupted.</para>
</listitem>
<listitem>
<para>Checking and mounting the root filesystem has to be done
manually by running a script at a shell prompt. On most modern
operating systems this function is handled automatically as part of
the system start-up process.</para>
</listitem>
<listitem>
<para>Using
<keycap>CTRL</keycap>-<keycap>ALT</keycap>-<keycap>DELETE</keycap> for
system shutdown is not very graceful. Filesystems should be unmounted
and cached information should be flushed prior to shutdown. Again,
this is something that most operating systems handle
automatically.</para>
</listitem>
</orderedlist>
<para>Taking the above list into consideration, the goals for this phase
are defined as follows:</para>
<itemizedlist>
<listitem>
<para>Kernel loads without manual intervention.</para>
</listitem>
<listitem>
<para>Automated system start-up sequence.</para>
</listitem>
<listitem>
<para>Graceful shutdown capability.</para>
</listitem>
</itemizedlist>
</sect1>
<sect1>
<title>Design</title>
<sect2>
<title>Determining necessary utilities</title>
<para>Loading the kernel without manually typing parameters is easy to
do if we read the grub info page. According to the section entitled
"configuration" all of the commands used for booting can be put in a
file called <filename>menu.lst</filename> and placed in the
<filename>/boot/grub</filename> directory.</para>
<note>
<para>Be sure to type the <filename>menu.lst</filename> filename
correctly with a lowercase L after the dot and not a number
one.</para>
</note>
<para>To automate system start-up we will need an init daemon. We know
this because the Bootdisk-HOWTO and From-Powerup-To-BASH-Prompt-HOWTO
both make mention of <command>init</command> as the first program to
start after the kernel loads. The latter HOWTO also goes into some
detail about the <filename>/etc/inittab</filename> file and the
organization of startup scripts. This could be helpful since FHS, the
blueprint we have used so far, makes no recommendation for init
scripts.</para>
<para>We will also need to find the <command>shutdown</command> command
to fulfill the second goal of graceful shutdown capability.</para>
</sect2>
<sect2>
<title>Obtaining source code</title>
<para>Searching the Linux Software Map on Ibiblio for the keyword "init"
gives a large number of results. From reading the
From-Powerup-To-BASH-Prompt-HOWTO however, we know that most Linux
systems use a System V style init daemon. Narrowing the search with the
additional key phrase of "System V" gives much better results. The
sysvinit package contains <command>init</command>,
<command>shutdown</command>, <command>halt</command> and
<command>reboot</command> which is everything we need. The version
listed in the LSM entry looks to be pretty old, but there is a
primary-site URL that will probably lead to the latest version.</para>
</sect2>
<sect2>
<title>Checking dependencies</title>
<para>The manpage for <command>init</command> mentions a FIFO called
<filename>/dev/initctl</filename> that is required for
<command>init</command> to communicate with other programs in the
sysvinit package. We will have to create this file for
<command>init</command> to function properly.</para>
</sect2>
<sect2>
<title>Designing a simple GRUB configuration file.</title>
<para>Using a GRUB configuration file is slightly more complex than
specifying the bootloader commands manually. There are directives for
features like menus, default selections and timeouts that need to be
specified in the configuration file as well as the familiar kernel
loading command. The info page for GRUB gives much of the necessary
information. We may also be able to use the GRUB configuration file on
the development system as a template. However, there is some
inconsistency between vendors as to the name and location of the file.
Regardless of what the path is on the development system it should be
<filename>/boot/grub/menu.lst</filename> on the Pocket Linux
System.</para>
</sect2>
<sect2>
<title>Outlining start-up scripts</title>
<para>Many of the popular GNU/Linux distributions use System V style
init scripts. Since we are using a "sysvinit" daemon it makes sense to
use System V style scripts as well. The following documents all touch
upon the System V style init scripts in some way and will serve as
references when building the scripts for this project:</para>
<itemizedlist>
<listitem>
<para>The Debian Policy Manual -- available online at <ulink
url="http://www.debian.org/doc/debian-policy">http://www.debian.org/doc/debian-policy</ulink>.</para>
</listitem>
<listitem>
<para>The Linux Standard Base specification -- downloadable in many
formats from <ulink
url="http://www.linuxbase.org/spec/index.shtml">http://www.linuxbase.org/spec/index.shtml</ulink>.</para>
</listitem>
<listitem>
<para>Essential System Administration, 3rd Edition by Aeleen Frisch
-- available at libraries, bookstores or directly from O'Reilly
Publishing at <ulink
url="http://www.oreilly.com/">http://www.oreilly.com/</ulink>.</para>
</listitem>
</itemizedlist>
<para>After glancing at one or two of the above references we should
have a pretty good idea of how the System V style system initialization
process works. We should also know what it takes to create System V
style init scripts for the Pocket Linux project. Below is a brief list
of what needs to be done:</para>
<itemizedlist>
<listitem>
<para>Create an <filename>inittab</filename> file to call an
<filename>rc</filename> script with a numerical argument giving the
runlevel.</para>
</listitem>
<listitem>
<para>Write an <filename>rc</filename> script that uses the runlevel
argument to execute the appropriate "K" and "S" scripts.</para>
</listitem>
<listitem>
<para>Modify the previously built <filename>local_fs</filename>
script to take <parameter>start</parameter> and
<parameter>stop</parameter> arguments.</para>
</listitem>
<listitem>
<para>Create new scripts for <filename>shutdown</filename> and
<filename>reboot</filename>.</para>
</listitem>
<listitem>
<para>Set up <filename>/etc/rcN.d</filename> directories and links
to scripts in <filename>/etc/init.d</filename>.</para>
</listitem>
</itemizedlist>
<para>As always, the BASH(1) manpage and the Advanced BASH Scripting
Guide are very helpful for writing and understanding shell
scripts.</para>
</sect2>
</sect1>
<sect1>
<title>Construction</title>
<para>There is a lot of typing to do in this section because of all of the
start-up scripts that need to be created. Using a mouse to copy the text
from this guide and paste it into a text editor can be a great time saving
tool.</para>
<sect2>
<title>Create a GRUB configuration file</title>
<para>Insert and mount the floppy labeled "boot disk".</para>
<programlisting><prompt>bash#</prompt> mount /dev/fd0 /mnt
<prompt>bash#</prompt> cd /mnt/boot/grub</programlisting>
<para>Use your favorite text editor to create the following file and
save it as /mnt/boot/grub/menu.lst:</para>
<programlisting>default 0
timeout 3
title Pocket Linux Boot Disk
kernel (fd0)/boot/vmlinuz root=/dev/fd0 load_ramdisk=1 prompt_ramdisk=1</programlisting>
</sect2>
<sect2>
<title>Install sysvinit utilities</title>
<para>Download the latest sysvinit source from <ulink
url="ftp://ftp.cistron.nl/pub/people/miquels/software/">ftp://ftp.cistron.nl/pub/people/miquels/software/</ulink></para>
<para><programlisting><prompt>bash#</prompt> cd /usr/src/sysvinit-2.85/src
<prompt>bash#</prompt> make CC="gcc -mcpu=i386"
<prompt>bash#</prompt> cp halt init shutdown ~/staging/sbin
<prompt>bash#</prompt> ln -s halt ~/staging/sbin/reboot
<prompt>bash#</prompt> ln -s init ~/staging/sbin/telinit
<prompt>bash#</prompt> mknod ~/staging/dev/initctl p</programlisting></para>
<note>
<para>In the interest of speed we are skipping the steps for checking
libraries and stripping binaries. The library requirements for
sysvinit are very basic and the Makefile is configured to
automatically strip the binaries.</para>
</note>
</sect2>
<sect2>
<title>Create /etc/inittab file</title>
<para>Use a text editor to create the following file and save it as
<filename>~/staging/etc/inittab</filename></para>
<para><programlisting># /etc/inittab - init daemon configuration file
#
# Default runlevel
id:1:initdefault:
#
# System initialization
si:S:sysinit:/etc/init.d/rc S
#
# Runlevel scripts
r0:0:wait:/etc/init.d/rc 0
r1:1:respawn:/bin/sh
r2:2:wait:/etc/init.d/rc 2
r3:3:wait:/etc/init.d/rc 3
r4:4:wait:/etc/init.d/rc 4
r5:5:wait:/etc/init.d/rc 5
r6:6:wait:/etc/init.d/rc 6
#
# end of /etc/inittab</programlisting></para>
</sect2>
<sect2>
<title>Create /etc/init.d/rc script</title>
<para>Use a text editor to create the following file and save it as
<filename>~/staging/etc/init.d/rc</filename></para>
<para><programlisting>#!/bin/sh
#
# /etc/init.d/rc - runlevel change script
#
PATH=/sbin:/bin
SCRIPT_DIR="/etc/rc$1.d"
#
# Check that the rcN.d directory really exists.
if [ -d $SCRIPT_DIR ]; then
#
# Execute the kill scripts first.
for SCRIPT in $SCRIPT_DIR/K*; do
if [ -x $SCRIPT ]; then
$SCRIPT stop;
fi;
done;
#
# Do the Start scripts last.
for SCRIPT in $SCRIPT_DIR/S*; do
if [ -x $SCRIPT ]; then
$SCRIPT start;
fi;
done;
fi
#
# end of /etc/init.d/rc</programlisting></para>
<para>Make the file executable.</para>
<para><programlisting><prompt>bash#</prompt> chmod +x ~/staging/etc/init.d/rc</programlisting></para>
</sect2>
<sect2>
<title>Modify /etc/init.d/local_fs script</title>
<para>A case statement is added to allow the script to either mount or
unmount local filesystems depending on the command-line argument given.
The original script is contained inside the "start" portion of the case
statement. The "stop" portion is new.</para>
<para><programlisting>#!/bin/sh
#
# local_fs - check and mount local filesystems
#
PATH=/sbin:/bin ; export PATH
case $1 in
start)
echo "Checking local filesystem integrity."
fsck -ATCp
if [ $? -gt 1 ]; then
echo "Filesystem errors still exist! Manual intervention required."
/bin/sh
else
echo "Remounting / as read-write."
mount -n -o remount,rw /
echo -n &gt; /etc/mtab
mount -f -o remount,rw /
echo "Mounting local filesystems."
mount -a -t nonfs,smbfs
fi
;;
stop)
echo "Unmounting local filesystems."
umount -a -r
;;
*)
echo "usage: $0 start|stop";
;;
esac
#
# end of local_fs</programlisting></para>
</sect2>
<sect2>
<title>Create a hostname script</title>
<para>Use a text editor to create the following script and save it as
<filename>~/staging/etc/init.d/hostname</filename></para>
<para><programlisting>#!/bin/sh
#
# hostname - set the system name to the name stored in /etc/hostname
#
PATH=/sbin:/bin ; export PATH
echo "Setting hostname."
if [ -f /etc/hostname ]; then
hostname $(cat /etc/hostname)
else
hostname gnu-linux
fi
#
# end of hostname</programlisting></para>
</sect2>
<sect2>
<title>Create halt &amp; reboot scripts</title>
<para>Use a text editor to create
<filename>~/staging/etc/init.d/halt</filename> as shown below.</para>
<para><programlisting>#!/bin/sh
#
# halt - halt the system
#
PATH=/sbin:/bin ; export PATH
echo "Initiating system halt."
halt
#
# end of /etc/init.d/halt</programlisting></para>
<para>Create the following script and save it as
<filename>~/staging/etc/init.d/reboot</filename></para>
<para><programlisting>#!/bin/sh
#
# reboot - reboot the system
#
PATH=/sbin:/bin ; export PATH
echo "Initiating system reboot."
reboot
#
# end of /etc/init.d/reboot</programlisting></para>
<para>Flag all script files as executable.</para>
<para><programlisting><prompt>bash#</prompt> chmod +x ~/staging/etc/init.d/*</programlisting></para>
</sect2>
<sect2>
<title>Create rcN.d directories and links</title>
<para><programlisting><prompt>bash#</prompt> cd ~/staging/etc
<prompt>bash#</prompt> mkdir rc0.d rc1.d rc2.d rc3.d rc4.d rc5.d rc6.d rcS.d
<prompt>bash#</prompt> cd ~/staging/etc/rcS.d
<prompt>bash#</prompt> ln -s ../init.d/local_fs S20local_fs
<prompt>bash#</prompt> ln -s ../init.d/hostname S30hostname
<prompt>bash#</prompt> cd ~/staging/etc/rc0.d
<prompt>bash#</prompt> ln -s ../init.d/local_fs K10local_fs
<prompt>bash#</prompt> ln -s ../init.d/halt K90halt
<prompt>bash#</prompt> cd ~/staging/etc/rc6.d
<prompt>bash#</prompt> ln -s ../init.d/local_fs K10local_fs
<prompt>bash#</prompt> ln -s ../init.d/reboot K90reboot</programlisting></para>
</sect2>
<sect2>
<title>Create the root disk image</title>
<para><programlisting><prompt>bash#</prompt> cd /
<prompt>bash#</prompt> dd if=/dev/zero of=/dev/ram7 bs=1k count=4096
<prompt>bash#</prompt> mke2fs -m0 /dev/ram7 4096
<prompt>bash#</prompt> mount /dev/ram7 /mnt
<prompt>bash#</prompt> cp -dpR ~/staging/* /mnt
<prompt>bash#</prompt> umount /dev/ram7
<prompt>bash#</prompt> dd if=/dev/ram7 of=~/phase5-image bs=1k
<prompt>bash#</prompt> gzip -9 ~/phase5-image</programlisting></para>
</sect2>
<sect2>
<title>Copy the image to diskette</title>
<para>Insert the diskette labeled "root disk" into drive fd0.</para>
<para><programlisting><prompt>bash#</prompt> dd if=~/phase5-image.gz of=/dev/fd0 bs=1k</programlisting></para>
</sect2>
</sect1>
<sect1>
<title>Implementation</title>
<sect2>
<title>System Startup</title>
<para>Boot the PC using the floppy labeled "boot disk". Place the
recently created root disk in fd0 when prompted. The output should
resemble the example below:</para>
<para><screen>GNU GRUB version 0.95
Uncompressing Linux... Ok, booting kernel.
..
.. [various kernel messages]
..
VFS: Insert root floppy to be loaded into RAM disk and press ENTER
RAMDISK: Compressed image found at block 0
VFS: Mounted root (ext2 filesystem) readonly.
Freeing unused kernel memory: 178k freed
Checking local filesystem integrity.
/dev/ram0: clean 105/1024 files 2842/4096 blocks
Remounting / as read-write.
Mounting local filesystems.
Setting the hostname.
INIT: Entering runlevel: 1
# _</screen></para>
</sect2>
<sect2>
<title>Verify success of startup scripts</title>
<para>Use the <command>mount</command> command to check that local
filesystems are mounted as read-write. The output should look like the
example below.</para>
<para><screen><prompt>bash#</prompt> mount
/dev/root on / type ext2 (rw)
proc on /proc type proc (rw)</screen></para>
<para>Check the hostname.</para>
<para><screen><prompt>bash#</prompt> uname -n
gnu-linux</screen></para>
</sect2>
<sect2>
<title>System shutdown</title>
<para>Bring the system down gracefully with the
<command>shutdown</command> command.</para>
<para><programlisting><prompt>bash#</prompt> shutdown -h now</programlisting></para>
<para>We should see the following output from <command>init</command>
and the shutdown scripts:</para>
<para><screen>INIT: Switching to runlevel: 0
INIT: Sending processes the TERM signal
Terminated
INIT: Sending processes the KILL signal
Unmounting local filesystems.
Initiating system halt.
System halted.</screen></para>
</sect2>
</sect1>
</chapter>