Overview of Class Three

by Torleif Mohling
CU Boulder, dept of Computer Science
(04/17/2000)

0 Contents

1 Booting Up, Runlevels, Shutting Down

If your computer is set up properly, booting may be as simple as turning the machine on. A runlevel is a System-V concept and has to do with the state that a machine is booted into; these range from runlevel 0 through to runlevel 6. BSD-like machines don't really have a `runlevel' concept. Instead they simply have single-user and multi-user modes.

Why is it necessary to carefully shutdown a unix system? In terms of just hardware, a sudden power outage could cause physical damage to your hard disk drives. The biggest reason from the point of view of the OS is also disk-related. Buffers holding recent changes to files on disk are kept in the machines RAM; these buffers are regularly flushed to disk. If the power outage occurs just before these buffers are flushed, then possibly significant data may not be represented on disk, resulting in a corrupted filesystem. Other reasons, on a multi-user boxes include annoyed users with un-written editor buffers and long-running processes that don't adequately checkpoint their activity and have good recovery..

The moral is: never turn off or reset a unix machine unless you absolutely have to. There are times when such draconian measures are called for, but only as a very last resort.

By the way, any user can use the sync command to force the filesystem updates to occur. (Often repeated two or three times and followed by halt for superstitious historical reasons :)

2 Booting

First lets talk about booting up some different kinds of machines. I am not going to talk about hardware specifically, although I will probably mention a few things.. next class will focus more on the hardware specifically (disks at least!).

It is of course always a good idea to have everything appropriately plugged in and connected to clean, grounded power. It's also wise to turn on your peripheral devices first, e.g. monitor, printer etc. Then power up the box.

2.1 Sparc OpenBoot

Sparc machines, except some crufty old ones, have a nice firmware which is sort of like a BIOS on a PC. It is called OpenBoot. Many folks refer to such a system as a boot ROM The machine powers on and runs through a POST (Power On Self Test). It then displays a banner describing the firmware version, MAC address of the machine, its hostid , and RAM. One Meg of RAM or more is tested, initialized and then either 1) you are dumped to the ok prompt or 2) the OS is automatically booted. At the ok prompt you can use the banner command to re-print the initially presented machine information:

    ok banner
    SPARCstation 5, No Keyboard
    ROM Rev. 2.24, 72 MB memory installed, Serial #8192563.
    Ethernet address 8:0:20:7d:2:33, Host ID: 807d0233.
You can interrupt the boot sequence and return to the ok prompt by striking the <L1>-A key combination; newer Sun keyboards have re-labeled the <L1> key to be <stop>. In either case it is in the upper left-hand corner of a Sun keyboard.

Solaris and SunOS (an older version of Un*x, no longer supported by Sun, it was BSD based) can be halted at anytime with <L1>-A key sequence. Some of you might also have notice, while using the Sun Ultra machines in the CSEL lab that one is dumped to the ok prompt if the keyboard is unplugged and then re-inserted. It is possible to type go at this point and resume execution of the OS without any damage. This actually no longer happens to the lab machines - it is possible to disable the keyboard break sequence: under Solaris edit the /etc/default/kbd file and comment out the following line in that file:

    #KEYBOARD_ABORT=enable
Under Sparc OpenBSD the break is disabled by default. To enable it under OpenBSD you need to turn on a kernel variable in the /etc/sysctl.conf file:

    ddb.console=1

The OpenBoot facility, depending on firmware revision will have varying degrees of functionality. The firmware is apparantly compliant with an IEEE standard (1275-1994) meaning it is theoretically platform independent. If you visit Sun's document website, see: http://docs.sun.com and do a search on openboot you can view the OpenBoot 3.x Command Reference that will tell you all about it! There is a full-featured programming language called forth that is supported by OpenBoot, but I am not going to show you how to do that! (It's for true guru's only :)

Anyway there are a number of useful commands to remember. First of all, similar to your Un*x shell, in the OpenBoot system you have an enivonment which can be displayed and changed in a similar fashion. Use the printenv command to display the environment variables; use setenv to change them:

    ok printenv
    Parameter Name        Value                  Default Value

tpe-link-test? true true output-device ttya screen input-device ttya keyboard keyboard-click? false false keymap ttyb-rts-dtr-off false false ttyb-ignore-cd false true ttya-rts-dtr-off false false ttya-ignore-cd false true ttyb-mode 9600,8,n,1,- 9600,8,n,1,- ttya-mode 9600,8,n,1,- 9600,8,n,1,- fcode-debug? false false local-mac-address? false false screen-#columns 80 80 screen-#rows 34 34 selftest-#megs 40 1 scsi-initiator-id 7 7 silent-mode? false false auto-boot? true true watchdog-reboot? true false More [<space>,<cr>,q] ?

diag-file diag-device net net boot-file boot-device disk disk net sbus-probe-list 541230 541230 use-nvramrc? false false nvramrc sunmon-compat? false false security-mode none none security-password security-#badlogins 0 <no default> oem-logo <no default> oem-logo? false false oem-banner <no default> oem-banner? false false hardware-revision <no default> last-hardware-update <no default> testarea 0 0 mfg-switch? false false diag-switch? false false ok

If you need to `reset' the machine in order to run `probe-scsi' (this can occur on UltraSparc systems) then you need to turn the auto-boot? variable to false, then reset the system..

    ok setenv auto-boot? false
    auto-boot? = false
    ok reset
    ...
I mentioned the POST tests earlier; in general the output of these tests is not displayed. There are occasions where you need to see it though. Some machines will have a diagnostic switch that may be flipped before you power on the box. You may also set the diag-switch? environment variable to true to achieve the same effect. Here is an example:

    ok setenv diag-switch? true
    diag-switch? =        true
    ok reset
    Resetting ... 
    initializing TLB
    initializing cache

Allocating SRMMU Context Table Setting SRMMU Context Register Setting SRMMU Context Table Pointer Register Allocating SRMMU Level 1 Table Mapping RAM Mapping ROM

ttya initialized Probing Memory Bank #0 32 Megabytes Probing Memory Bank #1 32 Megabytes Probing Memory Bank #2 8 Megabytes Probing Memory Bank #3 Nothing there Probing Memory Bank #4 Nothing there Probing Memory Bank #5 Nothing there Probing Memory Bank #6 Nothing there Probing Memory Bank #7 Nothing there Probing CPU FMI,MB86904 Probing /iommu@0,10000000/sbus@0,10001000 at 5,0 espdma esp sd st SUNW,bpp ledma le Probing /iommu@0,10000000/sbus@0,10001000 at 4,0 SUNW,CS4231 power-management Probing /iommu@0,10000000/sbus@0,10001000 at 1,0 Nothing there Probing /iommu@0,10000000/sbus@0,10001000 at 2,0 Nothing there Probing /iommu@0,10000000/sbus@0,10001000 at 3,0 cgsix Probing /iommu@0,10000000/sbus@0,10001000 at 0,0 Nothing there SPARCstation 5, No Keyboard ROM Rev. 2.24, 72 MB memory installed, Serial #8192563. Ethernet address 8:0:20:7d:2:33, Host ID: 807d0233.

Type help for more information ok

Note that to see this output you need to have a serial console hooked up to serial-port-A of the Sparc machine. (I.e the POST messages are not printed to a Sun graphical-console. If there are errors, however, you may view them with the show-post-results command.

All older Sun machines have SCSI (Small Computer System Interface) for I/O. Some newer Sun Ultra machines (like the ones in the lab) have PCI buses and IDE disks. We'll talk more about that next class. For now, note the command probe-scsi and for machines with more than one SCSI bus, the probe-scsi-all commands. The few Sun machines that have IDE disks in them also have the probe-ide command. Here is an example:

    ok probe-scsi
    Target 3 
      Unit 0   Disk     CONNER  CFP2107E  2.14GB1524
    Target 6 
      Unit 0   Removable Read Only device     TOSHIBA XM-4101TASUNSLCD175506/24/95
There are a lot of other useful commands at your fingertips in the OpenBoot environment. If you can't remember the whole name of a command, then remember this one: sifting . The sifting command is like grep in that it will return the names of all commands with a given word in them:

    ok sifting probe
    sbus-probe-list probe-all probe-sbus probe-slots probe-slot probe-scsi-all
    probe-scsi probe probe-virtual probe-fpu lprobe wprobe cprobe 
    ok 
Another command that lists out possible commands for the node where you are in the OpenBoot (explained below) is the words command. Now, OpenBoot builds a virtual device-tree that consists of all the devices on the machine that the OpenBoot recognizes. You use the show-devs command to list out the device tree:

    ok show-devs
    /FMI,MB86904
    /virtual-memory@0,0
    /memory@0,0
    /obio
    /iommu@0,10000000
    /openprom
    /aliases
    /options
    /packages
    /obio/SUNW,fdtwo@0,400000
    /obio/power@0,910000
    /obio/interrupt@0,e00000
    /obio/counter@0,d00000
    /obio/auxio@0,900000
    /obio/slavioconfig@0,800000
    /obio/eeprom@0,200000
    /obio/zs@0,0
    /obio/zs@0,100000
    /iommu@0,10000000/sbus@0,10001000
    /iommu@0,10000000/sbus@0,10001000/cgsix@3,0
    /iommu@0,10000000/sbus@0,10001000/power-management@4,a000000
    /iommu@0,10000000/sbus@0,10001000/SUNW,CS4231@4,c000000
    More [<space>,<cr>,q] ? 
You can use the cd and ls commands to traverse the device tree:

    ok cd /
    ok words
    decode-unit   decode-space  map-out       map-in        close 
    open 
    ok ls
    ffd3c19c FMI,MB86904
    ffd2d184 virtual-memory@0,0
    ffd2d0c8 memory@0,0
    ffd2c3fc obio
    ffd2c128 iommu@0,10000000
    ffd2c0b8 openprom
    ffd24ed4 aliases
    ffd24ea0 options
    ffd24e6c packages
    ok cd iommu
    ok words
    decode-unit   decode-space  map-in        close         open 
    ok ls
    ffd2c26c sbus@0,10001000
    ok 
The OpenBoot allows you to create aliases that point to specific devices in the device tree. Use the devalias command to list default/available aliases:

    ok sifting alias
    makealias nvunalias $nvunalias nvalias $nvalias devalias $devalias 
    aliases alias setalias flagalias 
    ok devalias
    screen         /iommu@0,10000000/sbus@0,10001000/cgsix@3,0
    ttyb           /obio/zs@0,100000:b
    ttya           /obio/zs@0,100000:a
    keyboard!      /obio/zs@0,0:forcemode
    keyboard       /obio/zs@0,0
    audio          /iommu/sbus/SUNW,CS4231
    floppy         /obio/SUNW,fdtwo
    scsi           /iommu/sbus/espdma@5,8400000/esp@5,8800000
    net-aui        /iommu/sbus/ledma@5,8400010:aui/le@5,8c00000
    net-tpe        /iommu/sbus/ledma@5,8400010:tpe/le@5,8c00000
    net            /iommu/sbus/ledma@5,8400010/le@5,8c00000
    disk           /iommu/sbus/espdma@5,8400000/esp@5,8800000/sd@3,0
    cdrom          /iommu/sbus/espdma@5,8400000/esp@5,8800000/sd@6,0:d
    tape           /iommu/sbus/espdma@5,8400000/esp@5,8800000/st@4,0
    tape0          /iommu/sbus/espdma@5,8400000/esp@5,8800000/st@4,0
    tape1          /iommu/sbus/espdma@5,8400000/esp@5,8800000/st@5,0
    disk3          /iommu/sbus/espdma@5,8400000/esp@5,8800000/sd@3,0
    disk2          /iommu/sbus/espdma@5,8400000/esp@5,8800000/sd@2,0
    disk1          /iommu/sbus/espdma@5,8400000/esp@5,8800000/sd@1,0
    disk0          /iommu/sbus/espdma@5,8400000/esp@5,8800000/sd@0,0
    ok  
Now, look back at the boot-device environment variable and you will see that it makes use of one of the above aliases:

    ok printenv boot-device
    boot-device =         disk
Finally, the boot command is used to boot the machine. With no arguments it will try and boot a kernel from the default boot-device. You may specify an alternate device, as in:

    ok boot cdrom 2.8/sparc/bsd.rd
    ...

2.2 PC BIOS

I am not going to really cover all the details of the myriad PC BIOS systems that are out there. For the most part, I assume most of you are familiar with them, at least from a user point of view.. The BIOS is an API (Application Programming Interface) between higher level software (like an OS) and the PC hardware. One of the main things you will need to set in your machine's BIOS is the default boot media, or the order in which a set of media types are checked for bootable magic numbers (i.e. floppy, cdrom, hard-disk). Many BIOSes suffer from an inability to deal with hard disks larger than a few Gigabytes and this deficiency manifests most acutely when it comes to booting off of one of those disks. This problem can sometimes get quite ugly. The safest thing, if you have a BIOS with such a problem, is to make sure the bootable partition lies entirely within the first 1024 cylinders of the disk (we'll look at partitioning more in-depth next class.)

In both the case of the Sparc OpenBoot ROM and the PC BIOS ROM what you are interacting with is a minimal set of instructions that can be stored in some kind of Read-Only-Memory. Most of the time, except with very old hardware, these instructions (called firmware ) reside in a re-writable storage device that can save data through loss-of-power (maybe with the help of a battery). Some devices are called EPROMS (or Erasable Programmable Read Only Memory). The problem with PROMs is that you need a special encoder to rerase and program them. Most PCs today have NVRAM (Non- Volitile RAM) that can updated using a special BIOS upgrade program that is run from a floppy. A battery is used to maintain state in the NVRAM.

2.3 Bootstrapping

The details of the bootstrap procedure is very architecture dependent and way beyond the scope of the class. Briefly, then, I'll describe what is meant by it.

You all understand that the CPU is solely capable of executing the "next instruction" that it finds in its instruction register, so how does the Operating System get loaded into memory and begin functioning?

Boot ROM systems like the PC BIOS or the OpenBoot provide a facility called primary bootstrapping also known as a "first-stage" bootloader. With the PC BIOS, many of you may have changed the order in which various devices are checked to be booted from. E.g:

    C, A, CDROM
would try your hard drive first, then your floppy drive, and then your CDROM. What is happening is that the BIOS is searching for a short multi-byte sequence at a specfic place on the target media. If such a sequence is found, then that media is considered bootable and the block of data of which the sequence is a part is fed to the CPU with the assumption that it contains valid machine code. If it doesn't, your machine will quickly hang solid and need to be reset in some fashion.

Frequently the first chunk of code that gets schlepped in from the target boot media is also referred to as a primary bootstrap, while there may also be multiple levels of boot-loading depending on what boot-loaders you are using and what OS's you have on your machine - i.e. a dual-boot machine. The job of the primary bootstrap is basically to load another program, known as a secondary bootstrap or second-stage bootloader.

The Sparc's OpenBoot system behaves similarly, except that, as you have seen, you have a lot more control over what happens.

Many of you have heard of LILO from the linux world. Lilo is a what I call a second stage boot loader, but its functionality sort of lies in between the primary and secondary boot systems on an OpenBSD PC.

This may all be a bit confusing, and it is! The flow of events is totally dependent on what hardware you have, and there isn't even a standard to speak of in PC land (that I know of). It comes down to knowing what is basically going on for all of the different machines you are using.

2.3.1 OpenBSD boot

For the PC architecture, called i386 in the vernacular, There are two basic stages. First, the BIOS determines that your disk is bootable (of course assuming that everything has already worked!) and loads that first program (read the biosboot(8) manpage on an OpenBSD box). It is a very small chunk of code (256 bytes!) whose sole purpose is to load and run the second stage program (read the boot(8) manpage on an OpenBSD PC box - like saclass-3).

The OpenBSD boot program has more smarts, approaching the facility of the OpenBoot ROM to some degree. From the manpage:

    Basic operations include:
    o   Detecting and switching between multiple consoles.
    o   Loading kernels from any device supported by your system BIOS.
    o   Loading kernels compressed by gzip(1).
    o   Passing system parameters queried from the BIOS to the kernel.
    o   Providing an interactive command line.
It may be configured to provide a desired behavior different from the default by entering commands in the file /etc/boot.conf. Most importantly, the boot program locates and loads the bsd kernel.

2.3.2 Linux LILO

Lilo is the Linux Boot Loader that one most commonly encounters. Another is called 'loadlin'. Its function is similar to what we have been discussing so far. It is less versatile than the OpenBSD or OpenBoot systems, in that, while booting may occur from the same possible devices, one must configure lilo ahead of time. It keeps a mapping of possible boot locations that is generated from the file /etc/lilo.conf using the command /sbin/lilo . It is more versatile than the OpenBSD bootloader is other ways though. For example, lilo is nice because it may be configured to boot a number of different OSs as well as different kernels from the same boot device. It can be configured to boot any BSD system as well as Windows 9x (but not Windows NT, at least not easily ;).

Here is a typical lilo.conf file from a PC running only linux:

    dwarf % cat /etc/lilo.conf
    boot=/dev/hda
    map=/boot/map
    install=/boot/boot.b
    prompt
    timeout=50
    default=linux

image=/boot/vmlinuz-2.2.12-20 label=linux initrd=/boot/initrd-2.2.12-20.img read-only root=/dev/hda10

And here is one from a dual boot system with DOS:

    boot = /dev/hda   # or your root partition
    delay = 10        # delay, in tenth of a second (so you can interact)
    vga = 0           # optional. Use "vga=1" to get 80x50
    #linear           # try "linear" in case of geometry problems.

image = /boot/vmlinux # your zImage file root = /dev/hda1 # your root partition label = Linux # or any fancy name read-only # mount root read-only

other = /dev/hda4 # your dos partition, if any table = /dev/hda # the current partition table label = dos # or any non-fancy name

2.3.3 Other Bootloaders

3 Dmesg

As the Un*x kernel boots, it outputs information about its process to the default console. This information is called dmesg output and most versions of Un*x supply a 'dmesg' command to display these messages at any time. Let's have a look:

    quetzel % dmesg
    OpenBSD 2.6 (GENERIC) #694: Sun Oct 31 21:08:41 MST 1999
        deraadt@i386.openbsd.org:/usr/src/sys/arch/i386/compile/GENERIC
    cpu0: F00F bug workaround installed
    cpu0: Intel Pentium (P54C) ("GenuineIntel" 586-class) 100 MHz
    cpu0: FPU,V86,DE,PSE,TSC,MSR,MCE,CX8
    BIOS mem  = 654336 conventional, 24313856 extended
    real mem  = 24969216
    avail mem = 18976768
    using 330 buffers containing 1351680 bytes of memory
    mainbus0 (root)
    bios0 at mainbus0: AT/286+(63) BIOS, date 02/24/99
    bios0: diskinfo 0xe055800c cksumlen 1 memmap 0xe0558088 apminfo 0xe05580d0
    apm0 at bios0: Power Management spec V1.1
    apm0: battery life expectancy 38%
    apm0: AC on, battery charge low, charging, estimated 0:58 minutes
    isa0 at mainbus0
    isadma0 at isa0
    wdc0 at isa0 port 0x1f0/8 irq 14
    wd0 at wdc0 channel 0 drive 0: <HITACHI_DK237A-32>
    wd0: can use 16-bit, PIO mode 4
    wd0: 16-sector PIO, LBA, 3102MB, 6304 cyl, 16 head, 63 sec, 6354432 sectors
    wdc1 at isa0 port 0x170/8 irq 15
    atapiscsi0 at wdc1 channel 0
    scsibus0 at atapiscsi0: 2 targets
    cd0 at scsibus0 targ 0 lun 0: <TOSHIBA, CD-ROM XM-1402B, 0186> SCSI0 5/cdrom removable
    cd0: can use 16-bit, PIO mode 3
    sb0 at isa0 port 0x220/24 irq 5 drq 1: dsp v3.01
    midi0 at sb0: <SB MIDI UART>
    audio0 at sb0
    opl0 at sb0: model OPL3
    midi1 at opl0: <SB Yamaha OPL3>
    pcppi0 at isa0 port 0x61
    midi2 at pcppi0: <PC speaker>
    sysbeep0 at pcppi0
    lpt0 at isa0 port 0x378/4 irq 7
    npx0 at isa0 port 0xf0/16: using exception 16
    pccom0 at isa0 port 0x3f8/8 irq 4: ns16550a, 16 byte fifo
    vt0 at isa0 port 0x60/16 irq 1: generic VGA, 80 col, color, 8 scr, mf2-kbd
    pms0 at vt0 irq 12
    fdc0 at isa0 port 0x3f0/6 irq 6 drq 2
    pcic0 at isa0 port 0x3e0/2 iomem 0xd0000/16384
    pcic0 controller 0: <Intel 82365SL rev 1> has sockets A and B
    pcmcia0 at pcic0 controller 0 socket 0
    pcmcia1 at pcic0 controller 0 socket 1
    xe0 at pcmcia1 function 0 "Xircom, CreditCard 10Base-T, PS-CE2-10" port 0x340/16 irq 3: address 00:80:c7:f7:5c:bf
    pcic0: irq 9
    biomask c040 netmask c048 ttymask d2ca
    pctr: 586-class performance counters and user-level cycle counter enabled
    dkcsum: wd0 matched BIOS disk 80
    root on wd0a
    rootdev=0x0 rrootdev=0x300 rawdev=0x302
We have discussed the output of dmesg several times in class. To reiterate, it is diagnostic output from the kernel as it probes the system and finds certain devices. Information about each device is printed. Generally, the name of the device driver is given first with an associated instance number followed by specific information about the device. For example,

    wdc0 at isa0 port 0x1f0/8 irq 14
This message is about wdc the IDE disk controller. You can frequently find a manpage for the device, e.g. wdc(4). Relevant information like what irq is associated with the device is usually given.

Following this message are listed devices controlled by the wdc device:

    wd0 at wdc0 channel 0 drive 0: <HITACHI_DK237A-32>
    wd0: can use 16-bit, PIO mode 4
    wd0: 16-sector PIO, LBA, 3102MB, 6304 cyl, 16 head, 63 sec, 6354432 sectors
This is a hard disk, as you can probably guess, because geometry information is given about the disk. To find out what the other devices are, see if there is a manpage available for each one.

At this point the kernel is loaded, and it has finished probing for devices. The kernel then starts the init process - read init(8) - which is the grandparent of all other processes on the machine. You should still see additional information printed to the console - this time though you are seeing messages from various daemons as they are started up by init.

4 BSD vs ATT Startup Files, Runlevels and Init

A fundamental difference between BSD-style machines and AT&T/Sys V-style machines is in their start-up file organization.

In a BSD system there are really only two runlevels: single user mode and multi user mode. One determines which mode to boot into at boot time or reboot time. I'll talk about single user mode later.

4.1 OpenBSD Startup

The OpenBSD startup files are:

The /etc/rc script is heart of the 'BSD startup. It's general behavior (i.e. which services get started) is determined by the /etc/rc.conf file. The config file is very straight-forward and has comments to help you turn on (or off) services correctly. Here is part of it:

    saclass:etc {163} head /etc/rc.conf
    #!/bin/sh -
    #
    #       $OpenBSD: rc.conf,v 1.53 2000/10/16 14:57:13 aaron Exp $

# set these to "NO" to turn them off. otherwise, they're used as flags routed_flags=NO # for normal use: "-q" mrouted_flags=NO # for normal use: "", if activated # be sure to enable multicast_router below. rarpd_flags=NO # for normal use: "-a" bootparamd_flags=NO # for normal use: ""

So, to turn on routed you would change the config line to read:

    routed_flags="-q"
The /etc/rc script also processes the /etc/netstart file which (as you can probably guess) starts up networking for OpenBSD. The netstart script is in turn configured by the following files:

The /etc/hostname.<interface> file gives either the IP address and netmask for the indicated network interface, or it specifies that DHCP should be used to acquire an IP address. We will explore these files more when we talk about networking.

The /etc/rc.local script-file is used for adding in local services that should be started at boot-time. Another important file that is processed at boot time is the /etc/sysctl.conf file which contains a list of kernel variables that need to be set with non-default values. For example, if your OpenBSD box has two network interfaces and is being used as a router then you need to turn on a specific kernel variable (to enable IP forwarding):

    net.inet.ip.forwarding=1

4.2 Sys-V Startup

SysV based machines have a different concept of runlevel, and in some ways it is easier to manage and is more flexible than the BSD system. Such a machine has a file called /etc/inittab that determines the default runlevel that the machine will boot into, as well as a number of other things. Before looking at that file though, lets look at the directory structure of the SYS-V style startup files.

First let's look at a Solaris machine, which has what I consider to be a standard SysV setup. The directory /etc/init.d has individual startup scripts for each service that could be run on the machine:

    bfs:tor % ls /etc/init.d
    ANNOUNCE*               devlinks*               rootusr*
    MOUNTFSYS*              dhcp*                   rootusr.old*
    PRESERVE*               drvconfig*              rpc*
    README                  dtlogin*                rpc.old*
    RMTMPFILES*             flashprom*              savecore*
    acct*                   inetinit*               sendmail*
    afbinit*                inetsvc*                spc*
    asppp*                  inetsvc.DIST*           standardmounts*
    audit*                  init.dmi*               sybstart*
    autofs*                 init.snmpdx*            sysetup*
    autofs.old*             initpcmcia*             sysid.net*
    autoinstall*            keymap*                 sysid.sys*
    buildmnttab*            lp*                     syslog*
    buttons_n_dials-setup*  mkdtab*                 syslog.old*
    cachefs.daemon*         nfs.client*             tsquantum*
    cachefs.root*           nfs.client.old*         tsquantum.old*
    cacheos*                nfs.server*             ufs_quota*
    cacheos.finish*         nscd*                   utmpd*
    coreadm*                pcmcia*                 uucp*
    coreadm.old*            pcmcia.old*             volmgt*
    cron*                   percol*                 volmgt.old*
    cvc*                    perf*                   xntpd*
    devfsadm*               power*
Conventionally, and at a minimum, each of these scripts should be invocable with the following arguments:

    /etc/init.d/<script> start      to start the service
    /etc/init.d/<script> stop       to halt the service
Other possible arguments are restart and reload and possibly others, it is script-dependant.

Now, runlevels. Solaris defines a runlevel as "a software configuration under which only a selected group of processes exists"; but this doesn't really define what each level means, beyond the fact that levels 0 5 and 6 are for shutting down, while 2 3 and 4 are for multi-user operation. This leaves level 1 for single user. Typically, for Solaris, runlevel 2 is for "multi-user without NFS" and runlevel 3, then is multi-user with NFS. Some folks claim the distinction is instead "without (2) or with (3) networking". Whatever, it really just comes down to what is in the /etc/inittab file and what services you decide to link into a given runlevel directory (these are described in the next paragraph).

Each runlevel, N, has a corresponding /etc/rcN.d directory. Here is /etc/rc2.d on a typical Solaris machine:

    duos:saclass % ls /etc/rc2.d
    K07dmi*             S71rpc*             S75cron*            S92volmgt*
    K07snmpdx*          S71sysid.sys*       S75savecore*        S93cacheos.finish*
    K28nfs.server*      S72autoinstall*     S76nscd*            S99audit*
    README              S72inetsvc@         S80PRESERVE*        S99tsquantum*
    S01MOUNTFSYS*       S73cachefs.daemon*  S80kdmconfig*       s74autofs*
    S05RMTMPFILES*      S73nfs.client*      S80spc*             s76snmpdx*
    S20sysetup*         S74syslog*          S85power*           s80lp*
    S30sysid.net*       S74xntpd*           S88sendmail*
    S69inet*            S75amd@             S88utmpd*
Each file starts with an S or a K indicating whether the service should be Started or Killed, respectively. The two digits following define the order in which services are started. Two or more services with the same number, have "no defined order" amongst themselves (although alphabetic is probably a good guess ;). Each of the files in the /etc/rcN.d directories are links to the actual scripts in /etc/init.d. Under Solaris the links are hardlinks whereas under RedHat they are symlinks (man ln(1) to see the difference). With Solaris, also, if e.g. the default run level is 3 then then runlevels 1 and 2 are started first.

RedHat's startup files are predominantly of the SysV variety. However the organization is different. All of RedHat's startup scripts live in the directory /etc/rc.d/init.d and the runlevel directories are in /etc/rc.d/rcN.d

The chkconfig(8) program available with RedHat is a handy way to manage the script file and symlinks in the /etc/rc.d/ tree. For example,

    schwinn % chkconfig --list sshd
    sshd            0:off   1:off   2:on    3:on    4:on    5:on    6:off
The runlevels in which sshd will be started are indicated, e.g. 2:on . Startup scripts need to have special config information in their comment headers in order for chkconfig to function on them. Here is the comment header for the sshd startup script:

    #!/bin/sh
    #
    # chkconfig: 2345 70 30
    # description: starts and stops the SSH daemon
    # pidfile: /etc/ssh/sshd.pid
    #
You can see the comment line that chkconfig uses; it indicates that the script should be started up in runlevels 2, 3, 4, and 5, and that the `start' script should be called S70sshd and the `kill' script should be called K30sshd.

You can always just do an ls -l of the startup script link to see at what init.d script it points to. For example:

    xibalba % cd /etc/rc.d/rc5.d
    xibalba % ls -l S55sshd 
    lrwxrwxrwx    1 root     root           14 Jan  7 12:06 S55sshd -> ../init.d/sshd*
On a Solaris box, on the other hand, the links are hard links, so it is a little bit more complicated to see the associated startup script's location.

    bfs:tor % cd /etc/rc2.d
    bfs:rc2.d % ls -l S75cron
    -rwxr--r--   5 root     sys           504 Sep  1  1998 S75cron*
The key here is the link count (which is five - 5 - in the above example). And to find the associated files you need to get the inode number for the file and then use the find(1) command to find other filenames with the same inode. Here is an example:

    bfs:rc2.d % ls -li !$
    ls -li S75cron
    40568 -rwxr--r--   5 root     sys           504 Sep  1  1998 S75cron*
    bfs:rc2.d % cd ..
    bfs:etc % find . -inum 40568 -print
    ./init.d/cron
    ./rc0.d/K40cron
    ./rc1.d/K40cron
    ./rc2.d/S75cron
    ./rcS.d/K40cron

Now, the /etc/inittab file for RedHat:

    dwarf % cat /etc/inittab
    #
    # inittab       This file describes how the INIT process should set up
    #               the system in a certain run-level.
    #
    # Author:       Miquel van Smoorenburg, <miquels@drinkel.nl.mugnet.org>
    #               Modified for RHS Linux by Marc Ewing and Donnie Barnes
    #
    # Default runlevel. The runlevels used by RHS are:
    #   0 - halt (Do NOT set initdefault to this)
    #   1 - Single user mode
    #   2 - Multiuser, without NFS (The same as 3, if you do not have networking)
    #   3 - Full multiuser mode
    #   4 - unused
    #   5 - X11
    #   6 - reboot (Do NOT set initdefault to this)
    # 
    id:5:initdefault:
    # System initialization.
    si::sysinit:/etc/rc.d/rc.sysinit
    l0:0:wait:/etc/rc.d/rc 0
    l1:1:wait:/etc/rc.d/rc 1
    l2:2:wait:/etc/rc.d/rc 2
    l3:3:wait:/etc/rc.d/rc 3
    l4:4:wait:/etc/rc.d/rc 4
    l5:5:wait:/etc/rc.d/rc 5
    l6:6:wait:/etc/rc.d/rc 6
    # Things to run in every runlevel.
    ud::once:/sbin/update
    # Trap CTRL-ALT-DELETE
    ca::ctrlaltdel:/sbin/shutdown -t3 -r now
    # When our UPS tells us power has failed, assume we have a few minutes
    # of power left.  Schedule a shutdown for 2 minutes from now.
    # This does, of course, assume you have powerd installed and your
    # UPS connected and working correctly.  
    pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down"
    # If power was restored before the shutdown kicked in, cancel it.
    pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled"

    # Run gettys in standard runlevels
    1:2345:respawn:/sbin/mingetty tty1
    2:2345:respawn:/sbin/mingetty tty2
    3:2345:respawn:/sbin/mingetty tty3
    4:2345:respawn:/sbin/mingetty tty4
    5:2345:respawn:/sbin/mingetty tty5
    6:2345:respawn:/sbin/mingetty tty6
    # Run xdm in runlevel 5
    # xdm is now a separate service
    x:5:respawn:/etc/X11/prefdm -nodaemon
The first (non blank or comment) line in the above file determines the default runlevel that the machine boots into:

    id:5:initdefault:
The fields for each entry in the inittab file are: 1) an ID tag, 2) the runlevel in which the entry is triggered, 3) `how' the entry should be dealt with, and 4) an action to be taken, like a script to run or a process to invoke. Notice that at each runlevel the /etc/rc.d/rc script is invoked with the current runlevel as an argument. Other processes started out of the RedHat inittab file include the xdm X-windows logon process.

4.3 Single User Mode

Single user mode is a limited mode of accessing the operating system; the only method is via a shell on the system console.

Most system's require you to know the root password in order to get into single user mode. Single user mode generally implies that most filesystem partitions are unmounted except for maybe / and /usr. Additionally, no networking facilities should be turned on. The actual behavior varies depending on the OS. The mode is used for system maintenance like filesystem repair using the fcsk(8) command; some sites perform backups in single user mode which guarantees quiescent filesystems (i.e. no one is using the filesystem, it is unmounted).

To switch from single-user mode into multi-user mode (or a multi-user runlevel) you need to type <CTRL><D> (i.e. 'control-d') at the shell prompt. Type halt to instead bring the system all the way down.

5 Shutting Down

The following commands can be used to shutdown a unix-like OS. They are all available on a System-V like machine, while only the first three work on a 'BSD box. The behavior of each of the commands varies by OS as well. I'll mention some of the differences.

We have already talked about why it is important to not simply reset or power-cycle a unix box. All of the above commands will perform a sync of the filesystem state during the shutdown process. On OpenBSD and RedHat boxes, halt and reboot perform the same tasks that `shutdown' itself does when they are used instead. This includes running either the /etc/rc.shutdown script (on OpenBSD) or running the kill scripts in the relevant runlevel directory (on RedHat). These shutdown or kill scripts may be important if you have server processes (like database systems, e.g. Sybase or Oracle) that need to save their state before they exit.

The two features that make shutdown the prefered command in most cases are the ability to specify a grace period before the actual shutdown occurs and to also specify a warning message explaining the need for the upcoming shutdown. These features allow you to warn any users logged on the system to close up any running processes and log off the machine cleanly. The `shutdown' command on `BSD boxes has the following syntax:

    % sudo shutdown -[h|r|p] <time> <message>
The -h flag says to halt the machine; the -r flag says to reboot the machine; the -p flag says to halt and power-off the machine (this feature is only available on compliant hardware - see the manpage). The time may be an absolute time or a +N where N is a number of minutes to wait before shutdown. The command takes some other flags as well, read the manpage for details. For example:

    baelzebub % sudo shutdown -p +5 "baelzebub is going down for maintenance"
    Password:
    shutdown: switch -p must be used with -h.
    usage: shutdown [-dfhknpr] shutdowntime [ message ]
    baelzebub % sudo shutdown -ph +5 "baelzebub is going down for maintenance"
    Shutdown at Fri Feb  2 18:00:06 2001.
    shutdown: [pid 21142]
    baelzebub %                                                                                
The shutdown process then echos a message like the following to every logged in users' terminal window(s):

    *** System shutdown message from tor@baelzebub ***
    System going down in 5 minutes

baelzebub is going down for maintenance

If you decide you don't want to shutdown afterall, you can kill(1) the shutdown process; note, above, that the BSD shutdown told us the PID so that makes it easy for us!

    baelzebub % sudo kill 21142
When a shutdown has been called for, the given message is placed into the /etc/nologin file. The presence of this file causes users to not be able to log into the system (as the name implies!). The text of the file is echoed to the person's screen.

The `shutdown' command on RedHat is theoretically similar to the BSD version. However, as seen in class, the BSD-style time specifications don't work so well. According to the manpage, though, this is supposed to work. In fact, I tried it again and it did the right thing:

    xibalba % sudo shutdown -r +5 "xibalba is rebooting..."

Broadcast message from root (pts/0) Fri Feb 2 18:51:52 2001...

xibalba is rebooting... The system is going DOWN for reboot in 5 minutes !!

The shutdown command on Solaris machines is totally different. Read the manpage for details before you use it!

A reboot either with the command of that name or with the -r flag to shutdown obviously does what you might think. More specifically, an OpenBSD box would be rebooted into multi-user mode. A RedHat box will be rebooted into the default runlevel.

The init command may be used on a System-V style machine. It is invoked with the desired runlevel to change into. Runlevel ZERO will halt the machine; runlevel SIX will reboot; runlevel FIVE will halt and attempt to power-off the machine (on Solaris only - runlevel five is for XDM service on a RedHat box!). In fact, init is called by the shutdown process on Sys-V style machines. Using `init' in this fashion is perfectly safe (you just don't get the grace-period and warning message; the kill scripts are performed).