首页 > 代码库 > linux系统运行级别改变时,系统所做的工作

linux系统运行级别改变时,系统所做的工作

# 其实计算机的关闭也就是运行级别的切换;
# init进程监控运行级别是否改变。
# 如果运行级别改变了,init进程就会触发 /etc/rc.d/rc 脚本运行。
# rc 脚本作用是:
#    1、如果当前计算机运行有,在当前运行级别
#   (correctrunlevel )/etc/rc.d/rc$runlevel.d/目录下以K开头的服务。就关闭。
#     2、开启当前运行级别(correct runlevel )/etc/rc.d/rc$runlevel.d/目录下#   以S开头的服务
#这样就实现了,不同运行级别的所允许启动、禁止启动的服务的控制。
#如果当前运行级别(correct runlevel )/etc/rc.d/rc$runlevel.d/目录下以S开头的#服务脚本有:half 就会关闭计算机。
#[root@node2 rc.d]# ll rc0.d/S*
lrwxrwxrwx 1 root root 17 Apr  5 00:13 rc0.d/S00killall ->../init.d/killall
lrwxrwxrwx 1 root root 14 Apr  5 00:13 rc0.d/S01halt -> ../init.d/halt
# 会先执行kill脚本再执行halt脚本。
# 其实系统管理员发出【shutdown】命令,就是通知 init 进程,运行级别改变了。
[root@node2 ~]# man shutdown
.....shutdown does its job by signalling the init process, asking it to change the runlevel.
......
# 进程init的配置文件/etc/inittab 定义等级切换时动作
[root@node2 ~]# vim /etc/inittab
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
# 这些行表示在系统的运行级别每次发生变化时都就当运行一次rc程序(/etc/rc.d/rc脚本),
# 而且init应当将一个包含运行级别号(0~~6)的单字符参数传递给rc程序。
# 会监控主机的运行等级的变化,如运行等级变化了就会调用:/etc/rc.d/rc 脚本
# 假如当前主机的运行等级是:
[root@node2 bin]# runlevel
N 3
# 作用命令init 发出关闭程序信号使用: 
[root@node2 bin]# init 0  
# init进程发现运行等级改变就会按照配置文件inittab中的 l0:0:wait:/etc/rc.d/rc # 0执行相关操作。  
[root@node2 ~]# vim /etc/rc.d/rc
#! /bin/bash
#
# rc            This file is responsible for starting/stopping
#               services when the runlevel changes.
#
# Original Author:
#               Miquel van Smoorenburg, <miquels@drinkel.nl.mugnet.org>
#
set -m
###################################################################
#该函数是检查当前运行级别的脚本条件:
#                     1、该脚本必须有可运行权限;
#                     2、不属于函数is_ignored_file 中指定的类型
# check a file to be a correct runlevel script
check_runlevel ()
{
        # Check if the file exists at all.
        [ -x "$1" ] || return 1
        is_ignored_file "$1" && return 1 # 调用函数检查文件类型。
        return 0
}
# Now find out what the current and what the previous runlevel are.
argv1="$1"   #记录:运行级别改变时,init进程触发运行rc脚本时传递的参数。
set `/sbin/runlevel`  # 记录当前主机的运行级别
runlevel=$2
previous=$1
export runlevel previous
. /etc/init.d/functions
# See if we want to be in user confirmation mode
if [ "$previous" = "N" ]; then
        if [ -f /var/run/confirm ]; then
                echo $"Entering interactive startup"
        else
                echo $"Entering non-interactive startup"
        fi
fi
# Get first argument. Set new runlevel to this argument.
[ -n "$argv1" ] && runlevel="$argv1" 
  #如果进程init监控到运行级别改变时,触发运行rc脚本时传递了参数,
  #就把该参数当作当前主机的运行级别
# Is there an rc directory for this new runlevel? 
   #判断运行级别在/etc/目录下是否的对应目录,如果没有就直接退出。
   #这也可判断传递的运行参数是否正确
[ -d /etc/rc$runlevel.d ] || exit 0
####################################################################
#给/etc/rc.d/rc$runlevel.d目录下的K开头的脚本传递:stop 以实现关闭该运行级别不
#启动的服务
# First, run the KILL scripts.          
for i in /etc/rc$runlevel.d/K* ; do
        check_runlevel "$i" || continue 
        #调用函数check_runlevel检查脚本,如果去一个服务的启动脚本就往下执行,
        #否则退出当前循环执行下一次循环
########################如果 $i 是一个服务的启动脚本,判断该脚本(以K开头的脚本)#在运行级别切换之前是否已经启动。
#因为通过脚本启动服务后(如:service httpd start 或 httpd start),
#都会在/var/lock/subsys/目录下创建一个以启动脚本命名的文件
#也正是通过判断/var/lock/subsys/目录下有没有该服务脚本对应的文件,
#来确定该服务是否启动的。
        # Check if the subsystem is already up.
        subsys=${i#/etc/rc$runlevel.d/K??}
        [ -f /var/lock/subsys/$subsys -o -f /var/lock/subsys/$subsys.init ]                 || continue
        # Bring the subsystem down. 
        #关闭当前运行级别设置不启动的服务(运行级别切换之前启动的服务,
        #但是该服务在当前运行级别是设置不启动的),
        if LC_ALL=C egrep -q "^..*init.d/functions" $i ; then
                $i stop              
        else
                action $"Stopping $subsys: " $i stop
        fi
done
############### 启动当前运行级别设置启动的服务#####################################################################
# Now run the START scripts.
for i in /etc/rc$runlevel.d/S* ; do
        check_runlevel "$i" || continue
        # Check if the subsystem is already up.
        subsys=${i#/etc/rc$runlevel.d/S??}
        [ -f /var/lock/subsys/$subsys -o -f /var/lock/subsys/$subsys.init ]                 && continue 
                #如果运行级别切换之前,已经启动了该服务就直接退出。
                #防止一个服务启动两次。目录/var/lock/subsys/下锁文件的作用。
        # If we‘re in confirmation mode, get user confirmation
        if [ -f /var/run/confirm ]; then
                confirm $subsys
                test $? = 1 && continue
        fi
          #如果当前运行级别下(/etc/rc.d/rc$runlevel.d)的half脚本是S开头的
          #就会运行该脚本,该脚本是关闭计算机的,
        update_boot_stage "$subsys"
        # Bring the subsystem up.
        if [ "$subsys" = "halt" -o "$subsys" = "reboot" ]; then
                export LC_ALL=C      
                exec $i start
        fi
        if LC_ALL=C egrep -q "^..*init.d/functions" $i                         || [ "$subsys" = "single" -o "$subsys" = "local" ]; then
                $i start
        else
                action $"Starting $subsys: " $i start
        fi
done
rm -f /var/run/confirm
if [ -x /usr/bin/rhgb-client ] && /usr/bin/rhgb-client --ping ; then
  /usr/bin/rhgb-client --quit
fi

 

本文出自 “Linux” 博客,请务必保留此出处http://9528du.blog.51cto.com/8979089/1420173