<?xml version="1.0" encoding="ISO-8859-1"?>
<chapter id="phase5">
  <title>Automatiseren van de systeemstart &#38; afsluiten van het systeem</title>

  <sect1>
    <title>Analyse</title>

<para>De rootdisk uit het laatste hoofdstuk ziet er tamelijk goed uit. Het
heeft ongeveer zeventig procent van de opdrachten die het
Filesystem Hierarchy Standard (FHS) document vereist voor het
root bestandssysteem. Plus dat het opdrachten heeft voor het controleren
en mounten van bestandssystemen. Maar zelfs met dit alles is de rootdisk
verre van perfect. In de lijst hieronder worden drie dingen uiteengezet
die wat verbeteringen kunnen gebruiken als het Pocket Linux systeem
    het hoofd moet bieden aan de professioneler uitziende distributies.
    </para>

    <orderedlist>
      <listitem>
        <para>Het systeem vereist thans dat de kernelparameter
        <parameter>init=/bin/sh</parameter> na de LILO-prompt wordt getypt om
juist te starten. Op elk ander GNU/Linux systeem wordt dit alleen
in een noodsituatie gedaan wanneer het systeem is beschadigd.
        </para>
      </listitem>

      <listitem>
        <para>Het controleren en mounten van het root bestandssysteem
moet handmatig worden uitgevoerd door na de shellprompt een script
uit te voeren. Onder de meeste moderne besturingssystemen wordt deze
functie automatisch afgehandeld als onderdeel van het systeemopstartproces.
        </para>
      </listitem>

      <listitem>
        <para>Het is niet erg elegant met <keycap>CTRL</keycap>-<keycap>ALT</keycap>-<keycap>DELETE</keycap> het systeem
af te sluiten. Bestandssystemen zouden moeten worden afgekoppeld met
umount en informatie in de cache zou voor het afsluiten naar disk
moeten worden geschreven. Ook dit is iets dat de meeste besturingssystemen
automatisch afhandelen.
        </para>
      </listitem>
    </orderedlist>

    <para>De bovenstaande lijst in aanmerking genomen, zijn de doelen
voor deze fase als volgt gedefinieerd:
    </para>

    <itemizedlist>
      <listitem>
        <para>Geautomatiseerde opstartreeks.</para>
      </listitem>

      <listitem>
        <para>Mogelijkheid tot het elegant afsluiten van het systeem.</para>
      </listitem>
    </itemizedlist>
  </sect1>

  <sect1>
    <title>Ontwerp</title>

    <sect2>
      <title>De nodige utility's vaststellen</title>

      <para>We hebben een init daemon nodig om de opstart te automatiseren.
We weten dit doordat de Bootdisk-HOWTO en From-Powerup-To-BASH-Prompt HOWTO
het beiden vermelden als het eerste te starten programma nadat de kernel
is geladen. De laatste HOWTO gaat ook in detail in op het <filename>/etc/inittab</filename> bestand en de organisatie van de opstartscripts. Dit zou van hulp kunnen
zijn, aangezien de FHS, de blauwdruk die we tot dusverre hebben gebruikt,
geen aanbevelingen doet voor init-scripts.</para>

      <para>We zullen ook de opdracht shutdown moeten vinden om aan het tweede
doel, het elegant afsluiten van het systeem, te voldoen.
      </para>
    </sect2>

    <sect2>
      <title>Verkrijgen van de broncode</title>

      <para>Het doorzoeken van de Linux Software Map op Ibiblio op het
trefwoord &#34;init&#34; geeft een groot aantal resultaten te zien.
Uit de From-Powerup-To-BASH-Prompt-HOWTO weten we echter dat de
meeste systemen een initdaemon in de stijl van System V gebruiken. 
      De zoekopdracht beperkend tot het aanvullende trefwoord
      &#34;System V&#34; geeft veel betere resultaten.
      Het sysvinit package bevat <command>init</command>, <command>shutdown</command>, <command>halt</command> en <command>reboot</command> wat alles
is wat we nodig hebben. De versie in het LSM record ziet er tamelijk oud
uit, maar er staat een URL in die verwijst naar de primaire site, die
waarschijnlijk zal leiden naar de laatste versie.
      </para>
    </sect2>

    <sect2>
      <title>Afhankelijkheden controleren</title>

<para>De manpage voor init vermeldt een FIFO genaamd <filename>/dev/initctl</filename> welke nodig is voor <command>init</command> om met andere programma's
in het sysvinit package te communiceren. We zullen dit bestand voor de
goede werking van <command>init</command> aan moeten maken.
      </para>
    </sect2>

    <sect2>
      <title>Uiteenzetting van opstartscripts</title>

      <para>Veel van de populaire GNU/Linux distributies maken gebruik van
initscripts in de stijl van System V. Aangezien we gebruik maken van een
      &#34;sysvinit&#34; daemon, is het zinvol om ook gebruik te maken van
scripts in de stijl van System V. De volgende documenten roeren het onderwerp
betreffende initscripts in de stijl van System V op &eacute;&eacute;n of 
andere manier aan en ze zullen dienen als referenties bij het bouwen van de
scripts voor dit project:
      </para>

      <itemizedlist>
        <listitem>
          <para>Het Debian Policy Manual -- online beschikbaar op <ulink
          url="http://www.debian.org/doc/debian-policy">http://www.debian.org/doc/debian-policy</ulink>.</para>
        </listitem>

        <listitem>
          <para>De Linux Standard Base specificatie -- in veel formaten
te downloaden vanaf
          <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 door Aeleen Frisch
          -- beschikbaar bij boekwinkels of direct bij O&#39;Reilly Publishing
          op <ulink url="http://www.oreilly.com/">http://www.oreilly.com/</ulink>.</para>
        </listitem>
      </itemizedlist>

      <para>Na een blik te hebben geworpen op &eacute;&eacute;n of twee
van de bovenstaande referenties zouden we een tamelijk goed beeld moeten
hebben hoe het systeeminitialisatieproces in de stijl van System V werkt.
      We zouden ook kunnen weten wat er nodig is om initscripts in de stijl
van System V voor het Pocket Linux project aan te maken.
      Hieronder staat een beknopte opsomming van wat er moet worden gedaan:
      </para>

      <itemizedlist>
        <listitem>
<para>Maak een <filename>inittab</filename> bestand voor de aanroep van een
<filename>rc</filename> met een numeriek argument dat het runlevel aanduidt.
          </para>
        </listitem>

        <listitem>
          <para>Schrijf een <filename>rc</filename> script dat het runlevelargument
gebruikt om de van toepassing zijnde
          &#34;K&#34; en &#34;S&#34; scripts uit te voeren.</para>
        </listitem>

        <listitem>
          <para>Pas het eerder gebouwde <filename>local_fs</filename> script 
aan dat het <parameter>start</parameter> en <parameter>stop</parameter> 
argumenten accepteert.</para>
        </listitem>

        <listitem>
          <para>Maak nieuwe scripts aan voor het afsluiten en opnieuw opstarten
van het systeem.</para>
        </listitem>

        <listitem>
          <para>Zet /etc/rcN.d directory's op en links naar scripts in
          /etc/init.d.</para>
        </listitem>
      </itemizedlist>

      <para>Zoals altijd zijn de BASH(1) manpage en de Advanced BASH Scripting
      Guide erg behulpzaam bij het schrijven en begrijpen van shellscripts.
</para>
    </sect2>
  </sect1>

  <sect1>
    <title>Constructie</title>

    <sect2>
      <title>Installeer sysvinit utility's</title>

      <para><programlisting>
<prompt>bash#</prompt> cd /usr/src/sysvinit-2.84/src
<prompt>bash#</prompt> make clobber
<prompt>bash#</prompt> make CC=&#34;gcc -mcpu=i386&#34;
<prompt>bash#</prompt> cp halt init shutdown ~/fase/sbin
<prompt>bash#</prompt> ln -s halt ~/fase/sbin/reboot
<prompt>bash#</prompt> ln -s init ~/fase/sbin/telinit
<prompt>bash#</prompt> mknod ~/fase/dev/initctl p</programlisting></para>
    
<note>
<para>
Omwille van de snelheid slaan we de stappen voor het controleren van libaray's
en strippen van binary's over. De library vereisten voor sysvinit zijn erg
fundamenteel en de Makefile is geconfigureerd om de binary's automatisch 
te strippen.
</para>
</note>


</sect2>

    <sect2>
      <title>Maak een /etc/inittab bestand aan</title>

      <para>Gebruik een teksteditor om het volgende bestand aan te maken
en sla het op als ~/fase/etc/inittab</para>

      <para><programlisting># /etc/inittab - init daemon configuratiebestand
#
# Standaardrunlevel
id:1:initdefault:
#
# Systeeminitialisatie
si:S:sysinit:/etc/init.d/rc S
#
# Runlevelscripts
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
#
# einde van /etc/inittab</programlisting></para>
    </sect2>

    <sect2>
      <title>Maak een <filename>/etc/init.d/rc</filename> script aan</title>

      <para>Gebruik een teksteditor om het volgende bestand aan te maken en
sla het op als <filename>~/fase/etc/init.d/rc</filename></para>

      <para><programlisting>#!/bin/sh
#
# /etc/init.d/rc - runlevel change script
#
PATH=/sbin:/bin
SCRIPT_DIR=&#34;/etc/rc$1.d&#34;
#
# Controleer dat de directory rcN.d echt bestaat
if [ -d $SCRIPT_DIR ]; then
#
# Voer als eerste de kill scripts uit.
  for SCRIPT in $SCRIPT_DIR/K*; do
    if [ -x &#34;$SCRIPT&#34; ]; then
      $SCRIPT stop;
    fi;
  done;
#
# Doe als laatste de startscripts.
  for SCRIPT in $SCRIPT_DIR/S*; do
    if [ -x $SCRIPT ]; then
      $SCRIPT start;
    fi;
  done;
fi</programlisting></para>

      <para>Maak het bestand uitvoerbaar.</para>

      <para><programlisting><prompt>bash#</prompt> chmod +x ~/fase/etc/init.d/rc</programlisting></para>
    </sect2>

    <sect2>
      <title>Pas het script /etc/init.d/local_fs aan</title>

      <para>Er wordt een case statement toegevoegd om het script afhankelijk
van het opgegeven opdrachtregelargument de lokale bestandssystemen te mounten
of unmounten. Het oorspronkelijke script staat in het &#34;start&#34; gedeelte 
van het case statement. Het &#34;stop&#34; gedeelte is nieuw.  
</para>

      <para><programlisting>#!/bin/sh
#
# local_fs - controleer en mount lokale bestandssystemen
#
PATH=/sbin:/bin ; export PATH

case $1 in

start)
  echo &#34;Checking local filesystem integrity.&#34;
  fsck -ATCp
  if [ $(($?)) -gt $((1)) ]; then
    echo &#34;Filesystem errors still exist!  Manual intervention required.&#34;
    /bin/sh
  else
    echo &#34;Remounting / as read-write.&#34;
    mount -o remount,rw /
    echo &#34;Mounting local filesystems.&#34;
    mount -a
  fi
;;

stop)
  echo &#34;Dismounting local filesystems.&#34;
  umount -a
  echo &#34;Remounting / as read-only.&#34;
  mount -o remount,rw /
  echo &#34;Flushing disk cache.&#34;
  sync
;;

default)
  echo &#34;usage: $0 start|stop&#34;;
;;

esac
#
# einde van local_fs</programlisting></para>
    </sect2>

    <sect2>
      <title>Maak een hostname script aan</title>

      <para>Gebruik een teksteditor om het volgende script aan te maken en
sla het op als <filename>~/fase/etc/init.d/hostname</filename></para>

      <para><programlisting>#!/bin/sh
#
# hostname - stel de systeemnaam in op de naam die is 
# opgeslagen in /etc/hostname
#
PATH=/sbin:/bin ; export PATH

echo &#34;Setting hostname.&#34;
if [ -f /etc/hostname ]; then
  hostname $(cat /etc/hostname)
else
  hostname gnu-linux
fi
#
# einde van hostname</programlisting></para>
    </sect2>

    <sect2>
      <title>Maak halt &#38; reboot scripts aan</title>

      <para>Gebruik een teksteditor om <filename>~/fase/etc/init.d/halt</filename> zoals hieronder getoond aan te maken.
      </para>

      <para><programlisting>#!/bin/sh
#
# halt - stop het systeem
#
PATH=/sbin:/bin ; export PATH

echo &#34;Initiating system halt.&#34;
halt
#
# einde van /etc/init.d/halt</programlisting></para>

      <para>Maak het volgende script aan het sla het op als
      <filename>~/fase/etc/init.d/reboot</filename></para>

      <para><programlisting>#!/bin/sh
#
# reboot - reboot het systeem
#
PATH=/sbin:/bin ; export PATH

echo &#34;Initiating system reboot.&#34;
reboot
#
# einde van /etc/init.d/reboot</programlisting></para>

      <para>Maak scriptbestanden uitvoerbaar.</para>

      <para><programlisting><prompt>bash#</prompt> chmod +x ~/fase/etc/init.d/*</programlisting></para>
    </sect2>

    <sect2>
      <title>Maak <filename>rcN.d</filename> directory's en links 
naar scripts in <filename>/etc/init.d</filename></title>

      <para><programlisting>
<prompt>bash#</prompt> cd ~/fase/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 ~/fase/etc/rcS.d
<prompt>bash#</prompt> ln -s ../init.d/proc_fs S10proc_fs
<prompt>bash#</prompt> ln -s ../init.d/local_fs S20local_fs
<prompt>bash#</prompt> ln -s ../init.d/hostname S30hostname
<prompt>bash#</prompt> cd ~/fase/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 ~/fase/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>Maak het rootdiskimage aan</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
<prompt>bash#</prompt> mount /dev/ram7 /mnt
<prompt>bash#</prompt> cp -dpR ~/fase/* /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>Kopieer de image naar diskette</title>

      <para>Doe de diskette met het label &#34;rootdisk&#34; in het
diskettestation fd0.</para>

      <para><programlisting><prompt>bash#</prompt> dd if=~/phase5-image.gz of=/dev/fd0 bs=1k</programlisting></para>
    </sect2>
  </sect1>

  <sect1>
    <title>Implementatie</title>

    <sect2>
      <title>Systeemstart</title>

      <para>Boot de PC met behulp van de diskette met het label 
      &#34;bootdisk&#34; en druk na de LILO-prompt op
      <keycap>Enter</keycap>. Plaats de recent gemaakte rootdisk in
fd0 wanneer dit wordt aangegeven. De uitvoer zou het voorbeeld hieronder
moeten weerspiegelen:
      </para>

      <para><screen>boot: bootdisk
Loading bootdisk
Uncompressing Linux... Ok, booting kernel.
..
.. [diverse kernelmeldingen]
..
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>Verifieer het succes van de opstartscripts</title>

<para>
Gebruik de opdracht <command>mount</command> om te controleren of alle lokale
bestandssystemen als read-write zijn gemount. De uitvoer zou er ongeveer
uit moeten zien als in het voorbeeld hieronder.
      </para>

      <para><screen><prompt>bash#</prompt> mount
/dev/root on / type ext2 (rw)
proc on /proc type proc (rw)</screen></para>

      <para>Controleer de hostnaam.</para>

      <para><screen><prompt>bash#</prompt> uname -n
gnu-linux</screen></para>
    </sect2>

    <sect2>
      <title>Systeem afsluiten</title>

<para>Sluit het systeem elegant af met de opdracht <command>shutdown</command>.
      </para>

<para><programlisting><prompt>bash#</prompt> shutdown -h now</programlisting></para>

      <para>We zouden in de volgende uitvoer van <command>init</command> en
de scripts te zien moeten krijgen waarmee het systeem wordt afgesloten:</para>

      <para><screen>INIT: Switching to runlevel: 0
INIT: Sending processes the TERM signal
Terminated
INIT: Sending processes the KILL signal
Dismounting local filesystems.
Remounting / as read-only.
Flushing disk cache.
Initiating system halt.
System halted.
</screen></para>
    </sect2>
  </sect1>
</chapter>
