zoukankan      html  css  js  c++  java
  • 运行级别(run level)

    inittab是很多linux版本的启动脚本。
    Linux在完成核内引导以后,就开始运行init程序,它的进程号是1,是所有其他进程的起点。
    init需要读取/etc/inittab,该文件告诉init在它的每个运行级别上需要做哪些事情。

    init共定义了七个运行级(run level),分别是什么?
    # Default runlevel. The runlevels used by RHS are:
      # 0 - halt (Do NOT set initdefault to this)
      # - 关闭计算机,安全关闭电源
      # 1 - Single user mode
      # - 进入单用户维护模式,卸下除root以外的所有文件系统并杀死所有用户进程
      # 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)
      # - 停止linux系统,并按照/etc/inittab默认的登记项重新引导系统


    通常在/etc/inittab的开头就定义了系统默认启动到的级别,如:
    id:3:initdefault:
    id - 用来定义缺省的init运行的级别
    3 - 默认的级别为此 (Full multiuser mode)
    initdefault - 是关键字,表示默认的级别。
    系统管理员可以通过修改这条语句方便地修改默认的运行级别。
    在机器引导时,init从运行级0开始,一级一级往上运行到在/etc/inittab中所设置的默认运行级别。为了完成在每一对相邻运行级别之间的过渡,init运行在/etc/inittab中为这种过渡而说明的一些操作。当机器关闭时,以相反的顺序执行同样的处理过程。

    既然之前指定的默认运行级别是3,那么init就要执行/etc/rc.d/rc3.d目录中的脚本。/etc/rc.d/rcN.d/目录中的这些启动脚本实际上都是一些链接文件,而不是真正的rc启动脚本,真正的rc启动脚本实际上都是放在/etc/rc.d/init.d/目录下。而这些rc启动脚本有着类似的用法,它们一般能接受start、stop、restart、status等参数。

    我们可以看到/etc/rc.d/rc5.d/中的 rc启动脚本通常是K或S开头的链接文件,对于以以S开头的启动脚本,将以start参数来运行。而如果发现存在相应的脚本也存在K打头的链接,而且已经处于运行态了(以/var/lock/subsys/下的文件作为标志),则将首先以stop为参数停止这些已经启动了的守护进程,然后再重新运行。这样做是为了保证是当init改变运行级别时,所有相关的守护进程都将重启。


    下面讲下几个特殊的linux.
    对于arch:
    以我机子上的arch linux为例,inittab如下:
    [sai@myhost etc]$ cat inittab 
    #
    # /etc/inittab
    #

    # Runlevels:
    # 0 Halt
    # 1(S) Single-user
    # 2 Not used
    # 3 Multi-user
    # 4 Not used
    # 5 X11
    # 6 Reboot

    ## Only one of the following two lines can be uncommented!
    # Boot to console
    #id:3:initdefault:
    # Boot to X11
    id:5:initdefault:

    rc::sysinit:/etc/rc.sysinit //第1个启动脚本
    rs:S1:wait:/etc/rc.single //当以S和1运行级启动时,rs为代号,wait为行为描述,下同
    rm:2345:wait:/etc/rc.multi //当以2-5运行级启动时
    rh:06:wait:/etc/rc.shutdown //6运行级启动时
    su:S:wait:/sbin/sulogin -p //S运行级启动时

    # -8 options fixes umlauts problem on login
    c1:2345:respawn:/sbin/agetty -8 38400 tty1 linux
    c2:2345:respawn:/sbin/agetty -8 38400 tty2 linux
    c3:2345:respawn:/sbin/agetty -8 38400 tty3 linux
    c4:2345:respawn:/sbin/agetty -8 38400 tty4 linux
    c5:2345:respawn:/sbin/agetty -8 38400 tty5 linux
    c6:2345:respawn:/sbin/agetty -8 38400 tty6 linux

    ca::ctrlaltdel:/sbin/shutdown -t3 -r now

    # Example lines for starting a login manager
    x:5:respawn:/usr/bin/xdm -nodaemon
    #x:5:respawn:/usr/sbin/gdm -nodaemon
    #x:5:respawn:/usr/bin/kdm -nodaemon
    #x:5:respawn:/usr/bin/slim >& /dev/null

    # End of file


    由id:5:initdefault:看出默认运行级别为5。
    arch并没有提供rcN.d之类的目录,但是我们由这一句rm:2345:wait:/etc/rc.multi看到会执行/etc/rc.multi/rc.multi脚本。内容如下:
    [sai@myhost etc]$ cat rc.multi 
    #!/bin/bash
    #
    # /etc/rc.multi
    #

    . /etc/rc.conf
    . /etc/rc.d/functions

    # Load sysctl variables if sysctl.conf is present
    [ -r /etc/sysctl.conf ] && /sbin/sysctl -q -p &>/dev/null

    # Start daemons
    for daemon in "${DAEMONS[@]}"; do
    if [ "$daemon" = "${daemon#!}" ]; then
    if [ "$daemon" = "${daemon#@}" ]; then
    start_daemon $daemon
    else
    start_daemon_bkgd ${daemon:1}
    fi
    fi
    done

    if [ -x /etc/rc.local ]; then
    /etc/rc.local
    fi

    # vim: set ts=2 noet:

    会执行/etc/rc.conf和/etc/rc.d/functions,前者是arch用户最熟悉的,后者看看代码很长,也是一些启动设置。上面我们看到会执行/etc/rc.local,这个也是一个启动脚本,用户常加入自定义脚本在里面。

    /etc/rc.conf里面的服务启动都是相应在/etc/rc.d/目录下当脚本,arch上并没有链接到/etc/init.d目录下,因为arch根本没有/etc/init.d这个目录


    对于ubuntu:
    参考文档
    http://hi.baidu.com/benzus/blog/item/a0f9791700bcf701c83d6d6e.html

    ubuntu中inittab不见了,而变成了upstart机制,启动脚本改成了/etc/event.d/rc-default,内容如下:
    start on stopped rcS

    script
    runlevel --reboot || true

    if grep -q -w -- "-s|single|S" /proc/cmdline; then
    telinit S
    elif [ -r /etc/inittab ]; then
    RL="$(sed -n -e "/^id:[0-9]*:initdefault:/{s/^id://;s/:.*//;p}" /etc/inittab || true)"
    if [ -n "$RL" ]; then
    telinit $RL
    else
    telinit 2
    fi
    else
    telinit 2
    fi
    end script

    telinit 2默认运行级别2,另外保留了inittab的方式,可以在/etc下建inittab来加入自己的选择。


    运行级别2触发相应的runlevel事件,开始运行/etc/event.d/rc2
    sai@sai-desktop:/etc$ cat /etc/event.d/rc2
    # rc2 - runlevel 2 compatibility
    #
    # This task runs the old sysv-rc runlevel 2 ("multi-user") scripts. It
    # is usually started by the telinit compatibility wrapper.

    start on runlevel 2

    stop on runlevel [!2]

    console output
    script
    set $(runlevel --set 2 || true)
    if [ "$1" != "unknown" ]; then
    PREVLEVEL=$1
    RUNLEVEL=$2
    export PREVLEVEL RUNLEVEL
    fi

    exec /etc/init.d/rc 2
    end script

    执行的是exec /etc/init.d/rc 2,这个脚本就很长了,而这里传递给它的参数为2,看这个脚本
    先是设置环境变量
    PATH=/sbin:/usr/sbin:/bin:/usr/bin
    export PATH
    。。。。
    然后是确认允许级别
    # Now find out what the current and what the previous runlevel are.

    runlevel=$RUNLEVEL
    # Get first argument. Set new runlevel to this argument.
    [ "$1" != "" ] && runlevel=$1
    if [ "$runlevel" = "" ]
    then
    echo "Usage: $scriptname <runlevel>" >&2
    exit 1
    fi

    接下来
    。。。。。。
    # Now run the START scripts for this runlevel.
    # Run all scripts with the same level in parallel
    CURLEVEL=""
    for s in /etc/rc$runlevel.d/S*
    do

    看来是驱动rcX下的运行脚本了,ubuntu的默认驱动级别为level 2。所以查看/etc/rc2.d下目录的脚本。
    sai@sai-desktop:/etc/rc2.d$ ls
    K08vmware-tools S19vmware-tools S50pulseaudio S89cron
    README S20apport S50rsync S90binfmt-support
    S01policykit S20hotkey-setup S50saned S98usplash
    S10acpid S24hal S50system-tools-backends S99acpi-support
    S10apmd S25bluetooth S70bootlogs.sh S99laptop-mode
    S10sysklogd S30gdm S70dns-clean S99ondemand
    S11klogd S50avahi-daemon S70pppd-dns S99rc.local
    S12dbus S50cups S89anacron S99rmnologin
    S16ssh S50NetworkManager S89atd S99stop-readahead


    可以看到这些就是ubuntu的启动脚本了,而这些脚本都是链接到/etc/init.d/下的符号。另外注意到/etc/rc2.d/rc.local,这个是/etc/init.d/rc.local的符号链接
    那么看下/etc/init.d/rc.local:
    sai@sai-desktop:/etc/init.d$ cat rc.local
    #! /bin/sh
    ### BEGIN INIT INFO
    # Provides: rc.local
    # Required-Start: $remote_fs
    # Required-Stop:
    # Default-Start: 2 3 4 5
    # Default-Stop:
    # Short-Description: Run /etc/rc.local if it exist
    ### END INIT INFO


    PATH=/sbin:/usr/sbin:/bin:/usr/bin

    . /lib/init/vars.sh
    . /lib/lsb/init-functions

    do_start() {
    if [ -x /etc/rc.local ]; then
    [ "$VERBOSE" != no ] && log_begin_msg "Running local boot scripts (/etc/rc.local)"
    /etc/rc.local
    ES=$?
    [ "$VERBOSE" != no ] && log_end_msg $ES
    return $ES
    fi
    }

    case "$1" in
    start)
    do_start
    ;;
    restart|reload|force-reload)
    echo "Error: argument '$1' not supported" >&2
    exit 3
    ;;
    stop)
    ;;
    *)
    echo "Usage: $0 start|stop" >&2
    exit 3
    ;;
    esac

    其实就是运行/etc/rc.local,所以说很多人把自己的启动项都加到/etc/rc.local中就是这么来得。

    最后用参考资料中总结.
    upstart管理的ubuntu启动过程:
    1,内核启动init
    2,init找到/etc/event.d/rc-default文件,确定默认的运行级别(X)
    3,触发相应的runlevel事件,开始运行/etc/event.d/rcX
    4,rcX运行/etc/init.d/rc,传入参数X
    5,/etc/init.d/rc脚本进行一系列设置,最后运行相应的/etc/rcX.d/中的脚本
    6,/etc/rcX.d/中的脚本按事先设定的优先级依次启动,直至最后给出登录画面(启动X服务器和GDM)

  • 相关阅读:
    java中的基本数据类型以及对应的包装类
    JQuery 基础
    题库一
    String、StringBuffer和StringBuilder的区别
    ideal控制台输出乱码
    python进阶
    python基础
    请求一个网页时,web服务做了什么?[以php为例]
    go defer看到你头晕的操作
    计算机基础-数据结构-栈
  • 原文地址:https://www.cnblogs.com/zhouhbing/p/4457766.html
Copyright © 2011-2022 走看看