#!/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 "                                                      # 打印 "<tab><tab>Welcom to" ,同时不换行
if LC_ALL=C fgrep -q "Red Hat" /etc/redhat-release ; then           # 从 /etc/redhat-release 文件中找出含有 "Red Hat" 的行,如果找到
 [ "$BOOTUP" = "color" ] && echo -en "\\033[0;31m"                        # 则变量 BOOTUP 的值为 color ,并设置输出字体输出红色
 echo -en "Red Hat"                                                                    # 同时打印 "Red Hat" ,接下来打印发行版本(产品)
 [ "$BOOTUP" = "color" ] && echo -en "\\033[0;39m"                        #  如果变量 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 "\\033[0;31m"
 echo -en "Fedora"
 [ "$BOOTUP" = "color" ] && echo -en "\\033[0;39m"
 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=""                                                                                              # 下面这些变量都是为了存储的型号,格式为 " <module1> <module2> <module3> ..."          
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 分区进行检查
######################################################################################################################################################## 

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jiangcl207504/archive/2010/01/15/5192215.aspx