# 注释 : 下面开始真正的 fsck 操作
if [ "${RHGB_STARTED}" != "0" -a -w /etc/rhgb/temp/rhgb-console ]; then # 如果 RHGB_STARTED 不为0且 /etc/rhgb/tmp/rhgb-console 文件可写,则
fsck -T -a $rootdev $fsckoptions > /etc/rhgb/temp/rhgb-console # 执行 fsck 命令,-T 表示不打印标题栏,-a 表示自动修复错误,设备是 / ,后面是选项
# 且信息写入 /etc/rhgb/temp/rhgb-console
else # 否则
initlog -c "fsck -T -a $rootdev $fsckoptions" # 调用 initlog 执行 fsck ,信息直接输出到屏幕,fsck 命令本身都是一样的。
fi
rc=$? # 把 fsck 的结果送给变量 rc
if [ "$rc" -eq "0" ]; then # 如果 rc的值为0,表示 fsck 成功通过
success "$STRING" # 则调用 success 打印 "checking root fileysyes [OK]"
echo
elif [ "$rc" -eq "1" ]; then # 如果 rc 为1 ,则打印 passed ,表示有错误但修复
passed "$STRING" # 这时调用的是 passed 函数(由 /etc/rc.d/init.d/functions 脚本定义,输出 "checking root filesystems [ PASSED ]")
echo
elif [ "$rc" -eq "2" -o "$rc" -eq "3" ]; then # 如果 rc 为 2 (表示系统应该重启)或者为 3(为 1+2 ,表示系统错误已修复,但需要重启)
echo $"Unmounting file systems" # 提示卸载 / 文件系统
umount -a # 把所有卸载,当然 / 除外
mount -n -o remount,ro / # 把 / 设备已 ro 模式重新 mount
echo $"Automatic reboot in progress." # 然后提示将要自动重启了
reboot -f # 在这里执行 reboot -f ,强制重启
fi # 这个 fi 是结束 "[ "$rc" -eq "0" ]; " 的
# A return of 4 or higher means there were serious problems. # 如果 fsck 返回的值大于4(不含4,4表示错误未修复),则表示 / 文件系统出现重大错误,无法继续
if [ $rc -gt 1 ]; then # 这里之所以用 -gt 1 ,是因为如果前面返回2或者3就会自动重启了,如果执行到这里说明 rc 的值必须至少大于等于4
if [ -x /usr/bin/rhgb-client ] && /usr/bin/rhgb-client --ping ; then # 如果 rhgb-client 可执行且 rhgb 服务在运行
chvt 1 # 强制切换到 1# 虚拟控制台
fi
failure "$STRING" # 调用 failure 函数,打印 "checking root filesystem [ FAILURE ]"
echo
echo
echo $"*** An error occurred during the file system check." # 提示 fsck 过程出错
echo $"*** Dropping you to a shell; the system will reboot" # 提示将进入紧急模式的 shell
echo $"*** when you leave the shell." # 当你退出该 shell 时会自动重启
str=$"(Repair filesystem)" # 设置紧急模式下的 shell 提示符
PS1="$str \# # "; export PS1 # 设置提示符变量 PS1 为 "(Repair filesystem) # " , 表示当前是第几个命令
[ "$SELINUX" = "1" ] && disable_selinux
sulogin # 自动执行 sulogin ,这不是 su ,而是 single-user login 的意思,自动进入单用户模式的 shell
# 注意这里将进入一个交互式的 shell 。只有你执行 exit 命令,才会执行下面的代码,否则下面的代码根本不会被执行
echo $"Unmounting file systems" # 提示卸载文件系统
umount -a # 卸载所有文件系统,/ 除外
mount -n -o remount,ro / # / 以 ro 模式挂载
echo $"Automatic reboot in progress." # 提示将自动重启
reboot -f # 立即重启
elif [ "$rc" -eq "1" ]; then # 如果 rc 的值等于1 ,则表示错误修复完毕
_RUN_QUOTACHECK=1 # 如果上面的 fsck 没有出错,自然就不会重启,所以这里把 _RUN_QUOTACHECK 的值设置为1,表示可以进行 quotacheck 了
fi # 这个 fi 是结束 " [ $rc -gt 1 ]; " 的
if [ -f /.autofsck -a -x /usr/bin/rhgb-client ] && /usr/bin/rhgb-client --ping ; then # 如果 rhgb-clinet 可运行且 rhgb 服务在运行
chvt 8 # 则切换换 8# 控制台,也就是图形
fi
fi # 这个 fi 是结束前面的 ”[ -z "$fastboot" -a "$READONLY" != "yes" -a "X$ROOTFSTYPE" != "Xnfs" -a "X$ROOTFSTYPE" != "Xnfs4" ]; “ 的
# 所以如果存在 /fastboot 文件,就直接跳转到这里
########################################################################################################################################################
# 注释 :在 initrd 的 /linuxrc 或者 /init 脚本中会把初始/文件系统卸载掉,如果没有卸载完全,则在这里会重新做一次
# Unmount the initrd, if necessary # 接下来是卸载 initrd 初始/ 文件系统,一般 /init 都会在结尾 umount /initrd/dev 的
if LC_ALL=C fgrep -q /initrd /proc/mounts && ! LC_ALL=C fgrep -q /initrd/loopfs /proc/mounts ; then # 如果 /proc/mounts 文件还有 /initrd/proc 条目,
# 且不存在 /initrd/loops 条目,则
if [ -e /initrd/dev/.devfsd ]; then # 如果存在 /initrd/dev/.devfsd 文件,则
umount /initrd/dev # 卸载 /initrd/dev 目录
fi
umount /initrd # 最后把整个 /initrd 卸载
/sbin/blockdev --flushbufs /dev/ram0 >/dev/null 2>&1 # 最后用 blockdev --flushbs 命令清除 /dev/ram0 的内容,该社备就是被挂载为初始/的
fi
######################################################################################################################################################## # 注释 :下面是对 / 进行 quota 检查,其他文件系统暂时不执行 quotacheck
# Possibly update quotas if fsck was run on /. # 如果 fsck 已经对 / 进行了检查,则执行 quotacheck 更新 quota 情况
LC_ALL=C grep -E '[[:space:]]+/[[:space:]]+' /etc/fstab | \ # 在 /etc/fstab 中找出 / 文件系统所在的行,并打印第4个字段(属性)
awk '{ print $4 }' | \ # 这是属性字段
LC_ALL=C fgrep -q quota # 找出是否有 quota 字符串,不管是 usrquota 还是 grpquota
_ROOT_HAS_QUOTA=$? # 把结果赋予 _ROOT_HAS_QUOTA 变量
if [ "X$_RUN_QUOTACHECK" = "X1" -a \ # 如果 x$_RUN_QUOTACHECK 返回 X1 ,且
"X$_ROOT_HAS_QUOTA" = "X0" -a \ # X$_ROOT_HAS_QUOTA 返回 X0 ,则表示当前可以执行 quotacheck ,且 / 也启用了 quota
-x /sbin/quotacheck ]; then # 如果存在 quotacheck 命令
if [ -x /sbin/convertquota ]; then # 如果存在 convertquota 命令
if [ -f /quota.user ]; then # 且存在 /quota.user 则
action $"Converting old user quota files: " \ # 并调用 action 函数,打印提示信息,用 convertquota 转换成 v2 格式的 aquota.user 文件
/sbin/convertquota -u / && rm -f /quota.user # 然后删除 v1格式的 /quota.user
fi
if [ -f /quota.group ]; then # 同样对 /quota.group 转换成 v2 格式的 aquota.group,并删除 /quota.group 文件
action $"Converting old group quota files: " \
/sbin/convertquota -g / && rm -f /quota.group # 同样在转换后删除旧的 v1 的 group quota 文件
fi
fi
action $"Checking root filesystem quotas: " /sbin/quotacheck -nug / # 然后执行 quotacheck -nug / 对 / 文件系统进行检查,并打印提示信息
fi # 这个 fi 是结束 "[ "X$_RUN_QUOTACHECK" = "X1" -a "X$_ROOT_HAS_QUOTA" = "X0" -a -x /sbin/quotacheck ]; " 的
########################################################################################################################################################
# 注释 :下面这个部分是设置 ISA 设备的,不过由于现在基本没有 ISA 设备了,所以可以跳过该部分,甚至可以在内核中指定不支持 ISA
if [ -x /sbin/isapnp -a -f /etc/isapnp.conf -a ! -f /proc/isapnp ]; then
# check for arguments passed from kernel
if ! strstr "$cmdline" nopnp ; then
PNP=yes
fi
if [ -n "$PNP" ]; then
action $"Setting up ISA PNP devices: " /sbin/isapnp /etc/isapnp.conf
else
action $"Skipping ISA PNP configuration at users request: " /bin/true
fi
fi
########################################################################################################################################################
# Remount the root filesystem read-write. # 现在 / 文件系统 fsck 过了,可以按照 read-write 的模式挂载了
update_boot_stage RCmountfs # 告诉 rhgb 服务器更新 RCmountfs 服务的状态
state=`awk '/ \/ / && ($3 !~ /rootfs/) { print $4 }' /proc/mounts` # 从 /proc/mounts 中找出 ' / ' 字符串并且第3个字段不等于 'rootfs',则打印其第4个字段,赋予 state
[ "$state" != "rw" -a "$READONLY" != "yes" ] && \ # 如果 state 变量的值不为 'rw' 且 READONLY 变量的值为 yes ,则
action $"Remounting root filesystem in read-write mode: " mount -n -o remount,rw / # 用 -o remount -o rw 重新挂载 / 为 rw 模式,并打印提示信息
########################################################################################################################################################
# 注释 :下面开始是 LVM2 的部分了
# LVM2 initialization # 下面部分是 LVM2 的初始化部分
if [ -x /sbin/lvm.static ]; then # 如果存在 /sbin/lvm.static 且可执行
if ! LC_ALL=C fgrep -q "device-mapper" /proc/devices 2>/dev/null ; then # 如果 /proc/devices 文件不含有 device-mapper ,则
modprobe dm-mod >/dev/null 2>&1 # 调用 modprobe 加载 dm-mod
fi
echo "mkdmnod" | /sbin/nash --quiet >/dev/null 2>&1 # 并调用 nash 执行 mkdmmod ,不过是以 quiet 模式执行的
[ -n "$SELINUX" ] && restorecon /dev/mapper/control >/dev/null 2>&1
if [ -c /dev/mapper/control -a -x /sbin/lvm.static ]; then # 假如存在 /dev/mapper/control 这个字符设备且 /sbin/lvm.static 可执行,则
if /sbin/lvm.static vgscan --mknodes --ignorelockingfailure > /dev/null 2>&1 ; then # 调用 lvm.static 执行 vgscan 扫描所有卷组(忽略锁错误)
action $"Setting up Logical Volume Management:" /sbin/lvm.static vgchange -a y --ignorelockingfailure # 如果扫描到卷组,则调用 action 函数,
fi # 打印提示信息,并执行 vgchange -ay 激活全部卷组
fi
fi
# LVM initialization # 这是 LVM1 的部分,因为系统可能同时存在 lVM1 和 lvm2 的 pv
if [ -f /etc/lvmtab ]; then # 如果存在 /etc/lvmtab 文件
[ -e /proc/lvm ] || modprobe lvm-mod > /dev/null 2>&1 # 且 /proc/lvm 文件存在,如果没有则调用 modprobe lvm-mod 加载 lvm-mod ,注意模块名的不同
if [ -e /proc/lvm -a -x /sbin/vgchange ]; then # 如果现在存在 /proc/lvm 文件且 /sbin/vgchange 可执行
action $"Setting up Logical Volume Management:" /sbin/vgscan && /sbin/vgchange -a y # 则调用 action 打印提示信息,并执行 vgchange -ay 激活它们
fi
fi
########################################################################################################################################################
# Clean up SELinux labels
if [ -n "$SELINUX" ]; then
for file in /etc/mtab /etc/ld.so.cache ; do
[ -r $file ] && restorecon $file >/dev/null 2>&1
done
fi
########################################################################################################################################################
# Clear mtab # 由于之前的 /etc/mtab 并不准确,所以现在把它的内容清掉
(> /etc/mtab) &> /dev/null # 用 >/etc/mtab 清空其内容
# Remove stale backups
rm -f /etc/mtab~ /etc/mtab~~ # 删除 /etc/mtab 的备份文件
# Enter root, /proc and (potentially) /proc/bus/usb and devfs into mtab. # 把 root ,/proc ,/proc/bus/usb,devpts 加入到 /etc/mtab 中
mount -f / # -f 表示只更新 /etc/mtab ,但不实际mount,因为这些文件系统在之前都挂载了,没有必要再挂载一次
mount -f /proc
mount -f /sys >/dev/null 2>&1
mount -f /dev/pts
[ -f /proc/bus/usb/devices ] && mount -f -t usbfs usbfs /proc/bus/usb # 如果存在 /proc/bus/usb/devices 文件,则用 mount -f -t usbfs 挂载到 /proc/bus/usb 下
[ -e /dev/.devfsd ] && mount -f -t devfs devfs /dev # 如果存在 /dev/.devfsd ,则同样挂载 devfs 到 /dev 下
########################################################################################################################################################
# configure all zfcp (scsi over fibrechannel) devices before trying to mount them
# zfcpconf.sh exists only on mainframe
[ -x /sbin/zfcpconf.sh ] && /sbin/zfcpconf.sh
########################################################################################################################################################
# The root filesystem is now read-write, so we can now log # 由于之前的 / 是只读的,所以通过 initlog 来记录信息,现在可以通过 syslog 了
# via syslog() directly..
if [ -n "$IN_INITLOG" ]; then
IN_INITLOG= # 如果 IN_INITLOG 的值不为空则清空它
fi
if ! strstr "$cmdline" nomodules && [ -f /proc/modules ] ; then # 如果内核启动参数含有 "nomodules" ,且存在 /proc/modules 文件,则
USEMODULES=y # 把 USEMODULES 设置为 y
fi
# Load modules (for backward compatibility with VARs)
if [ -f /etc/rc.modules ]; then
/etc/rc.modules
fi
########################################################################################################################################################
update_boot_stage RCraid # 下面部分是激活 RAID 的
if [ -f /etc/mdadm.conf ]; then # 如果存在 /etc/mdadm.conf 则
/sbin/mdadm -A -s # mdadm -A 表示 Assemble 模式,-s 则表示搜索 /etc/mdadm.conf
fi
# 注释 :下面解决旧式的用 raid-tools 建立的 software-raid
if [ -f /etc/raidtab ]; then # 如果存在旧式的 raidtools 的 /etc/raidtab 则
# Add raid devices
[ -f /proc/mdstat ] || modprobe md >/dev/null 2>&1 # 如果不存在 /proc/mdstat 文件,则用 modprobe md 先加载 md 模块
if [ -f /proc/mdstat ]; then
echo -n $"Starting up RAID devices: " # 并输出 "Starting up RAID devices:"
rc=0 # 先把 rc 的值设置为0,如果有某个 raid 激活失败,则 rc 为 1
# rc 和下面的 RESULT 不同,RESULT 是每个 raid 的激活状态,而 rc 是全局的激活状态
for i in `awk '{if ($1=="raiddev") print $2}' /etc/raidtab` # 用 awk 从 /etc/raidtab 中找出所有 raiddev 行打印第2个字段也就是 raid 的设备名
do # 针对每个 Software-raid 执行下面的代码
RAIDDEV=`basename $i` # 把每个 raid 设备的设备名(出去前面目录部分)赋予变量 RAIDDEV
RAIDSTAT=`LC_ALL=C grep "^$RAIDDEV : active" /proc/mdstat` # 如果 /proc/mdstat 中表明该 RAID 已经是 active 的状态
if [ -z "$RAIDSTAT" ]; then # 如果状态为空,表明该 RAID 并没有激活
# First scan the /etc/fstab for the "noauto"-flag
# for this device. If found, skip the initialization
# for it to avoid dropping to a shell on errors.
# If not, try raidstart...if that fails then
# fall back to raidadd, raidrun. If that
# also fails, then we drop to a shell
RESULT=1 # 先把 RESULT 设置为 1,表示 false
INFSTAB=`LC_ALL=C grep -c "^$i" /etc/fstab` # 然后检查 /etc/fstab 中是否有以指定的 md 设备开头的行,结果赋予 INFSTAB
if [ $INFSTAB -eq 0 ] ; then # 如果 INFSTAB 为0,表示没有找到,也就是不希望自动我你挂载该 raid 设备
RESULT=0 # 则把 RESULT 设置为0
RAIDDEV="$RAIDDEV(skipped)" # 并在 RAIDDEV 后面加上 (skipped) ,表示该设备跳过不激活它
fi
NOAUTO=`LC_ALL=C grep "^$i" /etc/fstab | LC_ALL=C fgrep -c "noauto"` # 如果该设备在 /etc/fstab 中但它的属性含有 noauto
if [ $NOAUTO -gt 0 ]; then # 则和上面不在 /etc/fstab 一样处理
RESULT=0
RAIDDEV="$RAIDDEV(skipped)"
fi
if [ $RESULT -gt 0 -a -x /sbin/mdadm ]; then # 如果 /sbin/mdadm 文件可执行,且尝试用 mdadm 来激活它们
/sbin/mdadm -Ac partitions $i -m dev # mdadm 将从 /proc/partitions 文件读取并状态指定 raid($i) ,-m 表示 minor
# number 就等于它刚才装配的 raid 设备名的数字部分
RESULT=$? # 并把 mdadm 的结果赋予 RESULT 变量
fi
if [ $RESULT -gt 0 -a -x /sbin/raidstart ]; then # 如果 RESULT 大于0,表示 madm 命令失败,则尝试用 /sbin/raidstart 来
/sbin/raidstart $i
RESULT=$?
fi
if [ $RESULT -gt 0 -a -x /sbin/raid0run ]; then # 如果 raidstart 还是失败,则尝试用 raid0run 来
/sbin/raid0run $i
RESULT=$?
fi
if [ $RESULT -gt 0 -a -x /sbin/raidadd -a -x /sbin/raidrun ]; then # 如果 raid0run 失败则尝试用 raidadd 然后用 raidrun
/sbin/raidadd $i
/sbin/raidrun $i
RESULT=$?
fi
if [ $RESULT -gt 0 ]; then # 如果还是失败,则 rc 的值最终为1
rc=1
fi
echo -n "$RAIDDEV " # 输出当前操作的 raid 设备名
else # 这个 else 是对应 ”if [ -z "$RAIDSTAT" ]; “的,因为可能内核集成了 raid support ,自动激活 raid
echo -n "$RAIDDEV " # 如果 RAID 的状态本来就是 active ,则直接输出 raid 的名称
fi
done
echo
# A non-zero return means there were problems. # 如果只要有一个 raid 激活失败,则 rc 的值就为1
if [ $rc -gt 0 ]; then # 如果 rc 的值大于0,则表示有 raid 激活失败
if [ -x /usr/bin/rhgb-client ] && /usr/bin/rhgb-client --ping ; then # 则按照前面 fsck 失败的情况,进入紧急模式
chvt 1
fi
echo
echo
echo $"*** An error occurred during the RAID startup"
echo $"*** Dropping you to a shell; the system will reboot"
echo $"*** when you leave the shell."
str=$"(RAID Repair)" # 只不过提示符有所不同而已,变成了 (RAID Repair) #
PS1="$str \# # "; export PS1
[ "$SELINUX" = "1" ] && disable_selinux
sulogin
echo $"Unmounting file systems"
umount -a
mount -n -o remount,ro /
echo $"Automatic reboot in progress."
reboot -f
fi # 注释 ;这个 fi 是结束 "if [ -f /etc/raidtab ];" 的,如果不存在 /etc/raidtab ,则直接跳到这里
########################################################################################################################################################