Customizing Red Hat Linux 6.1 for Nomad-series robots

Jake Sprouse (jake@robots.com)
Nomadic Technologies, Inc.
22 February 2000


This document describes how to modify an installation of Red Hat Linux version 6.1 for use with Nomad-series robots. It supplements the hard drive upgrade instructions for your particular robot type. There are typically three major steps to upgrading your hard drive:

  • Install Red Hat Linux;
  • Configure for read-only operation so that the system is unaffected by sudden power losses; and,
  • Install software for your particular robot type.
  • Steps (1) and (3) will be described in the upgrade instructions for your robot. This document provides instructions for step (2).

    Configuring the system for read-only operation is difficult because many of the Red Hat packages expect to be able to write configuration files. The installation used on a robot's hard drive is minimal compared to a full workstation configuration, reducing the number of packages that need write access. However, if the user chooses to install other packages on the hard drive, he will have to be aware of their individual requirements and take the necessary steps to accommodate them in a read-only environment.

    Our basic strategy is to move the /var filesystem to a RAM disk and configure each package to use it for any non-read-only requirements they might have. Starting with the base installation above, the following steps should be performed:

    Recompile the kernel (optional)

    But first, if you are comfortable recompiling the kernel, we recommend doing so in order to remove support for SMP and RAID devices. You can also remove support for "initrd" (initial RAM-disk) images. However, this step has the potential to make your system unusable. It is optional and will not significantly affect system performance. If you opt to perform this step, you should start with one of the default configuration in /usr/src/linux/configs/ (most likely the configuration file for non-SMP systems). Be careful that if you remove support for initrd images, you do not inadvertently remove support for normal RAM disks, which we will need to make our system power-down safe.

    After you recompile your kernel, the "depmod" program may report many modules with unresolved symbols. These modules can be deleted from the system as they are no longer needed.

    Move the RPM database

    The RPM database was moved from /var/lib/rpm to /home/rpm to reduce the space requirements of the RAM disk. The database will only need to be written when packages are being updated or installed, in which case the root filesystem will need to be remounted in read/write mode anyway. This operation required the following:

    Symlink /tmp to /var/tmp

    Many packages write to the /tmp directory during normal operation, so it must be moved under /var. The installation log file /tmp/install.log was discarded. Then the /tmp directory was deleted and replaced with a symlink to /var/tmp.

    # cd /tmp
    # rm install.log
    # cd ..
    # rm -rf /tmp
    # ln -s /var/tmp /tmp
    

    Edit /etc/rc.d/rc.sysinit

    rc.sysinit controls the initial mounting of filesystems. The following was added immediately after the point in the script where the root filesystem is remounted in read-write mode:

    # Add a ramdisk at /var/
    mke2fs /dev/ram >/dev/null
    mount /dev/ram /mnt/other
    cp -pR /var/* /mnt/other
    umount /mnt/other
    mount /dev/ram /var
    

    This code creates a RAM disk, copies the /var filesystem to it, and then replaces the /var filesystem with it. It requires the mount point /mnt/other to exist:

    # mkdir /mnt/other
    

    Add the "readonly" initscript

    The following script should be added as /etc/rc.d/init.d/readonly, and it should be made executable:

    #!/bin/bash
    #
    # readonly      Mount IDE harddrive filesystems as read-only
    #
    # Authors:	Jake Sprouse 
    #
    # chkconfig: 345 25 75
    # description:  Remounts currently mounted /dev/hd* as read-only
    
    # Function to do the remount
    remount() {
    	RET=0
    	for name in $1; do
    		! mount -n -o remount,$2 $name && let RET=$RET+1
    	done
    	return $RET
    }
    
    # Source function library.
    . /etc/rc.d/init.d/functions
    
    FSLIST=`mount | grep "/dev/hd" | awk '{ print $1 }'`
    
    # See how we were called.
    case "$1" in
      start)
    	if [ -n "$FSLIST" ]; then
    	    if remount "$FSLIST" ro; then
    		action "Remounting HDD filesystems as read-only" /bin/true
    	    else
    		action "Remounting HDD filesystems as read-only" /bin/false
    	    fi
    	fi
    	touch /var/lock/subsys/readonly
    	;;
      stop)
    	if [ -n "$FSLIST" ]; then
    	    if remount "$FSLIST" rw; then
    		action "Remounting HDD filesystems as read-write" /bin/true
    	    else
    		action "Remounting HDD filesystems as read-write" /bin/false
    	    fi
    	fi
    	rm -f /var/lock/subsys/readonly
    	;;
      *)
    	echo "Usage: readonly {start|stop}"
    	exit 1
    esac
    
    exit 0
    

    This script is used to switch from read-write mode to read-only mode and back. We wish to enter read-only mode as the last step of every runlevel except for 0 (halt) and 6 (reboot). We will need to make sure we're in read-write mode as the first step of entering every runlevel. Therefore, the following symlinks must be created in order to enable the readonly script:

    /etc/rc.d/rc0.d/K00readonly --> /etc/rc.d/init.d/readonly
    /etc/rc.d/rc1.d/K00readonly --> /etc/rc.d/init.d/readonly
    /etc/rc.d/rc1.d/S99readonly --> /etc/rc.d/init.d/readonly
    /etc/rc.d/rc2.d/K00readonly --> /etc/rc.d/init.d/readonly
    /etc/rc.d/rc2.d/S99readonly --> /etc/rc.d/init.d/readonly
    /etc/rc.d/rc3.d/K00readonly --> /etc/rc.d/init.d/readonly
    /etc/rc.d/rc3.d/S99readonly --> /etc/rc.d/init.d/readonly
    /etc/rc.d/rc4.d/K00readonly --> /etc/rc.d/init.d/readonly
    /etc/rc.d/rc4.d/S99readonly --> /etc/rc.d/init.d/readonly
    /etc/rc.d/rc5.d/K00readonly --> /etc/rc.d/init.d/readonly
    /etc/rc.d/rc5.d/S99readonly --> /etc/rc.d/init.d/readonly
    /etc/rc.d/rc6.d/K00readonly --> /etc/rc.d/init.d/readonly
    

    Note that this script can be run during normal operation if you have a need to write to the Scout's hard drive. For example, to remount all partitions as read/write:

    # /etc/rc.d/init.d/readonly stop
    

    Or, to go back to read-only mode:

    # /etc/rc.d/init.d/readonly start
    

    Edit /etc/rc.d/init.d/halt

    The /etc/rc.d/init.d/halt script was modified so that it will not attempt to unmount the /dev/ram filesystem when halting or rebooting the system. To accomplish this, those lines which search for filesystems to unmount were modified:

    Line 68:

    remaining=`awk '!/(^#|proc|^none|^\/dev\/root|^\/dev\/ram)/ {print $2}' /proc/mounts`
    

    Line 77:

    remaining=`awk '!/(^#|proc|^none|^\/dev\/root|^\/dev\/ram)/ {print $2}' /proc/mounts`
    

    Disable /etc/rc.d/rc.local

    In the default configuration, every runlevel besides 0 (halt) and 6 (reboot) have this symlink:

    /etc/rc.d/rcN.d/S99local --> /etc/rc.d/rc.local
    

    This runs the /etc/rc.d/rc.local script as the last step of each runlevel. The only function of this script is to create the /etc/issue and /etc/issue.net files when booting the machine. This operation will fail if the root filesystem is in readonly mode and therefore must be disabled. Disabling this script will have no effect, as the issue files rarely change. To disable it, delete the following symlinks:

    /etc/rc.d/rc1.d/S99local
    /etc/rc.d/rc2.d/S99local
    /etc/rc.d/rc3.d/S99local
    /etc/rc.d/rc4.d/S99local
    /etc/rc.d/rc5.d/S99local
    

    Move the catman files

    The default RedHat installation puts the temporary man files (catman files) under /var/catman. These were moved to the default location (MANPATH) by editing /etc/man.config and commenting out the line which defines the FSSTND macro. After this step, the directory /var/catman can be removed.

    Move the /dev/tty device nodes

    The console login prompts are presented by the mingetty program after the bootscripts have completed. This program accesses the /dev/tty0 through /dev/tty7 devices, and the first operations it performs are chown() and chmod() in order to make sure that the owner of the device is root, the group is root, and the device is not readable, writable, or executable by anyone other than root. This is for security reasons. Unfortunately, if the filesystem on which the tty device nodes reside is mounted as read-only, these operations will fail. So these device nodes must be moved to the ramdisk, under the /var/ directory. To do this, perform the following:

    # mkdir /var/dev
    # mv /dev/tty[0-9]* /var/dev
    # cd /var/dev
    # for name in *; do 
    > ln -s /var/dev/$name /dev/$name
    > done
    

    Test your configuration

    Now, reboot the robot and verify that things boot properly. You should get a login prompt, and after you log in, verify that the HDD filesystems were mounted read-only. You should see the following lines:

    # cat /proc/mounts
    /dev/root / ext2 ro 0 0
    /proc /proc proc rw 0 0
    /dev/ram /var ext2 rw 0 0
    /dev/hda1 /boot ext2 ro 0 0
    none /dev/pts devpts rw 0 0
    

    Both the halt and reboot commands should function normally, and not produce any error messages.


    Last modified 13 March 2000 by jake