Chinaunix首页 | 论坛 | 博客
  • 博客访问: 208422
  • 博文数量: 57
  • 博客积分: 1694
  • 博客等级: 上尉
  • 技术积分: 481
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-26 16:26
文章分类

全部博文(57)

文章存档

2011年(2)

2010年(37)

2009年(18)

我的朋友

分类: LINUX

2010-03-31 09:50:47

#!/bin/bash
#
# /etc/rc.d/rc.sysinit - run once at boot time

#
 
# Rerun ourselves through initlog                                                // 通过 /sbin/initlog 命令重新运行自己
if [ -z "$IN_INITLOG" -a -x /sbin/initlog ]; then                            
// 条件是 :如果 IN_INITLOG 变量的值不为空,且 /sbin/initlog 可执行
    exec /sbin/initlog -r /etc/rc.d/rc.sysinit                                
// 调用 exec /sbin/initlog ,-r 是表示运行某个程序
fi
 
######################################################################################################################################################
 
HOSTNAME=`/bin/hostname`                            # 取得主机名
HOSTTYPE=`uname -m`                                    
# 取得主机类型
unamer=`uname -r`                                          # 取得内核的 release 版本(例如 2.4.9.30-8)

eval version=`echo $unamer | awk -F '.' '{ print "(" $1 " " $2 ")" }'`            # 取得版本号
 
if [ -f /etc/sysconfig/network ]; then                # 如果存在 /etc/sysconfig/network ,则执行该文件。
    . /etc/sysconfig/network                             # network 文件主要控制是否启用网络、默认网关、主机名
fi
if [ -z "$HOSTNAME" -o "$HOSTNAME" = "(none)" ]; then            # 如果执行 network 文件后 HOSTNAME 为空或者为 "(none)" ,
    HOSTNAME=localhost                                                        
# 则将主机名设置为 "localhost"
fi
 
 
# Mount /proc and /sys (done here so volume labels can work with fsck)        # 接下来是挂载 /proc 和 /sys ,这样 fsck 才能使用卷标
mount -n -t proc /proc /proc                                                                      #  -n 表示不写 /etc/mtab ,这在 /etc 所在的文件系统为只读时用。因为此时的/还是只读
[ -d /proc/bus/usb ] && mount -n -t usbfs /proc/bus/usb /proc/bus/usb        # 如果存在 /proc/bus/usb 目录则把 /proc/bus/usb 以 usbfs 挂载到 /proc/bus/usb 下
mount -n -t sysfs /sys /sys >/dev/null 2>&1                                                    # 接下来就是把 /sys 目录以 sysfs 格式挂载到 /sys 目录下
 
########################################################################################################################################################
 
. /etc/init.d/functions             # 执行 /etc/init.d/functions 文件,该文件提供了很多有用的函数,具体见 “functions 脚本提供的函数”一文
 
########################################################################################################################################################
 
# Check SELinux status                                                       
selinuxfs=`awk '/ selinuxfs / { print $2 }' /proc/mounts`        
SELINUX=                                                                                                    
if [ -n "$selinuxfs" ] && [ "`cat /proc/self/attr/current`" != "kernel" ]; then            
 if [ -r $selinuxfs/enforce ] ; then
  SELINUX=`cat $selinuxfs/enforce`
 else
  # assume enforcing if you can't read it
  SELINUX=1
 fi
fi
 
if [ -x /sbin/restorecon ] && LC_ALL=C fgrep -q " /dev " /proc/mounts ; then
 /sbin/restorecon  -R /dev 2>/dev/null
fi
 
disable_selinux() {
 echo "*** Warning -- SELinux is active"
 echo "*** Disabling security enforcement for system recovery."
 echo "*** Run 'setenforce 1' to reenable."
 echo "0" > $selinuxfs/enforce
}
 
relabel_selinux() {
    if [ -x /usr/bin/rhgb-client ] && /usr/bin/rhgb-client --ping ; then
 chvt 1
    fi
    echo "
         *** Warning -- SELinux relabel is required. ***
  *** Disabling security enforcement.         ***
  *** Relabeling could take a very long time, ***
  *** depending on file system size.          ***
  "
    echo "0" > $selinuxfs/enforce
    /sbin/fixfiles -F relabel > /dev/null 2>&1
    rm -f  /.autorelabel
    echo "*** Enabling security enforcement.         ***"
    echo $SELINUX > $selinuxfs/enforce
    if [ -x /usr/bin/rhgb-client ] && /usr/bin/rhgb-client --ping ; then
 chvt 8
    fi
}
 
########################################################################################################################################################
 
if [ "$HOSTTYPE" != "s390" -a "$HOSTTYPE" != "s390x" ]; then
  last=0
  for i in `LC_ALL=C grep '^[0-9].*respawn:/sbin/mingetty' /etc/inittab | sed 's/^.* tty\([0-9][0-9]*\).*/\1/g'`; do
        > /dev/tty$i
        last=$i
  done
  if [ $last -gt 0 ]; then
       > /dev/tty$((last+1))
       > /dev/tty$((last+2))
  fi
fi
 
########################################################################################################################################################
 
if [ "$CONSOLETYPE" = "vt" -a -x /sbin/setsysfont ]; then            # 下面是设置屏幕的默认字体。如果 CONSOLETYPE 变量的值为 vt 且 /sbin/setsysfont 命令可执行
   echo -n "Setting default font ($SYSFONT): "                            # 打印 "setting deafault font xxxx " ,默认字体应该是 xxxx
   /sbin/setsysfont                                                                   
# 执行 /sbin/setsysfont
   if [ $? -eq 0 ]; then                                                                
# 如果上述命令执行返回的 exit status 为 0
      success                                                                               
 # 则调用 success 函数(来自于 functions 脚本),记录一个成功的事件
   else
      failure                                                                                
# 否则调用 failure 函数
   fi
   echo ; echo                                                
fi
 
########################################################################################################################################################
 
# Print a text banner.                                                                # 下面部分是打印 "welcome to xxxxx" 的标题栏

echo -en $"\t\tWelcome to "                                                      # 打印 "Welcom to" ,同时不换行
if LC_ALL=C fgrep -q "Red Hat" /etc/redhat-release ; then           # 从 /etc/redhat-release 文件中找出含有 "Red Hat" 的行,如果找到
 [ "$BOOTUP" = "color" ] && echo -en "
"                        # 则变量 BOOTUP 的值为 color ,并设置输出字体输出红色
 echo -en "Red Hat"                                                                    # 同时打印 "Red Hat" ,接下来打印发行版本(产品)
 [ "$BOOTUP" = "color" ] && echo -en "
"                        #  如果变量 BOOTUP 的值为 color 则设置输出字体为白色
 PRODUCT=`sed "s/Red Hat \(.*\) release.*/\1/" /etc/redhat-release`    # 从 /etc/redhat-release 中找出含有 "Red Hat" 且后面若干字符,然后是 "release" 的行,并截取中间部分给 PRODUCT
                                                                                                    
echo " $PRODUCT"                                                                            #  输出变量 PRODUCT 的值(白色)
elif LC_ALL=C fgrep -q "Fedora" /etc/redhat-release ; then             # 如果/etc/redhat-release 中没有 Red Hat 字符串,但有 Fedora ,则执行类似过程
 [ "$BOOTUP" = "color" ] && echo -en "
"
 echo -en "Fedora"
 [ "$BOOTUP" = "color" ] && echo -en "
"
 PRODUCT=`sed "s/Fedora \(.*\) release.*/\1/" /etc/redhat-release`
 echo " $PRODUCT"
else                                                                                            
# 如果 /etc/redhat-release 中既没有含 Red Hat 也没有含 Fedora 的行,则
 PRODUCT=`sed "s/ release.*//g" /etc/redhat-release`                    # 找到含有 ‘release' 的行,并把它前面的部分输出,作为 PRODUCT 变量的值并输出
 echo "$PRODUCT"
fi
 
# 补充 :实际效果是 Red Hat 两个字是红色,其他都是白色
########################################################################################################################################################

if [ "$PROMPT" != "no" ]; then                                                        # 如果变量 PROMPT 的值不为 "no" (表示允许交互启动),则
 echo -en $"\t\tPress 'I' to enter interactive startup."                           
 # 打印提示信息“Press I to enter interactive startup”,但此时按 I 还未起作用
 echo    
fi
######################################################################################################################################################## 
# 注释 :下面部分是设置输出到 console 的日志的详细级别
 
# Fix console loglevel                                                                  # 设置控制台的日志级别
if [ -n "$LOGLEVEL" ]; then                                                            # 如果 LOGLEVEL 变量的值不为空
 /bin/dmesg -n $LOGLEVEL                                                                # 则执行 dmesg ,设置打印到 consoel 的日志的级别为 $LOGLEVEL
fi
 
######################################################################################################################################################## 
 
# 注释 :下面部分是启动 udev 并加载 ide、scsi、network、audio 以及其他类型的设备的模块的部分
 
[ -x /sbin/start_udev ] && /sbin/start_udev                                    # 如果 /sbin/start_udev 可执行,则执行它,会在屏幕上显示 Starting udev ... [OK]”
 
# Only read this once.
cmdline=$(cat /proc/cmdline)                                                        # 读取 /proc/cmdline ,这是内核启动的时的参数,赋予变量 cmdline
 
# Initialize hardware                                                                     # 下面初始化硬件
if [ -f /proc/sys/kernel/modprobe ]; then                                        # 如果 /proc/sys/kernel/modprobe 文件存在(该文件告诉内核用什么命令来加载模块),则
   if ! strstr "$cmdline" nomodules && [ -f /proc/modules ] ; then            # 如果 $cmdline 变量的值含有 nomodules ,且存在 /proc/modules 文件,则
       sysctl -w kernel.modprobe="/sbin/modprobe" >/dev/null 2>&1            # 使用 sysctl 设置 kernel.modprobe 为 /sbin/modprobe 命令
       sysctl -w kernel.hotplug="/sbin/hotplug" >/dev/null 2>&1                    # 使用 sysctl 设置  kernel.hotplug 为 /sbin/hotplug 命令
   else                                                                                           # 如果不存在 /proc/sys/kernel/modprobe 文件,则                             
       # We used to set this to NULL, but that causes 'failed to exec' messages"    
       sysctl -w kernel.modprobe="/bin/true" >/dev/null 2>&1                # 使用 sysctl 设置 kernel.modprobe 为 /bin/true
       sysctl -w kernel.hotplug="/bin/true" >/dev/null 2>&1                    # kernel.hotplug 也一样
   fi
fi
 
######################################################################################################################################################## 
 
# 注释 :下面开始真正的加载各种类型的设备的驱动
 
# 首先是找出那些模块需要被加载,并把模块名按类分别放到 ide、scsi、network、audio、other 5个变量中
 
echo -n $"Initializing hardware... "                                                    # 打印 "initalizing hardware.." (不换行),并开始初始化硬件
 
ide=""                                                                                              # 下面这些变量都是为了存储的型号,格式为 "   ..."           
scsi=""
network=""
audio=""
other=""
eval `kmodule | while read devtype mod ; do                                # 从 kmodule 命令的输出一次读入两个变量 devtype (设备类型)和 mod(模块名)
 case "$devtype" in                                                                            # 根据 devtype 做出适当的选择 
  "IDE") ide="$ide $mod"                                                                            # 如果 devtype 的值为 IDE ,则把 mod 加入到现有的 ide 变量的值中 
     echo "ide=\"$ide"\";;                                                                            # 输出 "ide=" 然后是变量 ide 的值
  "SCSI") scsi="$scsi $mod"                                                                          # 如果 devtype 的值为 SCSI ,则把 mod 变量的值加入到 scsi 变量的值中
     echo "scsi=\"$scsi"\";;                                                                           # 输出 "scsi=" 再输出 $scsi  
  "NETWORK") network="$network $mod"                                                    # 下面的 NETWORK 和 AUDIO 也一样
     echo "network=\"$network"\";;
  "AUDIO") audio="$audio $mod"
     echo "audio=\"$audio"\";;
  *) other="$other $mod"                                                                            # 如果是属于 other 类型的则把模块名 $mod 加入到 other 变量的值列表中
     echo "other=\"$other"\";;
 esac
done`
 
load_module () {                    # 定义一个函数名为 load_module
 LC_ALL=C fgrep -xq "$1" /etc/hotplug/blacklist 2>/dev/null || modprobe $1 >/dev/null 2>&1        # 在 /etc/hotplug/blacklist 文件中查找是否有指定的模块,如果没有
}                                                                                                                                            # 再用 modprobe 加载指定的模块
 
# IDE                                        # 下面开始加载所有 IDE 类型的设备的模块
for module in $ide ; do                 # 从 ide 变量中每次取出1个值,赋予变量 module 
 load_module $module                 # 再用 load_module 函数加载它。如果该模块存在于 /etc/hotplug/blacklist ,则不会被加载(因为存在于黑名单中)
done
 
# SCSI                                    # SCSI 方面的比较特殊,除了加载 scsi 变量中的模块外,还会从 modprobe -c (显示所有配置)中找出 scsi 卡(hostadapter)的模块
for module in `/sbin/modprobe -c | awk '/^alias[[:space:]]+scsi_hostadapter[[:space:]]/ { print $3 }'` $scsi; do   # 从 modprobe -c 中找出所有scsi卡的模块别名,
 load_module $module             # 并和 scsi 变量一起,通过 for 循环一一加载
done

load_module floppy                # 然后加载 floppy 模块
 
echo -n $" storage"                # 输出 "storage" ,表示存储方面的模块加载已经完成
 
# Network                            # 接下来是加载网络设备模块

pushd /etc/sysconfig/network-scripts >/dev/null 2>&1        # pushd 是一个 bash 的内建命令,把目录名放入目录堆栈的顶部,并进入指定目录
interfaces=`ls ifcfg* | LC_ALL=C egrep -v '(ifcfg-lo|:|rpmsave|rpmorig|rpmnew)' | \        # 找出 network-scripts 目录下所有 lscfg 开头的文件名,排除指定备份和loopback
            LC_ALL=C egrep -v '(~|\.bak)$' | \                                                                    # 排除以 ~ 和 .bask 结尾的文件名
            LC_ALL=C egrep 'ifcfg-[A-Za-z0-9\._-]+$' | \                                                       # 找出所有以 ifcfg- 开头,并以多个字母/数字结尾的文件名
     sed 's/^ifcfg-//g' |                                                                                                  # 把前缀 ifcfg- 去掉,只留下后面的接口名
     sed 's/[0-9]/ &/' | LC_ALL=C sort -k 1,1 -k 2n | sed 's/ //'`                                         # 在数字前面加上空格,是类型和编号分离,便于 sort 排序,然后再组合回去
                                                                                                                                 # 目的是按顺序启动接口
for i in $interfaces ; do                                                                                                # 对于在 $interfaces 变量中的每个接口
 eval $(LC_ALL=C fgrep "DEVICE=" ifcfg-$i)                                                                     # 从对应的文件 ifcfg-$i 找出 DEVICE= 行
 load_module $DEVICE                                                                                                 # 然后用 load_module 加载它,注意,DEVICE= 行可以是别名,例如 eth1.n7css
done
popd >/dev/null 2>&1                                                                                                 # 把 network-scripts 从目录名堆栈中弹出,并返回原来的目录
                                                                                
for module in $network ; do                                                                                        #  剩下还有 network 变量中的模块
 load_module $module                                                                                                # 也一一加载
done
 
echo -n $" network"                                                                                                    # 输出 network 字符串,表示加载网络设备模块工作完毕
 
# Sound
for module in `/sbin/modprobe -c | awk '/^alias[[:space:]]+snd-card-[[:digit:]]+[[:space:]]/ { print $3 }'` $audio; do    # 和 scsi 一样,加载在 modprobe -c 和 audio 变量
 load_module $module                                                                                                                                          # 中的模块
done
 
echo -n $" audio"                                                                                                        # 输出 audio ,表示声卡设备驱动加载完毕,一般会有多个驱动被加载        
 
# Everything else (duck and cover)                                                                             # 剩下的就是 other 类型的设备了
for module in $other ; do
 load_module $module                                                                                                # 这个直接用 load_moudle 函数加载了
done
 
echo -n $" done"                                                                                                        # 输出 done 表示完成
success                                                                                                                    # 调用 success 函数,记录该事件
echo
 
######################################################################################################################################################## 
# 注释 :下面是启用 Software-RAID 的检测
 
echo "raidautorun /dev/md0" | nash --quiet       # 用 nash (小型脚本解释器)执行 "raidautorun /dev/md0" 命令,对所有paritition ID 为 0xFD 分区进行检查
########################################################################################################################################################  
 
# Start the graphical boot, if necessary; /usr may not be mounted yet, so we             # 显示图形模式的启动画面,但由于 rhgb 命令在 /usr 分区上,
# may have to do this again after mounting                                                             #  这时 /usr 分区还没有被挂载,所以在挂载后重新做一遍这部分脚本
RHGB_STARTED=0           # 初始化 RHGB_STARTED 变量的值为 0,表示尚未启动。RHGB 是 redhat graphical boot 的含义,
mount -n /dev/pts         # 挂载 /dev/pts ,类型是 devpts ,目的是获得 pty ,这是一种伪文件系统
 
if strstr "$cmdline" rhgb && [ "$BOOTUP" = "color" -a "$GRAPHICAL" = "yes" -a -x /usr/bin/rhgb ]; then        # 如果内核启动参数 $cmdline 含有 rhgb ,且
                                                                                                                                                        # BOOTUP 变量的值为 color ,且 GRPAHICAL 变量的值为 yes
                                                                                                                                                        # 且 /usr/bin/rhgb 文件存在并可执行
   LC_MESSAGES= /usr/bin/rhgb                                                                                                           # 把 "/usr/sbin/rhgb" 赋予变量 LC_MESSAGES
   RHGB_STARTED=1                                                                                                                            # RHGB_STARTED 变量的值为1。
fi
 
########################################################################################################################################################  
# 注释 :下面部分是使用 sysctl 设置内核的参数
 
# Configure kernel parameters                    
update_boot_stage RCkernelparam             # 调用 update_boot_stage 函数,该函数由 /etc/rc.d/init.d/functions 脚本定义,主要执行 "/usr/sbin/rhgb-client --update $1"
action $"Configuring kernel parameters: " sysctl -e -p /etc/sysctl.conf    # 调用 action 函数,执行 sysctl 命令,它读取 /etc/sysctl.conf ,同时输出 “Configuring kernel
                                                                                                       # parameters” 字符串,action 函数也是由 /etc/rc.d/init.d/functions 脚本定义
 
# 补充 :action 函数的作用是把第一个参数 $1 赋予变量 string 并输出到屏幕,同时把该字符串也写入 /etc/rhgb/temp/rhgb-console
 
# 然后把 $1 后面的部分作为命令交给 initlog 执行,并根据结果调用 success 或者 failure 函数。而 success 或者 failure 函数又会根据结果输出 [ OK ] 或者 [ FAILED ] 。
 
# 除了 success 和 failure 函数外,functions 脚本还定义了 passed 和 warnning 函数,它们又分别调用 echo_passwd() 和 echo_warnning()函数,
 
# 以输出 [ PASSED ] 和 [ WARNNING ]
 
########################################################################################################################################################  
# 注释 :下面设置系统的硬件时钟
# Set the system clock.                    # 接下来设置系统时钟
update_boot_stage RCclock                # 同样是告诉 update_boot_stage 该事件(执行 /usr/bin/rhgb-client --update="$1" 命令,这里 $1 就是 "RCclock")
ARC=0                                                
SRM=0
UTC=0
 
if [ -f /etc/sysconfig/clock ]; then        # 如果存在 /etc/sysconfig/clock 则执行该文件
   . /etc/sysconfig/clock
 
   # convert old style clock config to new values
   if [ "${CLOCKMODE}" = "GMT" ]; then                        # 如果变量 CLOCKMODE 为旧式的 GMT 格式
      UTC=true                                                                # 则 UTC 变量的值为 ture 
   elif [ "${CLOCKMODE}" = "ARC" ]; then                     # 如果 CLOCKMODE 的值是 ARC ,则
      ARC=true                                                                # ARC 的值为 true
   fi                                                                         # 如果 CLOCKMODE 不等于 GMT 或者 UTC ,则 UTC 的值等于 /etc/sysconfig/clock 中的值,一般都是 false
fi                                                                            # 如果 CLOCKMODE 不等于 GMT 后者 ARC ,则 UTC 的值为 0
 
CLOCKDEF=""                                                            # CLOCKDEF 变量的值默认为空
CLOCKFLAGS="$CLOCKFLAGS --hctosys"                       # 而 CLOCKFLAGS 变量的值为原来的值(可能为空)加上 '--hctosys' ,表示把硬件时钟写入内核时钟
 
case "$UTC" in                                                          # 根据 UTC 变量的值进行选择                                             
    yes|true) CLOCKFLAGS="$CLOCKFLAGS --utc"             # 如果 UTC 的值为 yes 或者 true,则变量 CLOCKFLAGS 的值加上 --utc ,表示采用 UTC 时区
  CLOCKDEF="$CLOCKDEF (utc)" ;;                                     # 同时变量 CLOCKDEF 的值加上 "(utc)"
    no|false) CLOCKFLAGS="$CLOCKFLAGS --localtime"     # 如果变量 UTC 的值为 false 或者 no,则
  CLOCKDEF="$CLOCKDEF (localtime)" ;;                        # CLOCKDEF 的值加上 "(localtime)" 。由于安装 OS时没有选择 UTC,CLOCKDEF 的值一般最后就是 (localtime) 而已
esac
case "$ARC" in                                                          # 根据 ARC 变量的值来选择              
    yes|true) CLOCKFLAGS="$CLOCKFLAGS --arc"            # 如果是 yes 或者 true ,则 CLOCKFLAGS 的值加上 --arc ,CLOCKDEF 的值加上 '(arc)'
  CLOCKDEF="$CLOCKDEF (arc)" ;;                                # 如果 ARC 的值为 0 ,则 CLOCKFLAGS 和 CLOCKDEF 的值都不变
esac
case "$SRM" in                                                         # 如果 SRM 的值是 yes 或者 true ,则 CLOCKFLAGS 的值加上 "--srm" ,CLOCKDEF 加上 "(srm)"
    yes|true) CLOCKFLAGS="$CLOCKFLAGS --srm"
  CLOCKDEF="$CLOCKDEF (srm)" ;;
esac
 
/sbin/hwclock $CLOCKFLAGS                    # 执行 hwclock $CLOCKFLAGS 命令,一般就是 /sbin/hwclock --hctosys
 
action $"Setting clock $CLOCKDEF: `date`" date        # 并输出 "setting clock " 和 $CLOCKDEF ,并执行 date 输出当前时间,然后输出 [ OK ]
######################################################################################################################################################## 
 
阅读(1349) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~