|
|

楼主 |
发表于 2005-11-16 13:10:01
|
显示全部楼层
初始化rc文件注释
在《init进程---inittab文件》理解中,我们知道,系统首先根据:
id:3:initdefault:
设置默认的运行等级,在man inittab中是这么说明initdefault的:"一个initdefault入口具体地说明了系统启动后应该进入的运行级别,如果默认值不存在,那么init进程将要求控制台输入一个运行级别。process被域忽略"。对wait的说明是:"当机器进入该等级时,该进程将被启动一次.并且init进程等待它的结束"。
以上的说明是我认为,机器启动时,如果默认等级为3时,只有13:3:wait:/etc/rc.d/init.d/rc 3运行的理由,通过试验,确实如此.。
系统初始化过程中,最重要的一个初始化脚本是/etc/rc.d/init.d/rc,可以看到所有的初始化都是通过给rc传递不同的参数而进行的.现在我们来分析rc脚本:
#!/bin/sh
# Begin $rc_base/init.d/rc - Main Run Level Control Script
# Based on rc script from LFS-3.1 and earlier.
# Rewritten by Gerard Beekmans - gerard@linuxfromscratch.org
. /etc/sysconfig/rc
#载入/etc/sysconfig/rc,该文件声明了一些变量,内容如下
#rc_base=/etc/rc.d
#rc_functions=$rc_base/init.d/functions
#network_devices=/etc/sysconfig/network-devices
. $rc_functions
#包含一些基本的shell函数,这些函数在/etc/rc.d/init.d/functions中
#以后可以直接引用其中的函数
# This sets a few default terminal options.
stty sane
#man stty 改变和显示终端行的设置
#这个地方具体不明白
# These 3 signals will not cause our script to exit
trap "" INT QUIT TSTP
#trap命令设置信号的处理方式
#把INT QUIT TSTP的处理方式设为空,忽略这些信号的处理
[ "$1" != "" ] && runlevel=$1
#如果参数不为空,那么把该参数赋给runlevel
#比如/etc/rc.d/init.d/rc sysinit 那么runlevel=sysinit
#而/etc/rc.d/init.d/rc 0 那么runlevel=0
if [ "$runlevel" = "" ]
then
echo "Usage: $0 <runlevel>" >&2
exit 1
fi
#如果runlevel为空,则退出脚本(各位可以改动inittab试验一下 )
previous=$PREVLEVEL
[ "$previous" = "" ] && previous=N
#把前一个运行的级别赋给previous
#如果前一个运行级别为空,则让它等于N
#这里主要是考虑到机器运行等级的改变,如果机器刚开始运行,那么前一个等级为为空
#没有找到PREVLEVEL的定义
if [ ! -d $rc_base/rc$runlevel.d ]
then
echo "$rc_base/rc$runlevel.d does not exist"
exit 1
fi
#判断目录/etc/rc.d/rc$runlevel.d,是否存在,如果不存在,那么退出
#其实就是判断rcsysinit.d ,rc0-6.d是否存在
# Attempt to stop all service started by previous runlevel,
# and killed in this runlevel
if [ "$previous" != "N" ]
#如果前一个运行等级不为N,也就是说不是刚开机,是机器运行等级的切换
#如果是刚开机,下面的不会运行
then
for i in $(ls -v $rc_base/rc$runlevel.d/K* 2> /dev/null)
#列/etc/rc.d/rc$runlevel.d目录下所有以K开头的脚本,对于其中的每个脚本做一下的操作
#对于runlevel=0,为/etc/rc.d/rc0.d/K80network /etc/rc.d/rc0.d/K90sysklogd
do
check_script_status
#首先调用functions中的函数check_script_status,检查脚本的状态
#check_script_status()
# {
# if [ ! -f $i ]; then
# echo "$i is not a valid symlink"
# continue
# fi
# if [ ! -x $i ]; then
# echo "$i is not executable, skipping"
# continue
# fi
# }
#作用是明显的,先检查是否存在,再判断是否可执行
suffix=${i#$rc_base/rc$runlevel.d/K[0-9][0-9]}
#这是一个字符串的模式匹配,i#$rc_base/rc$runlevel.d/K[0-9][0-9]表示对i从字符串的开头
#进行匹配,找到匹配最小rc_base/rc$runlevel.d/K[0-9][0-9],删除匹配部分,返回
#例如/etc/rc.d/rc0.d/K80network,那么这里删除/etc/rc.d/rc0.d/K80,suffic=network
prev_start=$rc_base/rc$previous.d/S[0-9][0-9]$suffix
#赋给prev_start为前一个运行级别的目录下的S开头的文件
#如果suffix=network,那么
#prev_start=/etc/rc.d/rc$previous.d/S[0-9][0-9]network
#其中[0-9]表示集合匹配,也就是0-9之间的任何一个数字都匹配
sysinit_start=$rc_base/rcsysinit.d/S[0-9][0-9]$suffix
#同上不过这里是rcsysinit.d目录下的
if [ "$runlevel" != "0" ] && [ "$runlevel" != "6" ]
#如果不是关机(运行级别为0),或者重新启动(运行级别为6),那么做以下的action
then
if [ ! -f $prev_start ] && [ ! -f $sysinit_start ]
#如果前一个运行级别下,该服务(也就是i)不存在,而且在rcsysinit.d中也不存在,那么打印以下提示
then
echo -n -e $WARNING
echo "$i can't be executed because it was"
echo "not started in the previous runlevel ($previous)"
echo -n -e $NORMAL
continue
#其中WARING,.NORMAL在funtions中定义
#重新开始循环
#这部分好像没有被执行过,不过你去删除几个/etc/rc.d/init.d下的文件,就不一定了
fi
fi
$i stop
#以参数stop运行脚本,比如如果i是/etc/rc.d/rc0.d/K80network,那么就是停止网络了
error_value=$?
# $? 表示上一个命令的返回值,如果上一条命令成功执行,则返回0,否则返回的是1-255之间的数
if [ "$error_value" != "0" ]
then
print_error_msg
fi
#如果服务停止不成功,调用functions中的函数print_error_msg打印错误信息,可以看一下打印些什么
done
fi
#Start all functions in this runlevel
for i in $( ls -v $rc_base/rc$runlevel.d/S* 2> /dev/null)
#列/etc/rc.d/rc$runlevel.d目录下所有以S开头的脚本,对于其中的每个脚本做一下的操作
#对于runlevel=sysinit,为
#/etc/rc.d/rcsysinit.d/S00mountkernfs
#/etc/rc.d/rcsysinit.d/S05modules
#/etc/rc.d/rcsysinit.d/S10udev
#/etc/rc.d/rcsysinit.d/S20swap
#/etc/rc.d/rcsysinit.d/S30checkfs
#/etc/rc.d/rcsysinit.d/S40mountfs
#/etc/rc.d/rcsysinit.d/S50cleanfs
#/etc/rc.d/rcsysinit.d/S60setclock
#/etc/rc.d/rcsysinit.d/S70console
#/etc/rc.d/rcsysinit.d/S80localnet 好多啊!
do
if [ "$previous" != "N" ]
#如果是运行级别的切换,而不是刚开机;刚开机不做以下action
then
suffix=${i#$rc_base/rc$runlevel.d/S[0-9][0-9]}
#同上,取后缀,比如runlevel=sysinit,则依次取mountkernfs modules udev swap checkfs mountfs cleanfs setclock console localnet
stop=$rc_base/rc$runlevel.d/K[0-9][0-9]$suffix
#找到相应以K开头的文件
prev_start=$rc_base/rc$previous.d/S[0-9][0-9]$suffix
#前一个运行等级目录下相应的文件
[ -f $prev_start ] && [ ! -f $stop ] && continue
#如果前一个运行级别中该项服务存在,而且,当前运行级别中该项服务不需要停止,那么continue
#其实就是说,如果一项服务前一个运行级别已经开启,而且当前运行级别不需要关闭,那么就没有必要重新开启该项服务了
#直接检查下一项服务
fi
check_script_status
#同样,检查一下脚本状态
case $runlevel in
0|6) $i stop ;;
#如果是要关机或者重新启动,那么关闭该项服务,以stop为参数,运行该脚本
*) $i start ;;
#其他的级别,那么开启服务,以start为参数
esac
error_value=$?
#获得返回值
if [ "$error_value" != "0" ]
then
print_error_msg
fi
#如果运行错误,打印错误提示信息
done
# End $rc_base/init.d/rc |
|