mirror of https://github.com/tLDP/LDP
363 lines
14 KiB
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 > /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></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> kernel (fd0)/boot/vmlinuz rw init=/bin/sh root=/dev/fd0 load_ramdisk=1 prompt_ramdisk=1
|
|
[Linux-bzImage, setup=0xc00, size=0xce29b]
|
|
|
|
grub> 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" > /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> |