Linux系统脚本分析之rc.sysinit

1  2#!/bin/bash 3# 4# /etc/rc.d/rc.sysinit - run once at boot time 5 6# 7 8 9# Rerun ourselves through initlog                                                 10 // 通过 /sbin/initlog 命令重新运行自己 11 if [ -z "$IN_INITLOG" -a -x /sbin/initlog ]; then                             12 // 条件是 :如果 IN_INITLOG 变量的值不为空,且 /sbin/initlog 可执行 13     exec /sbin/initlog -r /etc/rc.d/rc.sysinit                                 14 // 调用 exec /sbin/initlog ,-r 是表示运行某个程序 15 fi 16 17 18 ###################################################################################################################################################### 19 20 21 HOSTNAME=`/bin/hostname`                             22 # 取得主机名 23 HOSTTYPE=`uname -m`                                     24 # 取得主机类型 25 unamer=`uname -r`                                          26 # 取得内核的 release 版本(例如 2.4.9.30-8) 27 28 eval version=`echo $unamer | awk -F '.' '{ print "(" $1 " " $2 ")" }'`            # 取得版本号 29 30 31 if [ -f /etc/sysconfig/network ]; then                # 如果存在 /etc/sysconfig/network ,则执行该文件。 32 33 34     . /etc/sysconfig/network                             # network 文件主要控制是否启用网络、默认网关、主机名 35 fi 36 37 38 if [ -z "$HOSTNAME" -o "$HOSTNAME" = "(none)" ]; then             39 # 如果执行 network 文件后 HOSTNAME 为空或者为 "(none)" , 40     HOSTNAME=localhost                                                         41 # 则将主机名设置为 "localhost" 42 fi 43 44 45 46 # Mount /proc and /sys (done here so volume labels can work with fsck)         47 # 接下来是挂载 /proc 和 /sys ,这样 fsck 才能使用卷标 48 mount -n -t proc /proc /proc                                                                       49 #  -n 表示不写 /etc/mtab ,这在 /etc 所在的文件系统为只读时用。因为此时的/还是只读 5051 52 [ -d /proc/bus/usb ] && mount -n -t usbfs /proc/bus/usb /proc/bus/usb         53 # 如果存在 /proc/bus/usb 目录则把 /proc/bus/usb 以 usbfs 挂载到 /proc/bus/usb 下 54 55 mount -n -t sysfs /sys /sys >/dev/null 2>&1                                                     56 # 接下来就是把 /sys 目录以 sysfs 格式挂载到 /sys 目录下 57 58 59 ######################################################################################################################################################## 60 61 62 63 . /etc/init.d/functions             # 执行 /etc/init.d/functions 文件,该文件提供了很多有用的函数,具体见 “functions 脚本提供的函数”一文 64 65 66 67 ######################################################################################################################################################## 68 69 # Check SELinux status                                                        70 selinuxfs=`awk '/ selinuxfs / { print $2 }' /proc/mounts`         71 SELINUX=                                                                                                     72 if [ -n "$selinuxfs" ] && [ "`cat /proc/self/attr/current`" != "kernel" ]; then             73  if [ -r $selinuxfs/enforce ] ; then 74   SELINUX=`cat $selinuxfs/enforce` 75  else 76   # assume enforcing if you can't read it 77   SELINUX=1 78  fi 79 fi 80 81 82 83 84 if [ -x /sbin/restorecon ] && LC_ALL=C fgrep -q " /dev " /proc/mounts ; then 85  /sbin/restorecon  -R /dev 2>/dev/null 86 fi 87 88 89 90 disable_selinux() { 91  echo "*** Warning -- SELinux is active" 92  echo "*** Disabling security enforcement for system recovery." 93  echo "*** Run 'setenforce 1' to reenable." 94  echo "0" > $selinuxfs/enforce 95 } 96 97 98 relabel_selinux() { 99     if [ -x /usr/bin/rhgb-client ] && /usr/bin/rhgb-client --ping ; then 100  chvt 1 101     fi 102     echo " 103          *** Warning -- SELinux relabel is required. *** 104   *** Disabling security enforcement.         *** 105   *** Relabeling could take a very long time, *** 106   *** depending on file system size.          *** 107   " 108     echo "0" > $selinuxfs/enforce 109     /sbin/fixfiles -F relabel > /dev/null 2>&1 110     rm -f  /.autorelabel 111     echo "*** Enabling security enforcement.         ***" 112     echo $SELINUX > $selinuxfs/enforce 113     if [ -x /usr/bin/rhgb-client ] && /usr/bin/rhgb-client --ping ; then 114  chvt 8 115     fi 116 } 117 118 119 ######################################################################################################################################################## 120 121 122 123 if [ "$HOSTTYPE" != "s390" -a "$HOSTTYPE" != "s390x" ]; then 124   last=0 125   for i in `LC_ALL=C grep '^[0-9].*respawn:/sbin/mingetty' /etc/inittab | sed 's/^.* tty\([0-9][0-9]*\).*/\1/g'`; do 126         > /dev/tty$i 127         last=$i 128   done 129   if [ $last -gt 0 ]; then 130        > /dev/tty$((last+1)) 131        > /dev/tty$((last+2)) 132   fi 133 fi 134 135 ######################################################################################################################################################## 136 137 138 if [ "$CONSOLETYPE" = "vt" -a -x /sbin/setsysfont ]; then             139 # 下面是设置屏幕的默认字体。如果 CONSOLETYPE 变量的值为 vt 且 /sbin/setsysfont 命令可执行 140    echo -n "Setting default font ($SYSFONT): "                            141  # 打印 "setting deafault font xxxx " ,默认字体应该是 xxxx 142 143    /sbin/setsysfont                                                                    144 # 执行 /sbin/setsysfont 145    if [ $? -eq 0 ]; then                                                                 146 # 如果上述命令执行返回的 exit status 为 0 147       success                                                                                148  # 则调用 success 函数(来自于 functions 脚本),记录一个成功的事件 149    else 150 151       failure                                                                                 152 # 否则调用 failure 函数 153    fi 154 155    echo ; echo                                                 156 157 fi 158 159 160 ######################################################################################################################################################## 161 162 163 164 165 # Print a text banner.                              166 # 下面部分是打印 "welcome to xxxxx" 的标题栏 167 168 169 echo -en $"\t\tWelcome to "  170             # 打印 "<tab><tab>Welcom to" ,同时不换行 171 if LC_ALL=C fgrep -q "Red Hat" /etc/redhat-release ; then 172           # 从 /etc/redhat-release 文件中找出含有 "Red Hat" 的行,如果找到 173  [ "$BOOTUP" = "color" ] && echo -en " 174 \\033[0;31m 175 " 176              # 则变量 BOOTUP 的值为 color ,并设置输出字体输出红色 177  echo -en "Red Hat"  178             # 同时打印 "Red Hat" ,接下来打印发行版本(产品) 179  [ "$BOOTUP" = "color" ] && echo -en " 180 \\033[0;39m 181 "                         182 #  如果变量 BOOTUP 的值为 color 则设置输出字体为白色 183  PRODUCT=`sed "s/Red Hat \(.*\) release.*/\1/" /etc/redhat-release`    184   185 # 从 /etc/redhat-release 中找出含有 "Red Hat" 且后面若干字符,然后是 "release" 的行,并截取中间部分给 PRODUCT 186 187 188 189 echo " $PRODUCT"      190 #  输出变量 PRODUCT 的值(白色) 191 elif LC_ALL=C fgrep -q "Fedora" /etc/redhat-release ; then             192  # 如果/etc/redhat-release 中没有 Red Hat 字符串,但有 Fedora ,则执行类似过程 193 194  [ "$BOOTUP" = "color" ] && echo -en " 195 \\033[0;31m 196 " 197  echo -en "Fedora" 198  [ "$BOOTUP" = "color" ] && echo -en " 199 \\033[0;39m 200 " 201  PRODUCT=`sed "s/Fedora \(.*\) release.*/\1/" /etc/redhat-release` 202  echo " $PRODUCT" 203 else                                                                                             204 # 如果 /etc/redhat-release 中既没有含 Red Hat 也没有含 Fedora 的行,则 205  PRODUCT=`sed "s/ release.*//g" /etc/redhat-release`                     206 # 找到含有 ‘release' 的行,并把它前面的部分输出,作为 PRODUCT 变量的值并输出 207 208  echo "$PRODUCT" 209 210 fi 211 212 213 214 # 补充 :实际效果是 Red Hat 两个字是红色,其他都是白色 215 216 217 ######################################################################################################################################################## 218 219 if [ "$PROMPT" != "no" ]; then                                                         220 # 如果变量 PROMPT 的值不为 "no" (表示允许交互启动),则 221  echo -en $"\t\tPress 'I' to enter interactive startup."                            222  # 打印提示信息“Press I to enter interactive startup”,但此时按 I 还未起作用 223  echo     224 225 fi 226 227 228 ########################################################################################################################################################  229 230 231 # 注释 :下面部分是设置输出到 console 的日志的详细级别 232 233 234 # Fix console loglevel                                                                  # 设置控制台的日志级别 235 if [ -n "$LOGLEVEL" ]; then                                                            # 如果 LOGLEVEL 变量的值不为空 236  /bin/dmesg -n $LOGLEVEL                                                                # 则执行 dmesg ,设置打印到 consoel 的日志的级别为 $LOGLEVEL 237 fi 238 239 ########################################################################################################################################################  240 241 242 243 # 注释 :下面部分是启动 udev 并加载 ide、scsi、network、audio 以及其他类型的设备的模块的部分 244 245 246 [ -x /sbin/start_udev ] && /sbin/start_udev                                    # 如果 /sbin/start_udev 可执行,则执行它,会在屏幕上显示 “Starting udev ... [OK]” 247 248 249 # Only read this once. 250 cmdline=$(cat /proc/cmdline)                                                        # 读取 /proc/cmdline ,这是内核启动的时的参数,赋予变量 cmdline 251 252 253 # Initialize hardware                                                                     254 # 下面初始化硬件 255 if [ -f /proc/sys/kernel/modprobe ]; then                                         256 # 如果 /proc/sys/kernel/modprobe 文件存在(该文件告诉内核用什么命令来加载模块),则 257 258    if ! strstr "$cmdline" nomodules && [ -f /proc/modules ] ; then             259 # 如果 $cmdline 变量的值含有 nomodules ,且存在 /proc/modules 文件,则 260 261        sysctl -w kernel.modprobe="/sbin/modprobe" >/dev/null 2>&1            262  # 使用 sysctl 设置 kernel.modprobe 为 /sbin/modprobe 命令 263        sysctl -w kernel.hotplug="/sbin/hotplug" >/dev/null 2>&1                     264 # 使用 sysctl 设置  kernel.hotplug 为 /sbin/hotplug 命令 265 266    else                                                                                            267 # 如果不存在 /proc/sys/kernel/modprobe 文件,则                              268 269        # We used to set this to NULL, but that causes 'failed to exec' messages"     270 271        sysctl -w kernel.modprobe="/bin/true" >/dev/null 2>&1                 272 # 使用 sysctl 设置 kernel.modprobe 为 /bin/true 273 274        sysctl -w kernel.hotplug="/bin/true" >/dev/null 2>&1                     275 # kernel.hotplug 也一样 276 277    fi 278 279 fi 280 281 282 ########################################################################################################################################################  283 284 285 # 注释 :下面开始真正的加载各种类型的设备的驱动 286 287 # 首先是找出那些模块需要被加载,并把模块名按类分别放到 ide、scsi、network、audio、other 5个变量中 288 289 290 291 echo -n $"Initializing hardware... "               292             # 打印 "initalizing hardware.." (不换行),并开始初始化硬件 293 294 295 ide=""           296             # 下面这些变量都是为了存储的型号,格式为 " <module1> <module2> <module3> ..."            297 scsi="" 298 network="" 299 audio="" 300 other="" 301 eval `kmodule | while read devtype mod ; do      302             # 从 kmodule 命令的输出一次读入两个变量 devtype (设备类型)和 mod(模块名) 303  case "$devtype" in                                                      304              # 根据 devtype 做出适当的选择  305   "IDE") ide="$ide $mod"                                                                  306           # 如果 devtype 的值为 IDE ,则把 mod 加入到现有的 ide 变量的值中  307      echo "ide=\"$ide"\";;                                                           308            # 输出 "ide=" 然后是变量 ide 的值 309   "SCSI") scsi="$scsi $mod"                                                               310            # 如果 devtype 的值为 SCSI ,则把 mod 变量的值加入到 scsi 变量的值中 311      echo "scsi=\"$scsi"\";;                                                                 312           # 输出 "scsi=" 再输出 $scsi   313   "NETWORK") network="$network $mod"                                     314           # 下面的 NETWORK 和 AUDIO 也一样 315      echo "network=\"$network"\";; 316   "AUDIO") audio="$audio $mod" 317      echo "audio=\"$audio"\";; 318   *) other="$other $mod"                                                       319          # 如果是属于 other 类型的则把模块名 $mod 加入到 other 变量的值列表中 320      echo "other=\"$other"\";; 321  esac 322 done` 323 324 325 load_module () {           326          # 定义一个函数名为 load_module 327  LC_ALL=C fgrep -xq "$1" /etc/hotplug/blacklist 2>/dev/null || modprobe $1 >/dev/null 2>&1 328         # 在 /etc/hotplug/blacklist 文件中查找是否有指定的模块,如果没有, 329 }                                                                                                        # 再用 modprobe 加载指定的模块 330 331 332 # IDE                         333             # 下面开始加载所有 IDE 类型的设备的模块 334 for module in $ide ; do   335             # 从 ide 变量中每次取出1个值,赋予变量 module  336  load_module $module  337             # 再用 load_module 函数加载它。如果该模块存在于 /etc/hotplug/blacklist ,则不会被加载(因为存在于黑名单中) 338 done 339 340 341 # SCSI               342             # SCSI 方面的比较特殊,除了加载 scsi 变量中的模块外,还会从 modprobe -c (显示所有配置)中找出 scsi 卡(hostadapter)的模块 343 for module in `/sbin/modprobe -c | awk '/^alias[[:space:]]+scsi_hostadapter[[:space:]]/ { print $3 }'` $scsi; do 344    # 从 modprobe -c 中找出所有scsi卡的模块别名, 345  load_module $module   346          # 并和 scsi 变量一起,通过 for 循环一一加载 347 done 348 349 load_module floppy                # 然后加载 floppy 模块 350 351 352 echo -n $" storage"                # 输出 "storage" ,表示存储方面的模块加载已经完成 353 354 # Network                            # 接下来是加载网络设备模块 355 356 357 pushd /etc/sysconfig/network-scripts >/dev/null 2>&1        # pushd 是一个 bash 的内建命令,把目录名放入目录堆栈的顶部,并进入指定目录 358 interfaces=`ls ifcfg* | LC_ALL=C egrep -v '(ifcfg-lo|:|rpmsave|rpmorig|rpmnew)' | \        # 找出 network-scripts 目录下所有 lscfg 开头的文件名,排除指定备份和loopback 359             LC_ALL=C egrep -v '(~|\.bak)$' | \                                                                    # 排除以 ~ 和 .bask 结尾的文件名 360             LC_ALL=C egrep 'ifcfg-[A-Za-z0-9\._-]+$' | \                                                       # 找出所有以 ifcfg- 开头,并以多个字母/数字结尾的文件名 361      sed 's/^ifcfg-//g' |                                                                                                  # 把前缀 ifcfg- 去掉,只留下后面的接口名 362      sed 's/[0-9]/ &/' | LC_ALL=C sort -k 1,1 -k 2n | sed 's/ //'`                                         # 在数字前面加上空格,是类型和编号分离,便于 sort 排序,然后再组合回去 363 364                                                                                                                                  # 目的是按顺序启动接口 365 366 for i in $interfaces ; do                                                                                                # 对于在 $interfaces 变量中的每个接口 367  eval $(LC_ALL=C fgrep "DEVICE=" ifcfg-$i)                                                                     # 从对应的文件 ifcfg-$i 找出 DEVICE= 行 368  load_module $DEVICE                                                                                                 # 然后用 load_module 加载它,注意,DEVICE= 行可以是别名,例如 eth1.n7css 369 done 370 popd >/dev/null 2>&1                                                                                                 # 把 network-scripts 从目录名堆栈中弹出,并返回原来的目录 371 372 373 for module in $network ; do                                                                                        #  剩下还有 network 变量中的模块 374  load_module $module                                                                                                # 也一一加载 375 done 376 377 378 echo -n $" network"                                                                                                    # 输出 network 字符串,表示加载网络设备模块工作完毕 379 # Sound 380 for module in `/sbin/modprobe -c | awk '/^alias[[:space:]]+snd-card-[[:digit:]]+[[:space:]]/ { print $3 }'` $audio; do    # 和 scsi 一样,加载在 modprobe -c 和 audio 变量 381  load_module $module                                                                                                                                          # 中的模块 382 done 383 384 385 echo -n $" audio"                                                                                                        # 输出 audio ,表示声卡设备驱动加载完毕,一般会有多个驱动被加载         386 387 # Everything else (duck and cover)                                                                             # 剩下的就是 other 类型的设备了 388 for module in $other ; do 389  load_module $module                                                                                                # 这个直接用 load_moudle 函数加载了 390 done 391 392 echo -n $" done"                                                                                                        # 输出 done 表示完成 393 success                                                                                                                    # 调用 success 函数,记录该事件 394 echo 395 396 ########################################################################################################################################################  397 398 399 # 注释 :下面是启用 Software-RAID 的检测 400 echo "raidautorun /dev/md0" | nash --quiet       # 用 nash (小型脚本解释器)执行 "raidautorun /dev/md0" 命令,对所有paritition ID 为 0xFD 分区进行检查 401 402 403 ########################################################################################################################################################   404 405 406 # Start the graphical boot, if necessary; /usr may not be mounted yet, so we             # 显示图形模式的启动画面,但由于 rhgb 命令在 /usr 分区上, 407 # may have to do this again after mounting                                                             #  这时 /usr 分区还没有被挂载,所以在挂载后重新做一遍这部分脚本 408 RHGB_STARTED=0           # 初始化 RHGB_STARTED 变量的值为 0,表示尚未启动。RHGB 是 redhat graphical boot 的含义, 409 mount -n /dev/pts         # 挂载 /dev/pts ,类型是 devpts ,目的是获得 pty ,这是一种伪文件系统 410 411 412 if strstr "$cmdline" rhgb && [ "$BOOTUP" = "color" -a "$GRAPHICAL" = "yes" -a -x /usr/bin/rhgb ]; then        # 如果内核启动参数 $cmdline 含有 rhgb ,且 413                                                                                                                 # BOOTUP 变量的值为 color ,且 GRPAHICAL 变量的值为 yes 414 415                             # 且 /usr/bin/rhgb 文件存在并可执行 416    LC_MESSAGES= /usr/bin/rhgb                                                                                                           # 把 "/usr/sbin/rhgb" 赋予变量 LC_MESSAGES 417    RHGB_STARTED=1                                                                                                                            # RHGB_STARTED 变量的值为1。 418 fi 419 420 421 ########################################################################################################################################################   422 423 424 425 426 427 # 注释 :下面部分是使用 sysctl 设置内核的参数 428 # Configure kernel parameters                     429 update_boot_stage RCkernelparam             # 调用 update_boot_stage 函数,该函数由 /etc/rc.d/init.d/functions 脚本定义,主要执行 "/usr/sbin/rhgb-client --update $1" 430 action $"Configuring kernel parameters: " sysctl -e -p /etc/sysctl.conf    # 调用 action 函数,执行 sysctl 命令,它读取 /etc/sysctl.conf ,同时输出 “Configuring kernel 431 432                                                                                                        # parameters” 字符串,action 函数也是由 /etc/rc.d/init.d/functions 脚本定义 433 434 # 补充 :action 函数的作用是把第一个参数 $1 赋予变量 string 并输出到屏幕,同时把该字符串也写入 /etc/rhgb/temp/rhgb-console 435 436 437 438 # 然后把 $1 后面的部分作为命令交给 initlog 执行,并根据结果调用 success 或者 failure 函数。 439 而 success 或者 failure 函数又会根据结果输出 [ OK ] 或者 [ FAILED ]440 441 # 除了 success 和 failure 函数外,functions 脚本还定义了 passed 和 warnning 函数,它们又分别调用 echo_passwd() 和 echo_warnning()函数, 442 443 # 以输出 [ PASSED ] 和 [ WARNNING ] 444 445 ########################################################################################################################################################   446 447 448 # 注释 :下面设置系统的硬件时钟 449 # Set the system clock.                    # 接下来设置系统时钟 450 update_boot_stage RCclock                # 同样是告诉 update_boot_stage 该事件(执行 /usr/bin/rhgb-client --update="$1" 命令,这里 $1 就是 "RCclock") 451 ARC=0                                                 452 SRM=0 453 UTC=0 454 455 if [ -f /etc/sysconfig/clock ]; then        # 如果存在 /etc/sysconfig/clock 则执行该文件 456    . /etc/sysconfig/clock 457 458    # convert old style clock config to new values 459    if [ "${CLOCKMODE}" = "GMT" ]; then                        # 如果变量 CLOCKMODE 为旧式的 GMT 格式 460       UTC=true                                                                # 则 UTC 变量的值为 ture  461    elif [ "${CLOCKMODE}" = "ARC" ]; then                     # 如果 CLOCKMODE 的值是 ARC ,则 462       ARC=true                                                                # ARC 的值为 true 463    fi                                                                         # 如果 CLOCKMODE 不等于 GMT 或者 UTC ,则 UTC 的值等于 /etc/sysconfig/clock 中的值,一般都是 false 464 fi                                                                            # 如果 CLOCKMODE 不等于 GMT 后者 ARC ,则 UTC 的值为 0 465 466 CLOCKDEF=""                                                            # CLOCKDEF 变量的值默认为空 467 CLOCKFLAGS="$CLOCKFLAGS --hctosys"                       # 而 CLOCKFLAGS 变量的值为原来的值(可能为空)加上 '--hctosys' ,表示把硬件时钟写入内核时钟 468 469 case "$UTC" in                                                          # 根据 UTC 变量的值进行选择                                              470     yes|true) CLOCKFLAGS="$CLOCKFLAGS --utc"             # 如果 UTC 的值为 yes 或者 true,则变量 CLOCKFLAGS 的值加上 --utc ,表示采用 UTC 时区 471   CLOCKDEF="$CLOCKDEF (utc)" ;;                                     # 同时变量 CLOCKDEF 的值加上 "(utc)" 472     no|false) CLOCKFLAGS="$CLOCKFLAGS --localtime"     # 如果变量 UTC 的值为 false 或者 no,则 473   CLOCKDEF="$CLOCKDEF (localtime)" ;;                        # CLOCKDEF 的值加上 "(localtime)" 。由于安装 OS时没有选择 UTC,CLOCKDEF 的值一般最后就是 (localtime) 而已 474 esac 475 case "$ARC" in                                                          # 根据 ARC 变量的值来选择               476     yes|true) CLOCKFLAGS="$CLOCKFLAGS --arc"            # 如果是 yes 或者 true ,则 CLOCKFLAGS 的值加上 --arc ,CLOCKDEF 的值加上 '(arc)' 477   CLOCKDEF="$CLOCKDEF (arc)" ;;                                # 如果 ARC 的值为 0 ,则 CLOCKFLAGS 和 CLOCKDEF 的值都不变 478 esac 479 case "$SRM" in                                                         # 如果 SRM 的值是 yes 或者 true ,则 CLOCKFLAGS 的值加上 "--srm" ,CLOCKDEF 加上 "(srm)" 480     yes|true) CLOCKFLAGS="$CLOCKFLAGS --srm" 481   CLOCKDEF="$CLOCKDEF (srm)" ;; 482 esac 483 484 /sbin/hwclock $CLOCKFLAGS                    # 执行 hwclock $CLOCKFLAGS 命令,一般就是 /sbin/hwclock --hctosys 485 486 action $"Setting clock $CLOCKDEF: `date`" date        # 并输出 "setting clock " 和 $CLOCKDEF ,并执行 date 输出当前时间,然后输出 [ OK ] 487 488 ########################################################################################################################################################  489 490 # 注释 :下面部分是设置 key map   491 if [ "$CONSOLETYPE" = "vt" -a -x /bin/loadkeys ]; then            # 接下来是设置 keymap ,一般都是 us 492  KEYTABLE=                                                                        #  设置 KEYTABLE 和 KEYMAP 493  KEYMAP= 494  if [ -f /etc/sysconfig/console/default.kmap ]; then                # 假如存在 /etc/sysconfig/console/default.kmap ,则 495   KEYMAP=/etc/sysconfig/console/default.kmap                            # KEYMAP 变量的值为 /etc/sysconfig/console/default.kmap 496  else                                                                                    # 否则 497   if [ -f /etc/sysconfig/keyboard ]; then                                        # 如果存在 /etc/sysconfig/keyboard 文件,则执行它 498     . /etc/sysconfig/keyboard                                                       # 该文件设置 KEYTABLE 变量的值,例如 KEYTABLE="/usr/lib/kbd/keytables/us.map   fi 499   if [ -n "$KEYTABLE" -a -d "/lib/kbd/keymaps" ]; then              # 如果 KEYTABLE 的值不为空,且存在 /lib/kbd/keymaps/ 目录,则 500      KEYMAP="$KEYTABLE.map"                                                # KEYMAP 的值为 KEYTABLE 的值加上 ".map" 501   fi 502  fi 503  if [ -n "$KEYMAP" ]; then                                                                 # 假如 KEYMAP 变量的值不为空(间接表示 KEYTABLE 不为空且存在 keymaps 目录) 504   # Since this takes in/output from stdin/out, we can't use initlog 505   if [ -n "$KEYTABLE" ]; then                                                                    # 且 KEYTABLE 的值不为空 506     echo -n $"Loading default keymap ($KEYTABLE): "                                     # 则输出 "Loading default keymap xxxx" 507   else 508     echo -n $"Loading default keymap: "                                                    # 否则只输出 Loading default keymap 509   fi     510   loadkeys $KEYMAP < /dev/tty0 > /dev/tty0 2>/dev/null && \            # 接下来用 loadkeys 加载 $KEYMAP 指定的键盘映射文件。 511      success $"Loading default keymap" || failure $"Loading default keymap"        # 如果成功则调用 success 函数,否则调用 failure 函数 512   echo 513  fi 514 fi 515 ######################################################################################################################################################## 516 517 518 519 520 521 # 注释 :下面部分是设置主机名  522 # Set the hostname.                                # 接下来是设置主机名 523 update_boot_stage RChostname                # 告诉 update_boot_stage 函数该事件,以执行 /usr/sbin/rhgb-client --update RChostname 命令 524 action $"Setting hostname ${HOSTNAME}: " hostname ${HOSTNAME}        # 打印 "setting hostname xxxx" 字符串,并执行 hostname ${HOSTNAME}设置主机名 525 526                                                                  #  注意,HOSTNAME 变量前面已经有过赋值的了,就是 `/bin/hostname` 命令返回的值 527 528 529 ######################################################################################################################################################## 530 531 532 # 注释 :下面设置 ACPI 部分 533 534 # Initialiaze ACPI bits 535 if [ -d /proc/acpi ]; then                                                                    # 如果存在 /proc/acpi 目录,则 536    for module in /lib/modules/$unamer/kernel/drivers/acpi/* ; do            # 对于在 /lib/modules/<kernel-version>/kernel/drivers/acpi/ 目录下的所有模块文件, 537       insmod $module >/dev/null 2>&1                                                        # 都用 insmod 命令加载到内核中 538    done 539 fi 540 541 ######################################################################################################################################################## 542 543 544 # 注释 :下面是主要的部分,就是确认是否需要对 / 文件系统进行 fsck   545 546 if [ -f /fastboot ] || strstr "$cmdline" fastboot ; then      # 接下来是看对 / 系统进行 fsck 的时候了。如果不存在 /fastboot 文件则看 cmdline 变量是否含有 fastboot 字符串 547  fastboot=yes                                                              # 如果有,则 fastboot 变量的值为 yes。/fastboot 是由 shutdown -f 创建的,表示重启时不作 fsck 548 fi 549 550 if [ -f /fsckoptions ]; then                                            # 如果存在 /fsckoptions 文件,则把文件的内容赋予变量 fsckoptions 变量 551  fsckoptions=`cat /fsckoptions` 552 fi 553 554 if [ -f /forcefsck ] || strstr "$cmdline" forcefsck ; then        # 如果不存在 /forcefsck 文件,则检查 cmdline 变量是否含有 forcefsck 字符串,如果有 555  fsckoptions="-f $fsckoptions"                                            # 则在 fsckoptions 的值前面加上 "-f" 。/forcefsck 是由 shutdown -F 创建的,强制 fsck 556 557 elif [ -f /.autofsck ]; then                                                 # 如果存在 /.autofsck 558        559 if [ -x /usr/bin/rhgb-client ] && /usr/bin/rhgb-client --ping ; then        #  且文件 /usr/bin/rhgb-clinet 可执行,且 /usr/bin/rhgb 服务在运行(--pnig),则 560            chvt 1                                                                                                #  切换到虚拟控制台 #1 (主要是显示 fsck 的信息用) 561        fi 562      563    echo $"Your system appears to have shut down uncleanly"                            # 并显示需要 fsck 的信息 “You system appears to have shut down uncleanly” 564        AUTOFSCK_TIMEOUT=5                                                                              # 设置超时时间为5秒 565        566 [ -f /etc/sysconfig/autofsck ] && . /etc/sysconfig/autofsck                           # 如果存在 /etc/sysconfig/autofsck 则执行它 567      568   if [ "$AUTOFSCK_DEF_CHECK" = "yes" ]; then                                                 # 如果执行该文件后 AUTOFSCK_DEF_CHECK 变量的值为 yes ,则 569           AUTOFSCK_OPT=-f                                                                                        # 变量 AUTOFSCK_OPT 的值为 "-f" 570       fi 571 572       if [ "$PROMPT" != "no" ]; then                                                                // 如果 PROMPT 的值不为 no ,则 573 574         if [ "$AUTOFSCK_DEF_CHECK" = "yes" ]; then                                                // 且 AUTOFSCK_DEF_CHECK 的值为 yes 575 576            if /sbin/getkey -c $AUTOFSCK_TIMEOUT -m $"Press N within %d seconds to not force file system integrity check..." n ; then    //  执行 getkey 命令,超时5秒,并 577                                                                                                                                                                                        // 提示5秒内按下 n 键可跳过 fsck 578               AUTOFSCK_OPT=        // 如果用户按下 n ,则 AUTOFSCK_OPT 的值为空,表示取消自动 fsck 579            fi 580         else                    // 如果 AUTOFSCK_DEF_CHECK 的值不为 yes ,则提示5秒内按y 可以强制 fsck 581           if /sbin/getkey -c $AUTOFSCK_TIMEOUT -m $"Press Y within %d seconds to force file system integrity check..." y ; then        // 同样是用 getkey 捕捉 y 键 582               AUTOFSCK_OPT=-f        // 如果用户按下了 y 键,则 AUTOFSCK_OPT 的值为 "-f" 583           fi 584        fi 585        echo 586       else         // 如果 PROMPT 的值为 "no", 这是用户无法选择是否 fsck  587         # PROMPT not allowed 588         if [ "$AUTOFSCK_DEF_CHECK" = "yes" ]; then                                                # 取决于 AUTOFSCK_DEF_CHECK 变量的值,如果是 yes ,则 589           echo $"Forcing file system integrity check due to default setting"     # 提示由于默认的设置强制 fsck 。可能是 mount 次数达到限制,或者多长时间没有 fsck 了 590         else                                             591           echo $"Not forcing file system integrity check due to default setting"            # 如果 AUTOFSCK_DEF_CHECK 的值为 no ,则表示不做 fsck  592         fi 593       fi 594 595       fsckoptions="$AUTOFSCK_OPT $fsckoptions" 596 597 598 fi 599 600 # 注释 :注意!到这里为止并没有执行 fsck 操作,只是判断是否需要执行 fsck 以及 fsck 命令的选项 601 602 if [ "$BOOTUP" = "color" ]; then       # 如果 BOOTUP 的值为 color ,则 603  fsckoptions="-C $fsckoptions"            # -C 表示显示 fsck 进度信息 604 else                                              # 否则 605  fsckoptions="-V $fsckoptions"            # -V 表示显示 verbose 信息 606 fi 607 608 if [ -f /etc/sysconfig/readonly-root ]; then            # 如果存在 /etc/sysconfig/readonly-root ,则 609     . /etc/sysconfig/readonly-root                            # 执行该文件 610 611     if [ "$READONLY" = "yes" ]; then                            # 如果 READONLY 变量的值为 yes ,则 612         # Call rc.readonly to set up magic stuff needed for readonly root        # 执行 /etc/rc.readonly 脚本 613         . /etc/rc.readonly 614     fi 615 fi 616 ######################################################################################################################################################### 617 618 # 注释 :下面开始判断 / 文件系统的类型(是本地还是 nfs 格式)。如果是nfs则不执行 fsck ,否则继续 619 _RUN_QUOTACHECK=0                                            # 初始化 RUN_QUOTACHECK 的值为0.这里是作一个标记,因为后面的代码可能会导致重启。在这里做好标记 620                                                                             # 如果后面没有重启,就可以把 _RUN_QUOTACHECK 设置为1 621 ROOTFSTYPE=`awk '/ \/ / && ($3 !~ /rootfs/) { print $3 }' /proc/mounts`         622 # 从 /proc/mounts 中找出 / 文件系统的类型,并赋予变量 ROOTFSTYPE 623 624 # 注释 :下面用到 -z "$fastboot" ,如果有 /fastboot ,则 fastboot 的值为 yes, 所以就不合 if 的条件,则跳过 fsck 。这就是 shutdown -f 快速启动的效果 625 626 if [ -z "$fastboot" -a "$READONLY" != "yes" -a "X$ROOTFSTYPE" != "Xnfs" -a "X$ROOTFSTYPE" != "Xnfs4" ]; then     # 如果fastboot 变量的值为空且  READONLY 变量不为 yes 627                                                                             # 且 / 文件系统的类型不是 nfs 或者 nfs4 ,则  628 629         STRING=$"Checking root filesystem"    # 初始化 string 变量并输出 "checking root filesystem"  630         echo $STRING 631 632         rootdev=`awk '/ \/ / && ($3 !~ /rootfs/) {print $1}' /proc/mounts`        # 从 /proc/mounts 中找出 / 文件系统所在的设备,并赋予 rootdev 变量(例如 /dev/hdb2) 633          if [ -b /initrd/"$rootdev" ] ; then        # 如果 /initrd/$rootdev 是一个 block 设备 634               rootdev=/initrd/"$rootdev"                    # 则 rootdev 就是 /initrd/rootdev  635          else                                                 # 否则 rootdev 就是 / ,正常情况应该是执行该步的,也就是 rootdev 最终为 / 636          rootdev=/                                       # rootdev 的值为 / ,因为 fsck 支持用 LABEL、mount point、device name 来指定要检查的文件系统  637 638         # 注释 : 下面开始真正的 fsck 操作 639 640 641 642 643 644 645 646          if [ "${RHGB_STARTED}" != "0" -a -w /etc/rhgb/temp/rhgb-console ]; then        # 如果 RHGB_STARTED 不为0且 /etc/rhgb/tmp/rhgb-console 文件可写,则 647               fsck -T -a $rootdev $fsckoptions > /etc/rhgb/temp/rhgb-console           # 执行 fsck 命令,-T 表示不打印标题栏,-a 表示自动修复错误,设备是 / ,后面是选项 648 649 650 651 652 653                                                                                                                       # 且信息写入 /etc/rhgb/temp/rhgb-console 654          else                                                                                                            655 # 否则 656 657               initlog -c "fsck -T -a $rootdev $fsckoptions"                                                         658 # 调用 initlog 执行 659 fsck ,信息直接输出到屏幕,fsck 命令本身都是一样的。 660 661         fi                                                                                                                      662 663         rc=$?                                     664 # 把 fsck 的结果送给变量 rc 665 666 667 668 669 670         if [ "$rc" -eq "0" ]; then         # 如果 rc的值为0,表示 fsck 成功通过 671               success "$STRING"                    # 则调用 success 打印 "checking root fileysyes      [OK]" 672           echo 673         elif [ "$rc" -eq "1" ]; then        # 如果 rc 为1 ,则打印 passed ,表示有错误但修复 674              passed "$STRING"                # 这时调用的是 passed 函数(由 /etc/rc.d/init.d/functions 脚本定义,输出 "checking root filesystems     [ PASSED ]") 675              echo 676          elif [ "$rc" -eq "2" -o "$rc" -eq "3" ]; then         # 如果 rc 为 2 (表示系统应该重启)或者为 3(为 1+2 ,表示系统错误已修复,但需要重启) 677               echo $"Unmounting file systems"                        # 提示卸载 / 文件系统 678               umount -a                                                        # 把所有卸载,当然 / 除外 679               mount -n -o remount,ro /                                  # 把 / 设备已 ro 模式重新 mount 680               echo $"Automatic reboot in progress."                # 然后提示将要自动重启了 681               reboot -f                                                         # 在这里执行 reboot -f ,强制重启 682           fi     # 这个 fi 是结束 "[ "$rc" -eq "0" ]; " 的 683   684           # A return of 4 or higher means there were serious problems.    # 如果 fsck 返回的值大于4(不含4,4表示错误未修复),则表示 / 文件系统出现重大错误,无法继续 685          if [ $rc -gt 1 ]; then    # 这里之所以用 -gt 1 ,是因为如果前面返回2或者3就会自动重启了,如果执行到这里说明 rc 的值必须至少大于等于4 686              if [ -x /usr/bin/rhgb-client ] && /usr/bin/rhgb-client --ping ; then    # 如果 rhgb-client 可执行且 rhgb 服务在运行 687                   chvt 1                 # 强制切换到 1# 虚拟控制台 688              fi 689 690 691 692 693 694   695 696 697 698 699 700             failure "$STRING"        # 调用 failure 函数,打印 "checking root filesystem     [ FAILURE ]" 701             echo 702             echo 703             echo $"*** An error occurred during the file system check."        # 提示 fsck 过程出错 704             echo $"*** Dropping you to a shell; the system will reboot"         # 提示将进入紧急模式的 shell  705             echo $"*** when you leave the shell."                                       # 当你退出该 shell 时会自动重启 706 707 708 709 710 711   712 713 714 715 716 717             str=$"(Repair filesystem)"        # 设置紧急模式下的 shell 提示符 718             PS1="$str \# # "; export PS1     #  设置提示符变量 PS1 为 "(Repair filesystem) <N> # " ,<N> 表示当前是第几个命令 719             [ "$SELINUX" = "1" ] && disable_selinux 720             sulogin                                    # 自动执行 sulogin ,这不是 su ,而是 single-user login 的意思,自动进入单用户模式的 shell 721 722 723 724 725 726          727 728 729 730 731 732                                733 # 注意这里将进入一个交互式的 shell 。只有你执行 exit 命令,才会执行下面的代码,否则下面的代码根本不会被执行 734 735 736 737 738 739   740 741 742 743 744 745             echo $"Unmounting file systems"    # 提示卸载文件系统 746             umount -a                                    # 卸载所有文件系统,/ 除外 747             mount -n -o remount,ro /              # / 以 ro 模式挂载 748             echo $"Automatic reboot in progress."        # 提示将自动重启 749             reboot -f                                     # 立即重启 750 751 752 753 754 755 756          elif [ "$rc" -eq "1" ]; then                     # 如果 rc 的值等于1 ,则表示错误修复完毕 757             _RUN_QUOTACHECK=1                    # 如果上面的 fsck 没有出错,自然就不会重启,所以这里把 _RUN_QUOTACHECK 的值设置为1,表示可以进行 quotacheck 了 758 759 760 761 762 763 764          fi   # 这个 fi 是结束 " [ $rc -gt 1 ]; " 的                             765 766 767 768 769 770 771          if [ -f /.autofsck -a -x /usr/bin/rhgb-client ] && /usr/bin/rhgb-client --ping ; then    #  如果 rhgb-clinet 可运行且 rhgb 服务在运行 772           chvt 8                                                                                                                    # 则切换换 8# 控制台,也就是图形 773          fi 774 fi        # 这个 fi 是结束前面的 ”[ -z "$fastboot" -a "$READONLY" != "yes" -a "X$ROOTFSTYPE" != "Xnfs" -a "X$ROOTFSTYPE" != "Xnfs4" ]; “ 的 775 776 777 778 779 780   781 782 783 784 785 786      787    # 所以如果存在 /fastboot 文件,就直接跳转到这里 788 789 790 791 792 793   794 795 796 797 798 799 ######################################################################################################################################################## 800 # 注释 :在 initrd 的 /linuxrc 或者 /init 脚本中会把初始/文件系统卸载掉,如果没有卸载完全,则在这里会重新做一次 801 802 803 804 805 806   807 808 809 810 811 812 # Unmount the initrd, if necessary                    # 接下来是卸载 initrd 初始/ 文件系统,一般 /init 都会在结尾 umount /initrd/dev 的  813 if LC_ALL=C fgrep -q /initrd /proc/mounts && ! LC_ALL=C fgrep -q /initrd/loopfs /proc/mounts ; then    # 如果 /proc/mounts 文件还有 /initrd/proc 条目, 814 815 816 817 818 819                                                                                                                                                       # 且不存在 /initrd/loops 条目,则 820    if [ -e /initrd/dev/.devfsd ]; then                                                                                                     # 如果存在 /initrd/dev/.devfsd 文件,则        821       umount /initrd/dev                                                                                                                            # 卸载 /initrd/dev 目录 822    fi 823    umount /initrd                                            # 最后把整个 /initrd 卸载 824    /sbin/blockdev --flushbufs /dev/ram0 >/dev/null 2>&1    # 最后用 blockdev --flushbs 命令清除 /dev/ram0 的内容,该社备就是被挂载为初始/的 825 fi 826 ########################################################################################################################################################                                                                                # 注释 :下面是对 / 进行 quota 检查,其他文件系统暂时不执行 quotacheck 827 828 829 830 831 832 # Possibly update quotas if fsck was run on /.                    # 如果 fsck 已经对 / 进行了检查,则执行 quotacheck 更新 quota 情况 833 LC_ALL=C grep -E '[[:space:]]+/[[:space:]]+' /etc/fstab | \        # 在 /etc/fstab 中找出 / 文件系统所在的行,并打印第4个字段(属性) 834     awk '{ print $4 }' | \                                                           # 这是属性字段 835     LC_ALL=C fgrep -q quota                                                    # 找出是否有 quota 字符串,不管是 usrquota 还是 grpquota 836 _ROOT_HAS_QUOTA=$?                                                    # 把结果赋予 _ROOT_HAS_QUOTA 变量 837 838 if [ "X$_RUN_QUOTACHECK" = "X1" -a \                              839 #  如果 x$_RUN_QUOTACHECK 返回 X1 ,且 840     "X$_ROOT_HAS_QUOTA" = "X0" -a \                                #   X$_ROOT_HAS_QUOTA 返回 X0 ,则表示当前可以执行 quotacheck ,且 / 也启用了 quota  841     -x /sbin/quotacheck ]; then                                        #  如果存在 quotacheck 命令    842  if [ -x /sbin/convertquota ]; then                                     843 # 如果存在 convertquota 命令 844 845      if [ -f /quota.user ]; then                                                 846 # 且存在 /quota.user 则 847 848           action $"Converting old user quota files: " \                          849 # 并 850 调用 action 函数,打印提示信息,用 851 convertquota 转换成 v2 格式的 aquota.user 文件 852 853           /sbin/convertquota -u / && rm -f /quota.user                854  # 然后删除 v1格式的 /quota.user 855 856      fi 857 858      if [ -f /quota.group ]; then                                             859 # 同样对 /quota.group 转换成 v2 格式的 aquota.group,并删除 /quota.group 文件 860           action $"Converting old group quota files: " \ 861 862           /sbin/convertquota -g / && rm -f /quota.group             863 # 同样在转换后删除旧的 v1 的 group quota 文件 864 865      fi 866 867  fi 868 869  action $"Checking root filesystem quotas: " /sbin/quotacheck -nug /         870 # 然后执行 quotacheck -nug / 对 / 文件系统进行检查,并打印提示信息 871 fi    872  # 这个 fi 是结束 "[ "X$_RUN_QUOTACHECK" = "X1" -a "X$_ROOT_HAS_QUOTA" = "X0" -a -x /sbin/quotacheck ]; " 的 873 874 875 876 877 878   879 880 881 882 883 884 ######################################################################################################################################################## 885 886 887 888 889 890 # 注释 :下面这个部分是设置 ISA 设备的,不过由于现在基本没有 ISA 设备了,所以可以跳过该部分,甚至可以在内核中指定不支持 ISA 891 892 893 894 895 896 if [ -x /sbin/isapnp -a -f /etc/isapnp.conf -a ! -f /proc/isapnp ]; then         897     # check for arguments passed from kernel 898     if ! strstr "$cmdline" nopnp ; then 899  PNP=yes 900     fi 901     if [ -n "$PNP" ]; then 902  action $"Setting up ISA PNP devices: " /sbin/isapnp /etc/isapnp.conf 903     else 904  action $"Skipping ISA PNP configuration at users request: " /bin/true 905     fi 906 907 fi 908 909 910 911 912 913 ########################################################################################################################################################  914 915 916 917 918 919 # Remount the root filesystem read-write.                                    # 现在 / 文件系统 fsck 过了,可以按照 read-write 的模式挂载了 920 update_boot_stage RCmountfs                                                      # 告诉 rhgb 服务器更新 RCmountfs 服务的状态 921 state=`awk '/ \/ / && ($3 !~ /rootfs/) { print $4 }' /proc/mounts`    # 从 /proc/mounts 中找出 ' / ' 字符串并且第3个字段不等于 'rootfs',则打印其第4个字段,赋予 state 922 [ "$state" != "rw" -a "$READONLY" != "yes" ] && \                              # 如果 state 变量的值不为 'rw' 且 READONLY 变量的值为 yes ,则   923   action $"Remounting root filesystem in read-write mode: " mount -n -o remount,rw /        # 用 -o remount -o rw 重新挂载 / 为 rw 模式,并打印提示信息 924 925 926 927 928 929 ########################################################################################################################################################  930 931 932 933 934 935 # 注释 :下面开始是 LVM2 的部分了 936 937 938 939 940 941 # LVM2 initialization                                                                                        # 下面部分是 LVM2  的初始化部分 942 if [ -x /sbin/lvm.static ]; then                                                                          # 如果存在 /sbin/lvm.static 且可执行 943     if ! LC_ALL=C fgrep -q "device-mapper" /proc/devices 2>/dev/null ; then        # 如果 /proc/devices 文件不含有 device-mapper ,则 944          modprobe dm-mod >/dev/null 2>&1                                                                        # 调用 modprobe 加载 dm-mod 945     fi 946     echo "mkdmnod" | /sbin/nash --quiet >/dev/null 2>&1                                    # 并调用 nash 执行 mkdmmod ,不过是以 quiet 模式执行的 947     [ -n "$SELINUX" ] && restorecon /dev/mapper/control >/dev/null 2>&1 948     if [ -c /dev/mapper/control -a -x /sbin/lvm.static ]; then                                # 假如存在 /dev/mapper/control 这个字符设备且 /sbin/lvm.static 可执行,则 949          if /sbin/lvm.static vgscan --mknodes --ignorelockingfailure > /dev/null 2>&1 ; then        # 调用 lvm.static 执行 vgscan 扫描所有卷组(忽略锁错误) 950              action $"Setting up Logical Volume Management:" /sbin/lvm.static vgchange -a y --ignorelockingfailure        # 如果扫描到卷组,则调用 action 函数, 951          fi                                                                                                                                                      # 打印提示信息,并执行 vgchange -ay 激活全部卷组 952     fi 953 fi 954 955 956 957 958 959 # LVM initialization                 # 这是 LVM1 的部分,因为系统可能同时存在 lVM1 和 lvm2 的 pv 960 if [ -f /etc/lvmtab ]; then        # 如果存在 /etc/lvmtab 文件 961     [ -e /proc/lvm ] || modprobe lvm-mod > /dev/null 2>&1    # 且 /proc/lvm 文件存在,如果没有则调用 modprobe lvm-mod 加载 lvm-mod ,注意模块名的不同 962         if [ -e /proc/lvm -a -x /sbin/vgchange ]; then                # 如果现在存在 /proc/lvm 文件且 /sbin/vgchange 可执行 963              action $"Setting up Logical Volume Management:" /sbin/vgscan && /sbin/vgchange -a y    # 则调用 action 打印提示信息,并执行 vgchange -ay 激活它们 964         fi 965 fi 966 967 968 969 970 971   972 973 974 975 976 977 978 979 980 ########################################################################################################################################################  981 982 983 984 985 986 987 988 # Clean up SELinux labels 989 if [ -n "$SELINUX" ]; then 990    for file in /etc/mtab /etc/ld.so.cache ; do 991     [ -r $file ] && restorecon $file  >/dev/null 2>&1 992    done 993 fi 994 995 996 997 998 999 ########################################################################################################################################################  1000 1001 1002 1003 1004 1005 # Clear mtab                                                            # 由于之前的 /etc/mtab 并不准确,所以现在把它的内容清掉 1006 (> /etc/mtab) &> /dev/null                                              # 用 >/etc/mtab 清空其内容   1007 1008 1009 1010 1011 1012   1013 1014 1015 1016 1017 1018 # Remove stale backups 1019 rm -f /etc/mtab~ /etc/mtab~~                                    # 删除 /etc/mtab 的备份文件 1020 1021 1022 1023 1024 1025   1026 1027 1028 1029 1030 1031 # Enter root, /proc and (potentially) /proc/bus/usb and devfs into mtab.        # 把 root ,/proc ,/proc/bus/usb,devpts 加入到 /etc/mtab 中 1032 mount -f /                                                                    #  -f 表示只更新 /etc/mtab ,但不实际mount,因为这些文件系统在之前都挂载了,没有必要再挂载一次 1033 mount -f /proc 1034 mount -f /sys >/dev/null 2>&1 1035 mount -f /dev/pts 1036 [ -f /proc/bus/usb/devices ] && mount -f -t usbfs usbfs /proc/bus/usb  # 如果存在 /proc/bus/usb/devices 文件,则用 mount -f -t usbfs 挂载到 /proc/bus/usb 下       1037 [ -e /dev/.devfsd ] && mount -f -t devfs devfs /dev         # 如果存在 /dev/.devfsd ,则同样挂载 devfs 到 /dev 下 1038 1039 1040 1041 1042 1043 ########################################################################################################################################################  1044 1045 1046 1047 1048 1049 # configure all zfcp (scsi over fibrechannel) devices before trying to mount them 1050 # zfcpconf.sh exists only on mainframe 1051 [ -x /sbin/zfcpconf.sh ] && /sbin/zfcpconf.sh 1052 1053 1054 1055 1056 1057 ########################################################################################################################################################  1058 1059 1060 1061 1062 1063 # The root filesystem is now read-write, so we can now log        # 由于之前的 / 是只读的,所以通过 initlog 来记录信息,现在可以通过 syslog 了 1064 # via syslog() directly.. 1065 if [ -n "$IN_INITLOG" ]; then 1066     IN_INITLOG=                                                                            # 如果 IN_INITLOG 的值不为空则清空它 1067 fi 1068 1069 1070 1071 1072 1073   1074 1075 1076 1077 1078 1079 if ! strstr "$cmdline" nomodules && [ -f /proc/modules ] ; then        # 如果内核启动参数含有 "nomodules" ,且存在 /proc/modules 文件,则 1080     USEMODULES=y                                                                            # 把 USEMODULES 设置为 y 1081 fi 1082 1083 1084 1085 1086 1087   1088 1089 1090 1091 1092 1093 # Load modules (for backward compatibility with VARs)                 1094 if [ -f /etc/rc.modules ]; then 1095  /etc/rc.modules 1096 fi 1097 1098 1099 1100 1101 1102   1103 1104 1105 1106 1107 1108   1109 1110 1111 1112 1113 1114 ########################################################################################################################################################  1115 1116 1117 1118 1119 1120 update_boot_stage RCraid                                        # 下面部分是激活 RAID 的 1121 if [ -f /etc/mdadm.conf ]; then                                # 如果存在 /etc/mdadm.conf 则 1122     /sbin/mdadm -A -s                                                # mdadm -A 表示 Assemble 模式,-s 则表示搜索 /etc/mdadm.conf 1123 fi 1124 1125 1126 1127 1128 1129   1130 1131 1132 1133 1134 1135 # 注释 :下面解决旧式的用 raid-tools 建立的 software-raid 1136 1137 1138 1139 1140 1141   1142 1143 1144 1145 1146 1147 if [ -f /etc/raidtab ]; then                                        # 如果存在旧式的 raidtools 的 /etc/raidtab 则 1148     # Add raid devices 1149     [ -f /proc/mdstat ] || modprobe md >/dev/null 2>&1        # 如果不存在 /proc/mdstat 文件,则用 modprobe md 先加载 md 模块 1150 1151 1152 1153 1154 1155     if [ -f /proc/mdstat ]; then 1156          echo -n $"Starting up RAID devices: "                             # 并输出 "Starting up RAID devices:" 1157 1158 1159 1160 1161 1162          rc=0                                                                           # 先把 rc 的值设置为0,如果有某个 raid 激活失败,则 rc 为 1 1163 1164 1165 1166 1167 1168                                                                                           # rc  和下面的 RESULT 不同,RESULT 是每个 raid 的激活状态,而 rc 是全局的激活状态 1169          for i in `awk '{if ($1=="raiddev") print $2}' /etc/raidtab`     # 用 awk 从 /etc/raidtab 中找出所有 raiddev 行打印第2个字段也就是 raid 的设备名 1170 1171 1172 1173 1174 1175          do                                                                                    # 针对每个 Software-raid 执行下面的代码 1176                 RAIDDEV=`basename $i`                                                # 把每个 raid 设备的设备名(出去前面目录部分)赋予变量 RAIDDEV 1177                 RAIDSTAT=`LC_ALL=C grep "^$RAIDDEV : active" /proc/mdstat`            # 如果 /proc/mdstat 中表明该 RAID 已经是 active 的状态 1178                 if [ -z "$RAIDSTAT" ]; then                                                                # 如果状态为空,表明该 RAID 并没有激活 1179                     # First scan the /etc/fstab for the "noauto"-flag 1180                     # for this device. If found, skip the initialization 1181                     # for it to avoid dropping to a shell on errors. 1182                     # If not, try raidstart...if that fails then 1183                     # fall back to raidadd, raidrun.  If that 1184                     # also fails, then we drop to a shell 1185                     RESULT=1                                                                                    # 先把 RESULT 设置为 1,表示 false 1186                     INFSTAB=`LC_ALL=C grep -c "^$i" /etc/fstab`                                 # 然后检查 /etc/fstab 中是否有以指定的 md 设备开头的行,结果赋予 INFSTAB 1187                     if [ $INFSTAB -eq 0 ] ; then                                                           # 如果 INFSTAB 为0,表示没有找到,也就是不希望自动我你挂载该 raid 设备 1188                            RESULT=0                                                                                # 则把 RESULT 设置为0 1189                            RAIDDEV="$RAIDDEV(skipped)"                                                    # 并在 RAIDDEV 后面加上 (skipped) ,表示该设备跳过不激活它 1190                     fi 1191                     NOAUTO=`LC_ALL=C grep "^$i" /etc/fstab | LC_ALL=C fgrep -c "noauto"`    # 如果该设备在 /etc/fstab 中但它的属性含有 noauto 1192                     if [ $NOAUTO -gt 0 ]; then                                                                            # 则和上面不在 /etc/fstab 一样处理 1193                            RESULT=0 1194                            RAIDDEV="$RAIDDEV(skipped)" 1195                     fi 1196                     if [ $RESULT -gt 0 -a -x /sbin/mdadm ]; then                                            # 如果 /sbin/mdadm 文件可执行,且尝试用 mdadm 来激活它们 1197                             /sbin/mdadm -Ac partitions $i -m dev                                                    # mdadm 将从 /proc/partitions 文件读取并状态指定 raid($i) ,-m 表示 minor 1198 1199 1200 1201 1202 1203                                                                                                                                       # number 就等于它刚才装配的 raid 设备名的数字部分 1204                             RESULT=$?                                                                                           # 并把 mdadm 的结果赋予 RESULT 变量 1205                     fi 1206                     if [ $RESULT -gt 0 -a -x /sbin/raidstart ]; then                                            # 如果 RESULT 大于0,表示 madm 命令失败,则尝试用 /sbin/raidstart 来 1207                         /sbin/raidstart $i 1208                         RESULT=$?                                                                                     1209                     fi 1210                     if [ $RESULT -gt 0 -a -x /sbin/raid0run ]; then                                             # 如果 raidstart 还是失败,则尝试用 raid0run 来 1211                         /sbin/raid0run $i 1212                         RESULT=$? 1213                     fi 1214                     if [ $RESULT -gt 0 -a -x /sbin/raidadd -a -x /sbin/raidrun ]; then                  # 如果 raid0run 失败则尝试用 raidadd 然后用 raidrun 1215                         /sbin/raidadd $i 1216                         /sbin/raidrun $i 1217                         RESULT=$? 1218                     fi 1219                     if [ $RESULT -gt 0 ]; then                                                                         # 如果还是失败,则 rc 的值最终为1 1220                         rc=1 1221                    fi 1222                     echo -n "$RAIDDEV "                                                                                # 输出当前操作的 raid 设备名 1223                 else            # 这个 else 是对应 ”if [ -z "$RAIDSTAT" ]; “的,因为可能内核集成了 raid support ,自动激活 raid 1224                        echo -n "$RAIDDEV "                                                                             # 如果 RAID 的状态本来就是 active ,则直接输出 raid 的名称 1225                 fi 1226          done 1227  echo 1228 1229 1230 1231 1232 1233   1234 1235 1236 1237 1238 1239  # A non-zero return means there were problems.                    # 如果只要有一个 raid 激活失败,则 rc 的值就为1 1240   1241 if [ $rc -gt 0 ]; then                                                                # 如果 rc 的值大于0,则表示有 raid 激活失败 1242          if [ -x /usr/bin/rhgb-client ] && /usr/bin/rhgb-client --ping ; then    # 则按照前面 fsck 失败的情况,进入紧急模式 1243       chvt 1 1244   fi 1245   echo 1246   echo 1247   echo $"*** An error occurred during the RAID startup" 1248   echo $"*** Dropping you to a shell; the system will reboot" 1249   echo $"*** when you leave the shell." 1250 1251 1252 1253 1254 1255   1256 1257 1258 1259 1260 1261   str=$"(RAID Repair)"                                                                            # 只不过提示符有所不同而已,变成了 (RAID Repair) <N> # 1262   PS1="$str \# # "; export PS1 1263   [ "$SELINUX" = "1" ] && disable_selinux 1264   sulogin 1265 1266 1267 1268 1269 1270   1271 1272 1273 1274 1275 1276   echo $"Unmounting file systems" 1277   umount -a 1278   mount -n -o remount,ro / 1279   echo $"Automatic reboot in progress." 1280   reboot -f 1281 1282 1283 1284 1285 1286  fi        # 注释 ;这个 fi 是结束 "if [ -f /etc/raidtab ];" 的,如果不存在 /etc/raidtab ,则直接跳到这里 1287 1288 1289 1290 1291 1292 ######################################################################################################################################################## 1293  # LVM2 initialization, take 2                                                        # 由于 LVM 的 pv 可能是建立在 RAID 之上的,所以再次尝试扫描 vg 并激活它们 1294  if [ -c /dev/mapper/control -a -x /sbin/lvm.static ]; then             # 步骤和前面的一样 1295   if /sbin/lvm.static vgscan > /dev/null 2>&1 ; then 1296    action $"Setting up Logical Volume Management:" /sbin/lvm.static vgscan --mknodes --ignorelockingfailure && /sbin/lvm.static vgchange -a y --ignorelockingfailure 1297   fi 1298  fi 1299  # LVM initialization, take 2 (it could be on top of RAID) 1300  if [ -e /proc/lvm -a -x /sbin/vgchange -a -f /etc/lvmtab ]; then 1301   action $"Setting up Logical Volume Management:" /sbin/vgscan && /sbin/vgchange -a y 1302  fi 1303     fi 1304 fi 1305 1306 1307 1308 1309 1310 ########################################################################################################################################################  1311 1312 1313 1314 1315 1316 # 注释 :下面对其他文件系统(/ 除外)的文件系统进行 fsck 1317 1318 1319 1320 1321 1322 _RUN_QUOTACHECK=0        # 还是把 _RUN_QUOTACHECK 变量的值设置为0 1323 # Check filesystems            # 检查其他文件系统 1324 if [ -z "$fastboot" ]; then        # 如果不存在 /etc/fastboot ,则执行下面的脚本。可以看到 shutdown -r 不仅影响 / 的 fsck ,也影响其他文件系统的 fsck 1325         STRING=$"Checking filesystems"        # 打印提示信息 1326         echo $STRING 1327          if [ "${RHGB_STARTED}" != "0" -a -w /etc/rhgb/temp/rhgb-console ]; then 1328                   fsck -T -R -A -a $fsckoptions > /etc/rhgb/temp/rhgb-console                # -R 表示跳过 / 文件系统,其他选项和之前的一样 1329          else 1330                   initlog -c "fsck -T -R -A -a $fsckoptions" 1331          fi 1332           1333 rc=$? 1334          if [ "$rc" -eq "0" ]; then                                    #  这部分和之前处理/文件系统的 fsck 结果一样 1335            success "$STRING" 1336            echo 1337         elif [ "$rc" -eq "1" ]; then 1338            passed "$STRING" 1339            echo 1340         elif [ "$rc" -eq "2" -o "$rc" -eq "3" ]; then  1341            echo $"Unmounting file systems" 1342            umount -a 1343            mount -n -o remount,ro / 1344            echo $"Automatic reboot in progress." 1345            reboot -f 1346         fi 1347 1348 1349 1350 1351 1352   1353 1354 1355 1356 1357 1358          # A return of 4 or higher means there were serious problems. 1359          if [ $rc -gt 1 ]; then 1360              if [ -x /usr/bin/rhgb-client ] && /usr/bin/rhgb-client --ping ; then 1361                   chvt 1 1362              fi 1363 1364 1365 1366 1367 1368   1369 1370 1371 1372 1373 1374              failure "$STRING" 1375              echo 1376              echo 1377              echo $"*** An error occurred during the file system check." 1378              echo $"*** Dropping you to a shell; the system will reboot" 1379              echo $"*** when you leave the shell." 1380 1381 1382 1383 1384 1385   1386 1387 1388 1389 1390 1391              str=$"(Repair filesystem)" 1392              PS1="$str \# # "; export PS1 1393              [ "$SELINUX" = "1" ] && disable_selinux 1394              sulogin 1395 1396 1397 1398 1399 1400   1401 1402 1403 1404 1405 1406              echo $"Unmounting file systems" 1407              umount -a 1408              mount -n -o remount,ro / 1409              echo $"Automatic reboot in progress." 1410              reboot -f 1411          elif [ "$rc" -eq "1" -a -x /sbin/quotacheck ]; then 1412              _RUN_QUOTACHECK=1                                        # 如果   fsck 修复成功,则 _RUN_QUOTACHECK 的值修改为1,表示可以进行其他文件系统的 quotacheck 了 1413          fi        #  这个 fi 是结束  "if [ $rc -gt 1 ]; " 的 1414 fi                # 这个 fi 是结束 ”if [ -z "$fastboot" ];“ 的 1415 1416 1417 1418 1419 1420   1421 1422 1423 1424 1425 1426 ########################################################################################################################################################  1427 1428 1429 1430 1431 1432 # Mount all other filesystems (except for NFS and /proc, which is already            # 挂载除了 /,/proc,/proc/bus/usb,devpts 之外的文件系统 1433 # mounted). Contrary to standard usage, 1434 # filesystems are NOT unmounted in single user mode. 1435 action $"Mounting local filesystems: " mount -a -t nonfs,nfs4,smbfs,ncpfs,cifs,gfs -O no_netdev    # 挂载类型为 nonfs、nfs4、smbfs、ncptfs、cifs、gfs 的文件系统 1436 1437 1438 1439 1440 1441                                                                                        1442 # 但条件是这些文件系统对应在 /etc/fstab 中的属性字段没有 netdev 属性 1443 1444 1445 1446 1447 1448 ########################################################################################################################################################   1449 1450 1451 1452 1453 1454 # Start the graphical boot, if necessary and not done yet.                # 现在又再次检查是否可以启动图形启动界面 1455 if strstr "$cmdline" rhgb && [ "$RHGB_STARTED" -eq 0 -a "$BOOTUP" = "color" -a "$GRAPHICAL" = "yes" -a -x /usr/bin/rhgb ]; then 1456    LC_MESSAGES= /usr/bin/rhgb 1457    RHGB_STARTED=1 1458 fi 1459 1460 1461 1462 1463 1464 ########################################################################################################################################################  1465 1466 1467 1468 1469 1470 # check remaining quotas other than root                                                            # 对 / 系统之外的文件系统进行 quota 检查 1471 if [ X"$_RUN_QUOTACHECK" = X1 -a -x /sbin/quotacheck ]; then                            # 方法和之前对 / 进行 quotachec 一样 1472      if [ -x /sbin/convertquota ]; then 1473          # try to convert old quotas 1474          for mountpt in `awk '$4 ~ /quota/{print $2}' /etc/mtab` ; do 1475               if [ -f "$mountpt/quota.user" ]; then 1476                   action $"Converting old user quota files: " \ 1477                   /sbin/convertquota -u $mountpt && \ 1478                    rm -f $mountpt/quota.user 1479               fi 1480               if [ -f "$mountpt/quota.group" ]; then 1481                   action $"Converting old group quota files: " \ 1482                   /sbin/convertquota -g $mountpt && \ 1483                    rm -f $mountpt/quota.group 1484               fi 1485      done 1486  fi 1487 1488 1489 1490 1491 1492 1493  action $"Checking local filesystem quotas: " /sbin/quotacheck -aRnug                # quotachk -augRn 表示对 /etc/fstab 中除了 / 之外,所有启用了 usrquota、grpquota 的  1494 fi                                                                                                                 # 的文件系统都检查     1495 1496 1497 1498 1499 1500   1501 1502 1503 1504 1505 1506 if [ -x /sbin/quotaon ]; then 1507     action $"Enabling local filesystem quotas: " /sbin/quotaon -aug                       # 执行 quotaon 启动 quota 功能 1508 fi 1509 1510 1511 1512 1513 1514 ########################################################################################################################################################  1515 1516 1517 1518 1519 1520 # 1521 # Check to see if SELinux requires a relabel 1522 # 1523 [ -n "$SELINUX" ] && [ -f /.autorelabel ] && relabel_selinux 1524 1525 1526 1527 1528 1529 ########################################################################################################################################################  1530 1531 1532 1533 1534 1535 # Initialize pseudo-random number generator                                                    # 初始化随机数生成器 1536 if [ -f "/var/lib/random-seed" ]; then                                                                # 如果存在 /var/lib/random-seed 文件,则 1537  cat /var/lib/random-seed > /dev/urandom                                                            # 把它的内容送给 /dev/urandom 1538 else                                                                                                                # 否则 1539  touch /var/lib/random-seed                                                                                # 创建该文件 1540 fi 1541 chmod 600 /var/lib/random-seed                                                                     # 修改该文件的权限为 600 (rw-------) 1542 dd if=/dev/urandom of=/var/lib/random-seed count=1 bs=512 2>/dev/null           # 从 /dev/urandom 读入 512 kB 并送给 /var/lib/random-seed 1543 1544 1545 1546 1547 1548   1549 1550 1551 1552 1553 1554 # Use the hardware RNG to seed the entropy pool, if available 1555 [ -x /sbin/rngd -a -f /dev/hw_random ] && rngd                                                # 如果 /sbin/rngd 可执行且存在 /dev/hw_random 文件,则执行 rngd 为加密池生成种子 1556 1557 1558 1559 1560 1561   1562 1563 1564 1565 1566 1567   1568 1569 1570 1571 1572 1573 ########################################################################################################################################################  1574 1575 1576 1577 1578 1579 # Configure machine if necessary.                                                                # 这部分允许你在启动时作一些配置(手工的) 1580 if [ -f /.unconfigured ]; then                                                                        # 如果存在 /.unconfigured 文件 1581     if [ -x /usr/bin/rhgb-client ] && /usr/bin/rhgb-client --ping ; then                    # 且 rhgb-client 可执行,rhgb 服务在运行,则 1582          chvt 1                                                                                                                    # 切换回 1# 控制台 1583     fi 1584 1585 1586 1587 1588 1589   1590 1591 1592 1593 1594 1595     if [ -x /usr/bin/system-config-keyboard ]; then                                               # 如果 /usr/bin/sysconfig-keyboard 可执行 1596          /usr/bin/system-config-keyboard                                                                    # 则执行该命令 1597     fi 1598     if [ -x /usr/bin/passwd ]; then                                                                        # 如果存在 /usr/bin/passwd ,则 1599         /usr/bin/passwd root                                                                                        # 执行 passwd root ,修改 root 密码 1600     fi 1601     if [ -x /usr/sbin/netconfig ]; then                                                                    # 如果存在 /usr/sbin/netconfig ,则 1602          /usr/sbin/netconfig                                                                                            #  执行 /usr/sbin/netconfig ,重新配置网络 1603     fi 1604     if [ -x /usr/sbin/timeconfig ]; then                                                                    # 如果存在 /usr/sbin/timeconfig ,则 1605          /usr/sbin/timeconfig                                                                                            # 执行 /usr/sbin/timeconfig 重新配置时间和时区 1606     fi 1607     if [ -x /usr/sbin/authconfig ]; then                                                                    # 如果存在 /usr/sbin/authconfig ,则 1608          /usr/sbin/authconfig --nostart                                                                                # 执行 /usr/sbin/authconfig --nostart 重新配置 shadow、LDAP 、kerberos 等 1609     fi 1610     if [ -x /usr/sbin/ntsysv ]; then                                                                            # 如果存在 /usr/sbin/ntsysv ,则 1611          /usr/sbin/ntsysv --level 35                                                                                    # 执行 /usr/sbin/ntsysv --level 35 对运行级别3,5下的服务启动进行配置 1612     fi 1613 1614 1615 1616 1617 1618   1619 1620 1621 1622 1623 1624     # Reread in network configuration data.                                                              # 重新读取 /etc/sysconfig/network 文件 1625     if [ -f /etc/sysconfig/network ]; then                                                                  #  如果存在该文件就执行它          1626          . /etc/sysconfig/network 1627 1628 1629 1630 1631 1632   1633 1634 1635 1636 1637 1638          # Reset the hostname. 1639          action $"Resetting hostname ${HOSTNAME}: " hostname ${HOSTNAME}        # 重新设置主机名,因为上面的 /etc/sysconfig/network 被重新执行了 1640     fi 1641 1642 1643 1644 1645 1646   1647 1648 1649 1650 1651 1652     rm -f /.unconfigured                                                                          # 删除 /.unconfigured 1653 1654 1655 1656 1657 1658   1659 1660 1661 1662 1663 1664     if [ -x /usr/bin/rhgb-client ] && /usr/bin/rhgb-client --ping ; then        # 切换回 8# 控制台 1665          chvt 8 1666     fi 1667 fi 1668 1669 1670 1671 1672 1673   1674 1675 1676 1677 1678 1679 # Clean out /.                                                                                        # 下面把 / 下的一些文件删除,包括 /fastboot、/fsckoptions、/forcefsck、/.autofsck 1680 rm -f /fastboot /fsckoptions /forcefsck /.autofsck /halt /poweroff &> /dev/null        # /halt、/poweroff ,这样下次重启就会再次检测是否需要 fsck 了 1681 1682 1683 1684 1685 1686   1687 1688 1689 1690 1691 1692 # Do we need (w|u)tmpx files? We don't set them up, but the sysadmin might...        # 正常情况下是需要 /var/run/utmpx 和 /var/log/wtmpx 文件 1693 _NEED_XFILES=                                                                                                        #  _NEED_XFILES 的值为空 1694 [ -f /var/run/utmpx -o -f /var/log/wtmpx ] && _NEED_XFILES=1                                  # 如果存在其中之1个文件,就把 _NEED_XFILES 的值设置为1 1695 1696 1697 1698 1699 1700 ########################################################################################################################################################  1701 1702 1703 1704 1705 1706 # Clean up /var.  I'd use find, but /usr may not be mounted.            # 现在清理 /var 目录。 1707 for afile in /var/lock/* /var/run/* ; do                                          # 对于在 /var/lock/ 和 /var/run 下的每个文件,执行下面的操作 1708  if [ -d "$afile" ]; then                                                                        # 如果 $afile 是一个目录,则 1709     case "$afile" in                                                                                    # 根据 $afile 的值进行选择 1710   */news|*/mon) ;;                                                                                    # 如果该目录的路径名是以 '/news' 或者 '/mon' 结尾则跳过它们不处理 1711   */sudo)  rm -f $afile/*/* ;;                                                                        # 如果是以 '/sudo' 结尾,则用 rm -rf 把该目录下面的”所有子目录“下的全部东西删除 1712   */vmware) rm -rf $afile/*/* ;;                                                                   # 如果是以 '/vmware' 结尾,则用 rm -fr 把它下面的”所有子目录“下的内容全部删除 1713   */samba) rm -rf $afile/*/* ;;                                                                      # 如果是以 '/samba' 结尾,也是同样操作 1714   *)  rm -f $afile/* ;;                                                                                   # 如果不是上面4种类型,则把该目录下的所有内容都删除,不仅包括子目录,也包括文件 1715     esac 1716  else                                                                                                 # 如果 $afile 是一个文件,不是目录,则 1717     rm -f $afile                                                                                            # 删除该文件 1718  fi 1719 done 1720 rm -f /var/lib/rpm/__db* &> /dev/null                                            # 删除 /var/lib/rpm/_db* 1721 1722 1723 1724 1725 1726   1727 1728 1729 1730 1731 1732 # 补充 :可以看到不要在 /var/run 和 /var/lock 下面放置有用的文件,否则启动时会被删除。 1733 1734 1735 1736 1737 1738   1739 1740 1741 1742 1743 1744 # 正常情况下 /var/run 有如下内容 : 1745 1746 1747 1748 1749 1750   1751 1752 1753 1754 1755 1756 [root@mail run]# ls 1757 acpid.socket=           dbus/           iptraf/         mysqld/     ptal-mlcd/    rpc.statd.pid  syslogd.pid 1758 atd.pid                 dovecot/        klogd.pid       named/      ptal-printd/  saslauthd/     usb/ 1759 console/                dovecot-login/  mailman/        netreport/  pvm3/         sendmail.pid   utmp 1760 crond.pid               gpm.pid         mdadm/          news/       quagga/       sm-client.pid  winbindd/ 1761 cups-config-daemon.pid  haldaemon.pid   mdmpd/          nscd/       radiusd/      sshd.pid       xfs.pid 1762 cupsd.pid               iiim/           messagebus.pid  ppp/        radvd/        sudo/          xinetd.pid 1763 [root@mail run]# 1764 1765 1766 1767 1768 1769   1770 1771 1772 1773 1774 1775 ########################################################################################################################################################  1776 1777 1778 1779 1780 1781 # Reset pam_console permissions                                                                    # 这里重置 pam_console 的权限 1782 [ -x /sbin/pam_console_apply ] && /sbin/pam_console_apply -r                        # 如果 /sbin/pam_console_apply 存在且可以执行,则执行 /sbin/pam_console_apply -r 1783 1784 1785 1786 1787 1788                                                                                                                   # -r 是表示 reset 的意思,具体见 man pam_console_apply 1789 1790 1791 1792 1793 1794 ######################################################################################################################################################## 1795 1796 1797 1798 1799 1800 # 注意下面这段话,一直到后面的 "kill -TERM `/sbin/pidof getkey` >/dev/null 2>&1" 才算结束,这一段放在 {} 中的代码在 bash 中被成为 command block 1801 1802 1803 1804 1805 1806   1807 1808 1809 1810 1811 1812 # 它可以把放在 {} 中的多个命令当成1个命令来执行,这样可以对多个命令一次使用 IO 重定向。 1813 1814 1815 1816 1817 1818   1819 1820 1821 1822 1823 1824 # 实际上,这部分是被放在后台运行的 ,因为它是以  {xxxxx}& 的形式出现的 1825 1826 1827 1828 1829 1830   1831 1832 1833 1834 1835 1836 # 我们可以也可以用函数的形式来把下面的代码做成一个函数,不过 command blocks 是一种简便的方式 1837 1838 1839 1840 1841 1842   1843 1844 1845 1846 1847 1848 {                                                                                                        # command block 开始 1849 # Clean up utmp/wtmp                                                                        # 首先清空 utmp 和 wtmp 文件的内容 1850 > /var/run/utmp                                                                                  # 首先清空 /var/run/utmp 文件 1851 touch /var/log/wtmp                                                                           # 再用 touch 创建 /var/log/wtmp 文件 1852 chgrp utmp /var/run/utmp /var/log/wtmp                                             # 把这两个文件的组都改为 utmp 组 1853 chmod 0664 /var/run/utmp /var/log/wtmp                                            # 把这两个文件的权限改为 0664 (rw-rw-r--) 1854 if [ -n "$_NEED_XFILES" ]; then                                                               #  如果 _NEED_XFILES 的值不为空 1855   > /var/run/utmpx                                                                                    # 则清空  /var/log/umptx 1856   touch /var/log/wtmpx                                                                             # 创建 /var/log/wtmpx 1857   chgrp utmp /var/run/utmpx /var/log/wtmpx                                              # 同样是修改 group 和 permission 1858   chmod 0664 /var/run/utmpx /var/log/wtmpx 1859 fi 1860 1861 1862 1863 1864 1865   1866 1867 1868 1869 1870 1871   1872 1873 1874 1875 1876 1877   1878 1879 1880 1881 1882 1883 # Clean up various /tmp bits                                                                        # 解析来是清理 /tmp 目录了 1884 rm -f /tmp/.X*-lock /tmp/.lock.* /tmp/.gdm_socket /tmp/.s.PGSQL.*            # 删除 /tmp 下的一些隐藏文件 1885 rm -rf /tmp/.X*-unix /tmp/.ICE-unix /tmp/.font-unix /tmp/hsperfdata_* \ 1886        /tmp/kde-* /tmp/ksocket-* /tmp/mc-* /tmp/mcop-* /tmp/orbit-*  \ 1887        /tmp/scrollkeeper-*  /tmp/ssh-* 1888 1889 1890 1891 1892 1893 1894 # Make ICE directory                                                                                     # 下面创建 ICE 目录 1895 mkdir -m 1777 -p /tmp/.ICE-unix >/dev/null 2>&1                                            # 创建 /tmp/.ICE-unix/ 目录,权限为 1777(sticky) 1896 chown root:root /tmp/.ICE-unix                                                                     # 改为属于 root用户、root 组 1897 [ -n "$SELINUX" ] && restorecon /tmp/.ICE-unix >/dev/null 2>&1         1898 1899 1900 1901 1902 1903                 1904 1905 1906 1907 1908 1909   1910 1911 1912 1913 1914 1915 # Start up swapping.                                               # 下面是启动 swap 空间 1916 update_boot_stage RCswap                                     # 执行 rhgb-client --update RCswap 1917 action $"Enabling swap space: " swapon -a -e            # 启用所有 swap 分区,并跳过那些不存在的 swap 设备 1918 1919 1920 1921 1922 1923 # Set up binfmt_misc                                                                                    # 设置 binfmt_misc 1924 /bin/mount -t binfmt_misc none /proc/sys/fs/binfmt_misc > /dev/null 2>&1     # 挂载 binfmt_misc 文件系统 1925 1926 1927 1928 1929 1930   1931 1932 1933 1934 1935 1936 # Initialize the serial ports.                                    # 初始化串口 1937 if [ -f /etc/rc.serial ]; then                                    # 如果存在 /etc/rc.serial 则执行该文件 1938  . /etc/rc.serial 1939 fi 1940 1941 1942 1943 1944 1945   1946 1947 1948 1949 1950 1951 # If they asked for ide-scsi, load it 1952 if strstr "$cmdline" ide-scsi ; then 1953  modprobe ide-cd >/dev/null 2>&1 1954  modprobe ide-scsi >/dev/null 2>&1 1955 fi 1956 1957 1958 1959 1960 1961   1962 1963 1964 1965 1966 1967 # Turn on harddisk optimization                                                                                        # 下面部分是用 hdparm 命令对硬盘进行优化 1968 # There is only one file /etc/sysconfig/harddisks for all disks                                                # 默认是使用统一的优化参数文件 /etc/sysconfig/harddisks, 1969 # after installing the hdparm-RPM. If you need different hdparm parameters                          # 如果你想对针对不同的硬盘进行优化,把该文件拷贝并重新命名为 1970 # for each of your disks, copy /etc/sysconfig/harddisks to                                                    # /etc/sysconfig/harddisk<hda~hdt> ,并修改该文件 1971 # /etc/sysconfig/harddiskhda (hdb, hdc...) and modify it. 1972 # Each disk which has no special parameters will use the defaults.                                        # 如果某个选项没有指定,则默认使用默认值 1973 # Each non-disk which has no special parameters will be ignored.                                          1974 1975                                                                                                                                           1976 # 下面定义一个数组,名为 disk ,共有21个元素 1977 1978 1979 disk[0]=s; 1980 disk[1]=hda;  disk[2]=hdb;  disk[3]=hdc;  disk[4]=hdd; 1981 disk[5]=hde;  disk[6]=hdf;  disk[7]=hdg;  disk[8]=hdh; 1982 disk[9]=hdi;  disk[10]=hdj; disk[11]=hdk; disk[12]=hdl; 1983 disk[13]=hdm; disk[14]=hdn; disk[15]=hdo; disk[16]=hdp; 1984 disk[17]=hdq; disk[18]=hdr; disk[19]=hds; disk[20]=hdt; 1985   1986 1987   1988 1989 1990 if [ -x /sbin/hdparm ]; then                                                                                     # 如果存在 /sbin/hdparm 且可执行,则 1991    for device in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do                            # 从0-20 循环,每次把一个数字赋予 device 变量 1992         unset MULTIPLE_IO USE_DMA EIDE_32BIT LOOKAHEAD EXTRA_PARAMS                         # 首先把 MULTIPLE_IO、USE_DMA、EIDE_32BIT、LOOKAHEAD、 1993 1994 1995 1996 1997 1998                                                                                                                                    # EXTRA_PARAMS 的值清空 1999         if [ -f /etc/sysconfig/harddisk${disk[$device]} ]; then                                              # 如果存在 /etc/sysconfig/harddisk<hda~hdt> 文件,则       2000                 . /etc/sysconfig/harddisk${disk[$device]}                                                                # 执行该文件 2001                 HDFLAGS[$device]=                                                                                                # 把 HDFLAGS 数组对应 $device 的元素的值清空 2002                 if [ -n "$MULTIPLE_IO" ]; then                                                                                  # 如果 MULTIPLE_IO 的值不为空,则 2003                     HDFLAGS[$device]="-q -m$MULTIPLE_IO"                                                                    # HDFLAGS 数组对应该 deivce 值的元素的值为 -q -m$MULTIPE_IO 2004   2005                 fi 2006                 if [ -n "$USE_DMA" ]; then                                                                                        # 如果 USE_DMA 的值不为空,则 2007                     HDFLAGS[$device]="${HDFLAGS[$device]} -q -d$USE_DMA"                                        # HDFLAGS 对应该 deivce 值的元素的值再加上  -q -d$USE_DMA 2008                 fi 2009                 if [ -n "$EIDE_32BIT" ]; then                                                                                      # 如果 EIDE_32BIT 变量的值不为空,则 2010                     HDFLAGS[$device]="${HDFLAGS[$device]} -q -c$EIDE_32BIT"                                        # HDFLAGS 对应 device 值的元素的值再加上 -q -c$EIDE_32BIT 2011                 fi     2012                 if [ -n "$LOOKAHEAD" ]; then                                                                                    # 如果 LOOKAHEAD 变量的值不为空,则 2013                     HDFLAGS[$device]="${HDFLAGS[$device]} -q -A$LOOKAHEAD"                                        # HDFLGAS 对应 device 值的元素的值加上 -q -A$LOOKAHEAD 2014                 fi 2015                 if [ -n "$EXTRA_PARAMS" ]; then                                                                                # 如果 EXTRA_PARAMS 变量的值不为空,则 2016                     HDFLAGS[$device]="${HDFLAGS[$device]} $EXTRA_PARAMS"                                           # HDFLAGS 对应 device 值的元素的值加上 -q $EXTRA_PARAMS 2017                 fi 2018         else                                                                                                                        # 如果不存在 /etc/sysconfig/harddisk<hda~hdt> 文件,则 2019                 HDFLAGS[$device]="${HDFLAGS[0]}"                                                                            # 统一使用 HDFLAGS[0] 的值作为每个硬盘的优化参数值 2020         fi 2021         if [ -e "/proc/ide/${disk[$device]}/media" ]; then                                                      # 如果存在 /proc/ide/<hda~hdt>/media 文件,则 2022              hdmedia=`cat /proc/ide/${disk[$device]}/media`                                                    # 则找出它的 media 类型并赋予变俩功能 hdmedia 2023              if [ "$hdmedia" = "disk" -o -f "/etc/sysconfig/harddisk${disk[$device]}" ]; then        # 如果 hdmedia 的值是 "disk" 或者存在 /etc/sysconfig/harddisk<hda-hdt> 文件  2024                   if [ -n "${HDFLAGS[$device]}" ]; then                                                                    # 且对应硬盘的参数值不为空,则 2025                       action $"Setting hard drive parameters for ${disk[$device]}: "  /sbin/hdparm ${HDFLAGS[$device]} /dev/${disk[$device]}    # 调用 action 函数, 2026                   fi                                                                                                                                                                                    # 执行 /sbin/hdparm 命令, 2027              fi                                                                                                                                                                                         # 根据给定优化参数值进行优化 2028         fi 2029    done 2030 fi             2031 # 注释 :这个 fi 是结束 "if [ -x /sbin/hdparm ];" 的 2032 2033 2034 2035 2036 2037   2038 2039 2040 2041 2042 2043 # Boot time profiles. Yes, this should be somewhere else.                         2044 if [ -x /usr/sbin/system-config-network-cmd ]; then 2045   if strstr "$cmdline" netprofile= ; then 2046     for arg in $cmdline ; do 2047         if [ "${arg##netprofile=}" != "${arg}" ]; then 2048      /usr/sbin/system-config-network-cmd --profile ${arg##netprofile=} 2049         fi 2050     done 2051   fi 2052 fi 2053 2054 2055 2056 2057 2058   2059 2060 2061 2062 2063 2064 # Now that we have all of our basic modules loaded and the kernel going,        # 现在所有基础的模块都已经被加载,内核已经开始运行了。可以把这些信息导出了 2065 # let's dump the syslog ring somewhere so we can find it later                        # 这样在启动后可以重新查阅. 2066 2067 2068 2069 2070 2071   2072 2073 2074 2075 2076 2077 # 补充 :在第 125 行,我们执行了 dmesg -n  $LOGLEVEL 命令,把信息都写入 syslog 了。 2078 2079 2080 2081 2082 2083   2084 2085 2086 2087 2088 2089 # 现在把它们从 syslog 中导出来到文件中                                                                                2090 2091 2092 2093 2094 2095 dmesg -s 131072 > /var/log/dmesg       # 执行 dmesg -s 131072 > /var/log/dmesg 文件,导出的内容是 131072 字节。 2096 2097 2098 2099 2100 2101                                                         # 默认是 16392 字节                                                                   2102 2103 2104 2105 2106 2107          2108 2109 2110 2111 2112 2113 # create the crash indicator flag to warn on crashes, offer fsck with timeout        # 在这里创建 /.autofsck ,如果系统在这里崩溃了,下次重启就会出现 fsck 提示 2114 touch /.autofsck &> /dev/null                    # 用 touch 命令创建 /.autofsck 。不过可以看到前面的第 785 -786行 把 /.autofsck 连同其他 /fastboot 等都删除了 2115 2116 2117 2118 2119 2120   2121 2122 2123 2124 2125 2126 kill -TERM `/sbin/pidof getkey` >/dev/null 2>&1        # 在这里才把 getkey 命令杀死 2127 } &                                                                        # command block 结束 2128 2129 2130 2131 2132 2133   2134 2135 2136 2137 2138 2139 2140 2141 2142 ############################################################################################################################################################ 2143 2144 2145 2146 2147 2148 2149 2150 if strstr "$cmdline" confirm ; then                                                # 如果内核启动参数含有 "comfirm" ,则 2151  touch /var/run/confirm                                                                 # 创建 /var/run/confirm 文件 2152 fi     2153 if [ "$PROMPT" != "no" ]; then                                                      # 如果 PROMPT 变量的值不为 no ,则 2154  /sbin/getkey i && touch /var/run/confirm                                    # 调用 getkey 等待用户输入 i ,如果按下 i 则创建 /var/run/confirm 2155 fi 2156 wait                                                                                            # 一旦用户按下任意键,则跳过该行,继续执行下面的代码 2157 2158 2159 2160 2161 2162   2163 2164 2165 2166 2167 2168 if [ -x /sbin/redhat-support-check -a -f /var/lib/supportinfo ]; then        #  如果存在 /sbin/redhat-support-check 且可执行,且存在 /var/lib/supportinfo  文件,则 2169  /sbin/redhat-support-check || {                                                                # 执行该命令,如果不成功则输出”Normal startup will continue in 10 seconds“ , 2170    echo $"Normal startup will continue in 10 seconds."                                    # 然后睡眠10秒钟 2171    sleep 10 2172 } 2173 fi 2174 2175 2176 2177 2178 2179   2180 2181 2182 2183 2184 2185 ########################################################################################################################################################  2186 2187 2188 2189 2190 2191 # Let rhgb know that we're leaving rc.sysinit                                            # 到这里 rc.sysinit 就结束了。 2192 if [ -x /usr/bin/rhgb-client ] && /usr/bin/rhgb-client --ping ; then             # 执行 rhgb-client --sysinit ,告诉 rhgb 服务器已经完成 rc.sysinit 了 2193     /usr/bin/rhgb-client --sysinit 2194 fi 2195 2196 2197 2198 2199 2200   2201 2202 2203 2204 2205 2206   2207 2208 2209 2210 2211 2212 ######################################################################################################################################################## ================================================================================= Yan Wang Comment that at the end of this article, there is one reader comment that says: =================================================================================   if ! strstr "$cmdline" nomodules && [ -f /proc/modules ] ; then         这句解释有误, 应改为如果$cmdline 变量的值不为nomodules 且存在/proc/modules文件 2213 2214
下一篇:Redis启动脚本

代码交流 2021