#! /bin/bash
#
# rc This file is responsible for starting/stopping # 該腳本主要是用于在切換運行級別時啟動/停止服務(wù)
# services when the runlevel changes.
#
# Original Author:
# Miquel van Smoorenburg, <miquels@drinkel.nl.mugnet.org>
#
# check a file to be a correct runlevel script # 下面的 check_runlevel 不是檢查當(dāng)前運行級別的意思,而是檢查符號連接對應(yīng)的 target 是否真正存在
# 避免出現(xiàn)無效鏈接的情況
check_runlevel ()
{
# Check if the file exists at all. # -x 可以測試該 symbol link ($1)的 target 是否可執(zhí)行,如果不是則返回1
[ -x "$1" ] || return 1
# Reject backup files and files generated by rpm. # 如果可以執(zhí)行,還要檢查該腳本是否是備份或者升級 rpm 后留下來的。
case "$1" in # 根據(jù) $1 的值進行選擇
*.rpmsave|*.rpmorig|*.rpmnew|*~|*.orig) # 如果是以 .rpmsave ,。rpmorig、.rpmnew ,~ ,.orig 結(jié)尾的,則
return 1 # 返回 1
;;
esac
return 0 # 如果 target 存在且可執(zhí)行,又不是備份文件,則返回 0
}
# Now find out what the current and what the previous runlevel are. # 找出當(dāng)前和前一個運行級別
argv1="$1" # 把目標(biāo)新運行級別 $1 賦予給 argv1 變量
set `/sbin/runlevel` # 運行 runlevel 命令,把值送給 set 命令,set 默認(rèn)會把 N 賦予 $1 ,3 賦予 $2
runlevel=$2 # 把 $2 送給 runlevel 變量
previous=$1 # 把 $1 送給 previous 變量
export runlevel previous # 導(dǎo)出這兩個變量
# 補充 :注意不要混淆這里的 兩個 $1 ,前者是保存新的運行級別,后者是由 set $(runlevel)設(shè)置的 $1
. /etc/init.d/functions # 重要部分 :執(zhí)行 /etc/init.d/functions
##########################################################################################################################################################
# 注釋 :下面根據(jù)是否進入交互來打印不同的標(biāo)題欄,后面還會用到 /var/run/confirm 文件的。
# See if we want to be in user confirmation mode # 確認(rèn)是否處于 confirm 模式,也就是要求用戶確認(rèn)是否啟動服務(wù)
if [ "$previous" = "N" ]; then # 如果前一個運行級別是 N ,表示沒有改變過運行級別
if [ -f /var/run/confirm ]; then #如果存在 /var/run/confirm 文件(由 rc.sysinit 創(chuàng)建,前提是 $cmdline 有 confirm
#或者用戶按下了 i 鍵
echo $"Entering interactive startup" # 則打印 "Enterinig interactive setup" 提示信息
else #如果不存在 /var/run/confirm 文件,則
echo $"Entering non-interactive startup" # 打印 "Entering non-interactive startup" 表示用戶在下來的過程中無法干涉
fi
fi
# Get first argument. Set new runlevel to this argument. # 將新運行級別變量賦予變量 runlevel 。
[ -n "$argv1" ] && runlevel="$argv1" # 補充 :這里實際上可以在上面直接把 $1 賦予 runlevel ,因為后面并不
# 需要知道當(dāng)前的運行級別
# 補充 :一旦機器重啟,previous level 總是為 N ,除非你執(zhí)行了類似 telinit 1 這樣的命令,previous level 才會是3或者5
# Is there an rc directory for this new runlevel? # 檢查指定的新運行級別是否有對應(yīng)的 rc 目錄?
[ -d /etc/rc$runlevel.d ] || exit 0 # 如果存在這個目錄就繼續(xù),否則返回 0
###########################################################################################################################################################
# 注釋 :下面開始執(zhí)行新 runlevel 的 rc 目錄中那些以 K 開頭的腳本
# First, run the KILL scripts.
for i in /etc/rc$runlevel.d/K* ; do # 對于在 /etc/rc<new-level>.d/ 目錄下的每個以 K 開頭的文件
check_runlevel "$i" || continue # 首先用 check_runlevel 檢查符號連接的有效性
# 如果是無效地,則跳過它繼續(xù)處理下一個符號鏈接(服務(wù))
# Check if the subsystem is already up. # 下面檢查某項服務(wù) $(i) 是否是已經(jīng)激活的
subsys=${i#/etc/rc$runlevel.d/K??} # 從符號連接名中取出真正的服務(wù)名,也就是K<0-9><0-9> 后面的部分
[ -f /var/lock/subsys/$subsys -o -f /var/lock/subsys/$subsys.init ] \ # 如果在 /var/lock/subsys 中有同樣名稱的文件或者 <prog>.init 文件,
||continue # 則執(zhí)行后面的腳本,如果沒有則表示服務(wù)停止,無須執(zhí)行下面的代碼
# 補充 :從上面 subsys 變量的賦值中可以看出系統(tǒng)最多只能有 99 個服務(wù),如果是100的話,則 subsys 的值將不正確(會留有一個數(shù)字)
# 例如 K100nfs ,經(jīng)過上面的賦值后,subsys 會變成 0nfs ,而不是 nfs ,這樣可能就無法殺死當(dāng)前運行的 nfsd 進程了
# Bring the subsystem down. # 把服務(wù)停止
if egrep -q "(killproc |action )" $i ; then # 如果腳本中含有 killprog 或者 action
$i stop # 直接用 <prog> stop 的方式停止它們
else # 如果找不到這兩個字符串,則
action $"Stopping $subsys: " $i stop # 用 action 函數(shù),打印 "Stopping <prog> :" ,然后執(zhí)行 <prog> stop
fi
done # 這樣先把每個以 K 開頭的腳本都執(zhí)行完
# 補充 :上面搜索 killproc 或者 action 字符串的目的可能是因為 :如果某個腳本不使用 /etc/init.d/functions ,則在停止服務(wù)時可能不會
# 顯示相關(guān)信息,所以先用 action 打印該字符串(stopping xxx),然后再執(zhí)行 <prog> stop (可能在 <prog> 腳本中的 stop 部分不一定給出
# 相關(guān)的提示信息;如果 <prog> 腳本是含有 killproc 或者 action ,則 killproc 自動會調(diào)用 success()或者 failure()函數(shù)輸出提示信息
# Now run the START scripts. # 在上面的 Kill 腳本都執(zhí)行完后,就執(zhí)行以 S 開頭的腳本了。
for i in /etc/rc$runlevel.d/S* ; do # 首先對于 /etc/rc<new-level>.d/ 目錄下的 S 開頭的每個文件,都執(zhí)行下面的代碼
check_runlevel "$i" || continue # check_runlevel 確保存在 target ,否則跳過該服務(wù)
# Check if the subsystem is already up. # 檢查該服務(wù)是否已經(jīng)啟動,如果啟動就跳過下面代碼處理下一個服務(wù)
subsys=${i#/etc/rc$runlevel.d/S??}
[ -f /var/lock/subsys/$subsys -o -f /var/lock/subsys/$subsys.init ] \
&& continue
# If we're in confirmation mode, get user confirmation # 啟動服務(wù)可以是 confirm 模式,也就是按y啟動、按n不啟動,按c恢復(fù)到非交互模式
if [ -f /var/run/confirm ]; then # 首先查詢是否有 /var/run/confirm 文件存在。
confirm $subsys # 如果存在,就使用 /etc/init.d/functions 的 confirm 函數(shù)來處理該服務(wù)
test $? = 1 && continue # 按y返回0,按n返回1,按c返回2;如果是1的話表示不啟動該服務(wù),所以跳過后面代碼
fi
# 如果是y或者c則啟動。但 c 會取消 continue 模式
update_boot_stage "$subsys" # 調(diào)用 update_boot_stage ,執(zhí)行 rhgb-clinet --update "$subsys"
# Bring the subsystem up. # 現(xiàn)在可以激活該服務(wù)了。注意,上面 confirm $subsys 只是確認(rèn)是否啟動而已,并為真正啟動
if [ "$subsys" = "halt" -o "$subsys" = "reboot" ]; then # 如果該服務(wù) $sbusys 是 halt 或者 reboot 服務(wù),則
export LC_ALL=C # 把 LC_ALL 設(shè)置為 C
exec $i start # 執(zhí)行 exec $i start ,也就是用 halt start 或者 reboot start 代替當(dāng)前進程,注意 exec 的使用
fi
if egrep -q "(daemon |action |success |failure )" $i 2>/dev/null \ # 如果不是上面兩個服務(wù)之一,且該服務(wù)腳本中有 daemon、action、success、failure 等字符串,則
|| [ "$subsys" = "single" -o "$subsys" = "local" ]; then # 或者服務(wù)為 single 或者 local 服務(wù),則
$i start # 直接執(zhí)行 <prog> start ,這次不用 exec 方式了
else # 如果都不是上面的 halt、reboot、single、local 服務(wù),則
action $"Starting $subsys: " $i start # 用 action 打印一個 "starting xxx" 的信息,然后執(zhí)行 $i start 啟動該服務(wù)
fi
done # 就用這樣的方式對每個 S 開頭的腳本都處理一次
###########################################################################################################################################################
rm -f /var/run/confirm # 最后刪除 /var/run/confirm 文件,實際上如果上面在啟動某個某個服務(wù)按下c,則該文件就被刪除了
###########################################################################################################################################################
if [ -x /usr/bin/rhgb-client ] && /usr/bin/rhgb-client --ping ; then
/usr/bin/rhgb-client --quit # 執(zhí)行 rhgb-client --quit ,--quit 就是告訴 rhgb 服務(wù)器(/usr/sbin/rhgb)退出
fi