Runlevels in HP-UX and Solaris

In the following post I’d like to dwell upon differences between the run levels in Solaris and HP-UX.
So first, lets take a quick look at the description (man init(1M)) of the run levels which are supported in these two operating systems:


0Shut down HP-UX.
S|sUse for system administration (also known as "single-user state"). When booting into run level S at powerup, the only access to the system is through a shell spawned at the system console as the root user. The only processes running on the system will be kernel daemons started directly by the HP-UX kernel, daemon processes started from entries of type sysinit in /etc/inittab, the shell on the system console, and any processes started by the system administrator. Administration operations that require the system to be in a quiescent state (such as the fsck(1M) operation to repair a file system) should be run in this state. Transitioning into run level S from a higher run level does not terminate other system activity and does not result in a "single-user state"; this operation should not be done.
1Start a subset of essential system processes. This state can also be used to perform system administration tasks.
2Start most system daemons and login processes. This state is often called the "multi-user state". Login processes either at local terminals or over the network are possible.
3Export filesystems and start other system processes. In this state NFS filesystems are often exported, as may be required for an NFS server.
4Activate graphical presentation managers and start other system processes.
5-6These states are available for user-defined operations.


0Go into firmware
1Put the system in system administrator mode. All local file systems are mounted. Only a small set of essential kernel processes are left running. This mode is for administrative tasks such as installing optional utility packages. All files are accessible and no users are logged in on the system.
2Put the system in multi-user mode. All multi-user environment terminal processes and daemons are spawned. This state is commonly referred to as the multi-user state.
3Extend multi-user mode by making local resources available over the network.
4Is available to be defined as an alternative multi-user environment configuration. It is not necessary for system operation and is usually not used.
5Shut the machine down so that it is safe to remove the power. Have the machine remove power, if possible.
6Stop the operating system and reboot to the state defined by the initdefault entry in /etc/inittab.
S, sEnter single-user mode. This is the only run level that doesn't require the existence of a properly formatted /etc/inittab file. If this file does not exist, then by default, the only legal run level that init can enter is the single-user mode. When in single-user mode, the filesystems required for basic system operation will be mounted.
Q, qRe-examine /etc/inittab.

Apart from obvious distinctions between run levels with the same numbers, just take a closer look at run levels 5 and 6, there is a fundamental difference in a way that services are started/stopped when transition from on run-level to another takes place.

In HP-UX there is a single script /sbin/rc which acts as a general purpose sequencer invoked upon entering new run level. But what is more important is the following behavior of rc scipt:

If a transition from a lower to a higher run level (i.e., init state) occurs, the start scripts for the new run level and all intermediate levels between the old and new level are executed. If a transition from a higher to a lower run level occurs, the kill scripts for the new run level and all intermediate levels between the old and new level are executed.

Lets compare it to the way that Solaris does the same job. I’m going to concentrate on Solaris 9 leaving the latest Solaris 10 version for the last bit. Just like in HP-UX, Solaris has it’s own /etc/inittab file which controls process dispatching by init. The inittab file is composed of entries that are position dependent and have the following format:


ap::sysinit:/sbin/autopush -f /etc/iu.ap
ap::sysinit:/sbin/soconfig -f /etc/sock2path
fs::sysinit:/sbin/rcS sysinit >/dev/msglog 2<>/dev/msglog /dev/msglog 2<>/dev/msglog
sS:s:wait:/sbin/rcS >/dev/msglog 2<>/dev/msglog /dev/msglog 2<>/dev/msglog /dev/msglog 2<>/dev/msglog /dev/msglog 2<>/dev/msglog /dev/msglog 2<>/dev/msglog /dev/msglog 2<>/dev/msglog /dev/msglog 2<>/dev/msglog /dev/msglog 2<>/dev/msglog /dev/msglog 2<>/dev/msglog /dev/msglog 2<>/dev/msglog

But, in contrast to HP-UX, there is a single /etc/rc[S012356] script for every run level. More over, in Solaris only the scripts that pertain to the run-level we’re switching into are executed. These scripts are placed in a corresponding directories, i.e. /etc/rc0.d/ for the run level zero, /etc/rc1.d/ for the first and so on. In other words, if we’re transiting from the level S (single user mode) to the second run level then in that case one start/stop scripts from the zero and the first run levels are run by jumping right into the /etc/rc2.d/ directory where kill or K* scripts are run first following by start or S* scripts.

f [ $_INIT_PREV_LEVEL = S -o $_INIT_PREV_LEVEL = 1 ]; then
        echo 'The system is coming up.  Please wait.'

elif [ $_INIT_RUN_LEVEL = 2 ]; then
        echo 'Changing to state 2.'

        if [ -d /etc/rc2.d ]; then
                for f in /etc/rc2.d/K*; do
                        if [ -s $f ]; then
                                case $f in
                                        *.sh)   .        $f ;;
                                        *)      /sbin/sh $f stop ;;

if [ $_INIT_PREV_LEVEL != 2 -a $_INIT_PREV_LEVEL != 3 \
    -a $_INIT_PREV_LEVEL != 4 -a -d /etc/rc2.d ]; then

        for f in /etc/rc2.d/S*; do
                if [ -s $f ]; then
                        case $f in
                                *.sh)   .        $f ;;
                                *)      /sbin/sh $f start ;;

The third run level is an exception though. If you take a closer look at the /etc/inittab file from Solaris you’d noticed that /sbin/rc2 is also executed when switching into the third run level.

s2:23:wait:/sbin/rc2 >/dev/msglog 2<>/dev/msglog /dev/msglog 2<>/dev/msglog

By the way, it’s worth mentioning that most Kill scripts could be found in /etc/rc0.d and /etc/rc1.d/, so please pay attention to this.

In Solaris 10 with introduction of SMF (System Management Facility) things have changed noticeably and brought substantial enhancements to the traditional UNIX start-up scripts. I’m not going to linger on that subject in great details but just want to mention that run run-levels have been replaced with the milestones and for legacy purposes startup programs in the /etc/rc?.d directories are executed as part of the corresponding run-level milestone:

/etc/rcS.d milestone/single-user:default
/etc/rc2.d milestone/multi-user:default
/etc/rc3.d milestone/multi-user-server:default

In addition, a new restarter daemon for SMF and for all services has been added to the system – svc.startd.
Quick excerpt from its man page:

svc.startd maintains service state, as well as being responsible for managing faults in accordance with the dependencies of each service. svc.startd is invoked automatically during system startup. It is restarted if any failures occur. svc.startd should never be invoked directly.

So now a good question or even a series of them could start vibrating in your mind:

To tell the truth, it’s all dead easy.

  1. Simply running the following command you could get an answer to the first question:
    # svcs -a | grep milestone
    online         Dec_11   svc:/milestone/name-services:default
    online         Dec_11   svc:/milestone/network:default
    online         Dec_11   svc:/milestone/devices:default
    online         Dec_11   svc:/milestone/single-user:default
    online         Dec_11   svc:/milestone/sysconfig:default
    online         Dec_11   svc:/milestone/multi-user:default
    online         Dec_11   svc:/milestone/multi-user-server:default

    With “svcs -l” you could get a longer description of each service. More over, this command will also reveal its dependencies and whether they are optional or required:

    # svcs -l  svc:/milestone/multi-user-server:default
    fmri         svc:/milestone/multi-user-server:default
    name         multi-user plus exports milestone
    enabled      true
    state        online
    next_state   none
    state_time   December 11, 2009 12:20:44 PM MSK
    logfile      /var/svc/log/milestone-multi-user-server:default.log
    restarter    svc:/system/svc/restarter:default
    dependency   optional_all/none svc:/system/cluster/cl-svc-enable:default (online)
    dependency   require_all/none svc:/milestone/multi-user (online)
    dependency   optional_all/none svc:/application/management/dmi (online)
    dependency   optional_all/none svc:/application/management/snmpdx (online)
    dependency   optional_all/none svc:/network/rpc/bootparams (disabled)
    dependency   optional_all/none svc:/network/samba (disabled)
    dependency   optional_all/none svc:/network/winbind (disabled)
    dependency   optional_all/none svc:/network/wins (disabled)
    dependency   optional_all/none svc:/network/nfs/server (disabled)
    dependency   optional_all/none svc:/network/rarp (disabled)
    dependency   optional_all/none svc:/network/dhcp-server (disabled)
    dependency   optional_all/none svc:/network/ssh (online)
  2. Using svcprop command one could list all properties which belongs to a given service.
    # svcprop svc:/system/svc/restarter:default
    general/enabled boolean true
    general/entity_stability astring Unstable
    general/single_instance boolean true
    restarter/auxiliary_state astring none
    restarter/next_state astring none
    restarter/state astring online
    restarter/state_timestamp time 1260522889.099316000
    restarter/start_pid count 8
    restarter/contract count 4
    restarter/alt_logfile astring /etc/svc/volatile/svc.startd.log
    restarter/logfile astring /var/svc/log/svc.startd.log
    system/reconfigure boolean false
    options/milestone astring all
    tm_common_name/C ustring master\ restarter
    tm_man_svc_startd/manpath astring /usr/share/man
    tm_man_svc_startd/section astring 1M
    tm_man_svc_startd/title astring svc.startd

    As you could see, there is a special property options/milestone that defines the milestone used as the default boot level. Allow me to quote man page once again:

    Acceptable options include only the major milestones:


    or the special values all or none. all represents an idealized milestone that depends on every service. none is a special milestone where no services are running apart from the master svc:/system/svc/restarter:default.
    By default, svc.startd uses all, a synthetic milestone that depends on every service. If this property is specified, it overrides any initdefault setting in inittab(4).

    To change the default milestone just run the following command:

    # svccfg -s svc:/system/svc/restarter:default setprop options/milestone=svc:/milestone/multi-user-server:default
    # svcprop -p options/milestone svc:/system/svc/restarter:default
  3. Use “svcs -D” against the milestone your’re interested in to get the list of all dependents.
  4. # svcs -D  svc:/milestone/multi-user:default
    STATE          STIME    FMRI
    disabled       Dec_11   svc:/network/dhcp-server:default
    disabled       Dec_11   svc:/system/iscsitgt:default
    disabled       10:17:00 svc:/application/cde-printinfo:default
    disabled       10:17:00 svc:/application/graphical-login/cde-login:default
    disabled       10:17:01 svc:/system/vxvm/vxvm-recover:default
    disabled       10:17:32 svc:/application/management/common-agent-container-1:default
    online         Dec_11   svc:/system/cluster/cl-svc-enable:default
    online         Dec_11   svc:/milestone/multi-user-server:default
  5. And finally, to switch from one milestone to another use “svcadm milestone” command:
    # svcs -a | grep milestone
    online         Dec_11   svc:/milestone/name-services:default
    online         Dec_11   svc:/milestone/network:default
    online         Dec_11   svc:/milestone/devices:default
    online         Dec_11   svc:/milestone/single-user:default
    online         Dec_11   svc:/milestone/sysconfig:default
    online         Dec_11   svc:/milestone/multi-user:default
    online         10:55:39 svc:/milestone/multi-user-server:default
    offline        10:55:36 svc:/system/cluster/cl-svc-cluster-milestone:default
    # svcadm milestone svc:/milestone/single-user:default
    # svcs -a | grep milestone
    disabled       10:57:28 svc:/milestone/multi-user-server:default
    disabled       10:57:28 svc:/system/cluster/cl-svc-cluster-milestone:default
    disabled       10:57:38 svc:/milestone/multi-user:default
    disabled       10:58:06 svc:/milestone/sysconfig:default
    disabled       10:58:06 svc:/milestone/name-services:default
    online         Dec_11   svc:/milestone/network:default
    online         Dec_11   svc:/milestone/devices:default
    online         Dec_11   svc:/milestone/single-user:default

    If you add “-d” option to “svcadm milestone” command then this milestone becomes the default one as well.

That’s it. Feel free to comment if I’ve missed anything or made a mistake.

Posted on March 5, 2010 at 11:29 am by sergeyt · Permalink
In: HP-UX, Solaris

One Response

Subscribe to comments via RSS

  1. Written by somebody
    on April 10, 2015 at 2:36 pm
    Reply ·