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

363 lines
14 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<chapter id="phase3">
<title>Some Basic Utilities</title>
<sect1>
<title>Analysis</title>
<para>In the previous chapter it might seem like we did not accomplish
very much. A lot of energy was expended redesigning the root disk, but the
functionality is basically the same as in the initial prototype phase. The
root disk still does not do very much. But we did make significant
improvements when it comes to space savings. In this chapter we will put
that extra space to good use and start cramming the root disk with as many
utilities as it can hold.</para>
<para>The first two root disks we built only had shell built-in commands
like <command>echo</command> and <command>pwd</command>. This time it
would be nice to have some of the commonly used external commands like
<command>cat</command>, <command>ls</command>, <command>mkdir</command>,
<command>rm</command> and such on the root disk. Keeping this in mind we
can define the goals for this phase as follows:</para>
<itemizedlist>
<listitem>
<para>Retain all of the functionality from the previous root
disk.</para>
</listitem>
<listitem>
<para>Add some of the commonly used external commands.</para>
</listitem>
</itemizedlist>
</sect1>
<sect1>
<title>Design</title>
<sect2>
<title>Determining Required Commands</title>
<para>The first question that might come to mind is, "How do we know
which commands are needed?" It is possible to just start with
<command>cat</command> and <command>ls</command> then install other
commands as we discover a need for them. But this is terribly
inefficient. We need a plan or a blueprint to work from. For this we can
turn to the Filesystem Hierarchy Standard (FHS) available from <ulink
url="http://www.pathname.com/fhs/">http://www.pathname.com/fhs/</ulink>.
The FHS dictates which commands should be present on a Linux system and
where they should be placed in the directory structure.</para>
</sect2>
<sect2>
<title>Locating Source Code</title>
<para>The next logical question is, "Now that we know what we need,
where do we get the source code?" One way to find the answer to this
question is to check the manpages. We can either search the manpages
included with one of the popular GNU/Linux distributions or use one of
the manpage search engines listed at <ulink
url="http://www.tldp.org/docs.html#man">http://www.tldp.org/docs.html#man</ulink>.
One thing that should tip us off as to where to find the source code for
a particular command is the email address listed for reporting bugs. For
example the cat manpage lists bug-textutils@gnu.org. From this email
address we can deduce that <command>cat</command> is part of the
textutils package from <ulink url="http://gnu.org">GNU</ulink>.</para>
</sect2>
<sect2>
<title>Leveraging FHS</title>
<para>So let's look at the FHS requirements for the
<filename>/bin</filename> directory. The first few commands in the list
are <command>cat</command>, <command>chgrp</command>,
<command>chmod</command>, <command>chown</command> and
<command>cp</command>. We already know that <command>cat</command> is
part of GNU's textutils. Using the next few commands as keywords in a
manpage search we discover that we need GNU's fileutils package for
<command>chmod</command>, <command>chgrp</command>,
<command>chown</command> and <command>cp</command>. In fact quite a few
of the commands in <filename>/bin</filename> come from GNU's fileutils.
The <command>date</command> command also comes from a GNU package called
sh-utils. So a good way to tackle the problem of finding source code
might be to group the commands together by package as shown
below.</para>
<itemizedlist>
<listitem>
<para>The BASH shell -- <command>echo</command>,
<command>false</command>, <command>pwd</command>,
<command>sh</command>, <command>true</command></para>
</listitem>
<listitem>
<para>GNU textutils -- <command>cat</command></para>
</listitem>
<listitem>
<para>GNU fileutils -- <command>chgrp</command>,
<command>chmod</command>, <command>chown</command>,
<command>cp</command>, <command>dd</command>, <command>df</command>,
<command>ln</command>, <command>ls</command>,
<command>mkdir</command>, <command>mknod</command>,
<command>mv</command>, <command>rm</command>,
<command>rmdir</command>, <command>sync</command></para>
</listitem>
<listitem>
<para>GNU sh-utils -- <command>date</command>,
<command>hostname</command>, <command>stty</command>,
<command>su</command>, <command>uname</command></para>
</listitem>
</itemizedlist>
<para>These four packages do not contain all of the commands in the
<filename>/bin</filename> directory, but they do represent of over 70%
of them. That should be enough to accomplish our goal of adding some of
the commonly used external commands. We can worry about the other
commands in later phases of the project.</para>
</sect2>
<sect2>
<title>Downloading Source Code</title>
<para>To fetch the source code we simply need to connect to <ulink
url="ftp://ftp.gnu.org/gnu">GNU's FTP site</ulink> and navigate to the
appropriate package directory.</para>
<para>When we get to the directory for textutils there are several
versions available. There is also a note informing us that the package
has been renamed to coreutils. The same message about coreutils appears
in the fileutils and sh-utils directories as well. So instead of
downloading three separate packages we can get everything in one
convenient bundle in the coreutils directory.</para>
</sect2>
</sect1>
<sect1>
<title>Construction</title>
<para>Rather than copying files directly to the ramdisk, we can make
things easier by setting up a staging area. The staging area will give us
room to work without worrying about the space constraints of the ramdisk.
It will also provide a way to save our work and make it easier to enhance
the rootdisk in later phases of the project.</para>
<para>The staging procedure will work like this:</para>
<orderedlist>
<listitem>
<para>Create a directory structure as defined in the FHS.</para>
</listitem>
<listitem>
<para>Copy in the files from phase 2's root disk.</para>
</listitem>
<listitem>
<para>Build the new package from source code.</para>
</listitem>
<listitem>
<para>Install files into the correct FHS directories.</para>
</listitem>
<listitem>
<para>Strip the binaries to save space.</para>
</listitem>
<listitem>
<para>Check library dependencies.</para>
</listitem>
<listitem>
<para>Copy to the whole directory structure to the ramdisk.</para>
</listitem>
<listitem>
<para>Compress the ramdisk and write it out to floppy.</para>
</listitem>
</orderedlist>
<sect2>
<title>Create a staging area</title>
<para><programlisting><prompt>bash#</prompt> mkdir ~/staging
<prompt>bash#</prompt> cd ~/staging
<prompt>bash#</prompt> mkdir bin boot dev etc home lib mnt opt proc root sbin tmp usr var
<prompt>bash#</prompt> mkdir var/log var/run</programlisting></para>
</sect2>
<sect2>
<title>Copy contents of phase 2 rootdisk</title>
<para><programlisting><prompt>bash#</prompt> dd if=~/phase2-image.gz | gunzip -c &gt; /dev/ram7
<prompt>bash#</prompt> mount /dev/ram7 /mnt
<prompt>bash#</prompt> cp -dpR /mnt/* ~/staging
<prompt>bash#</prompt> umount /dev/ram7
<prompt>bash#</prompt> rmdir ~/staging/lost+found</programlisting></para>
</sect2>
<sect2>
<title>Install binaries from GNU coreutils</title>
<para>Download a recent version of coreutils from <ulink
url="ftp://ftp.gnu.org/gnu/coreutils/">ftp://ftp.gnu.org/gnu/coreutils/</ulink></para>
<para><programlisting><prompt>bash#</prompt> cd /usr/src/coreutils-5.2.1
<prompt>bash#</prompt> export CC="gcc -mcpu=i386"
<prompt>bash#</prompt> ./configure --host=i386-pc-linux-gnu
<prompt>bash#</prompt> make
<prompt>bash#</prompt> cd src
<prompt>bash#</prompt> cp cat chgrp chmod chown cp date dd df ~/staging/bin
<prompt>bash#</prompt> cp hostname ln ls mkdir mkfifo mknod ~/staging/bin
<prompt>bash#</prompt> cp mv rm rmdir stty su sync uname ~/staging/bin</programlisting></para>
</sect2>
<sect2>
<title>Copy additional libraries</title>
<para>Check library requirements by using <command>ldd</command> on some
of the new binaries.</para>
<para><programlisting><prompt>bash#</prompt> ldd ~/staging/bin/cat
<prompt>bash#</prompt> ldd ~/staging/bin/ls
<prompt>bash#</prompt> ldd ~/staging/bin/su
<prompt>bash#</prompt> ls ~/staging/lib
</programlisting></para>
<para>Note the differences in the required libraries, as shown by the
<command>ldd</command> command, and the libraries present in the staging
area, as shown by the <command>ls</command> command, then copy any
missing libraries to the staging area.</para>
<para><programlisting><prompt>bash#</prompt> cp /lib/librt.so.1 ~/staging/lib
<prompt>bash#</prompt> cp /lib/libpthread.so.0 ~/staging/lib
<prompt>bash#</prompt> cp /lib/libcrypt.so.1 ~/staging/lib</programlisting></para>
</sect2>
<sect2>
<title>Strip binaries and libraries</title>
<para><programlisting><prompt>bash#</prompt> strip ~/staging/bin/*
<prompt>bash#</prompt> strip --strip-unneeded ~/staging/lib/*</programlisting></para>
</sect2>
<sect2>
<title>Create a compressed 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=~/phase3-image bs=1k count=4096
<prompt>bash#</prompt> gzip -9 ~/phase3-image</programlisting><note>
<para>The process for creating the compressed root disk image will
change very little throughout the remaining chapters. Writing a
small script to handle this function can be a great time
saver.</para>
</note></para>
</sect2>
<sect2>
<title>Write the root disk image to floppy</title>
<para>Insert the diskette labeled "root disk" into drive fd0.</para>
<para><programlisting><prompt>bash#</prompt> dd if=~/phase3-image.gz of=/dev/fd0 bs=1k</programlisting></para>
</sect2>
</sect1>
<sect1>
<title>Implementation</title>
<para>We will need to have a read-write filesystem in order for some of
the commands to work. The kernel's normal behavior is to mount root as
read-only, but we can change this using a kernel option. By passing the
kernel the <parameter>rw</parameter> option before
<parameter>init=/bin/sh</parameter> we will get a read-write root
filesystem.</para>
<sect2>
<title>System startup</title>
<para>Follow these steps to get the system running.</para>
<itemizedlist>
<listitem>
<para>Boot the PC from using the GRUB boot disk.</para>
</listitem>
<listitem>
<para>At the <prompt>grub&gt;</prompt> prompt, type
<userinput>kernel (fd0)/boot/vmlinuz rw init=/bin/sh root=/dev/fd0
load_ramdisk=1 prompt_ramdisk=1</userinput>.</para>
</listitem>
<listitem>
<para>Verify that you remembered to add the
<parameter>rw</parameter> parameter and press
<keycap>Enter</keycap>.</para>
</listitem>
<listitem>
<para>Type boot and press <keycap>Enter</keycap>.</para>
</listitem>
<listitem>
<para>Insert the recently created root disk when prompted.</para>
</listitem>
</itemizedlist>
<para>The terminal display should look similar to the example
below.</para>
<para><screen>GNU GRUB version 0.95
grub&gt; kernel (fd0)/boot/vmlinuz rw init=/bin/sh root=/dev/fd0 load_ramdisk=1 prompt_ramdisk=1
[Linux-bzImage, setup=0xc00, size=0xce29b]
grub&gt; boot
Linux version 2.4.26
..
.. [various kernel messages]
..
VFS: Insert root floppy disk to be loaded into RAM disk and press ENTER
RAMDISK: Compressed image found at block 0
VFS: Mounted root (ext2 filesystem) read-write.
Freeing unused kernel memory: 178k freed
# _</screen></para>
</sect2>
<sect2>
<title>Testing new commands</title>
<para>Now that the system is up and running, try using some of the new
commands.</para>
<para><programlisting><prompt>bash#</prompt> uname -a
<prompt>bash#</prompt> ls /etc
<prompt>bash#</prompt> echo "PocketLinux" &gt; /etc/hostname
<prompt>bash#</prompt> hostname $(cat /etc/hostname)
<prompt>bash#</prompt> uname -n
<prompt>bash#</prompt> mkdir /home/stuff
<prompt>bash#</prompt> cd /home/stuff</programlisting></para>
<para>If everything goes well the commands like <command>cat</command>,
<command>ls</command> and <command>hostname</command> should work now.
Even <command>mkdir</command> should work since the root filesystem is
mounted read-write. Of course since we are using a ramdisk, any changes
will be lost once the PC is reset.</para>
</sect2>
<sect2>
<title>System shutdown</title>
<para>Remove the diskette from fd0 and restart the system using
<keycap>CTRL</keycap>-<keycap>ALT</keycap>-<keycap>DELETE</keycap>.</para>
</sect2>
</sect1>
</chapter>