sysinit文件寫法詳解
sysinit文件是linux初始化文件系統時執行的第一個腳本文件。它主要做在各個運行級別中進行初始化工作,包括: 啟動交換分區;檢查磁盤;設置主機名;檢查並掛載文件系統;加載並初始化硬件模塊.
具體執行的腳本由inittab文件中的action為sysinit的一行確定。如LFS中為如下一行:
si::sysinit:/etc/rc.d/init.d/rc sysinit
這代表init初始化程序執行的第一個腳本為/etc/rc.d/init.d/rc,並傳入sysinit參數。一般linux傳入的參數為一數字,代表運行級別。rc會用參數合成/etc/init.d/rcsysinit.d目錄,並執行其中的文件完成服務初始化。下面是/etc/init.d/rcsysinit.d目錄中的文件。
│ └── rcsysinit.d
│ ├── S00mountkernfs -> ../init.d/mountkernfs
│ ├── S02consolelog -> ../init.d/consolelog
│ ├── S05modules -> ../init.d/modules
│ ├── S10udev -> ../init.d/udev
│ ├── S20swap -> ../init.d/swap
│ ├── S30checkfs -> ../init.d/checkfs
│ ├── S40mountfs -> ../init.d/mountfs
│ ├── S45cleanfs -> ../init.d/cleanfs
│ ├── S50udev_retry -> ../init.d/udev_retry
│ ├── S70console -> ../init.d/console
│ ├── S80localnet -> ../init.d/localnet
│ └── S90sysctl -> ../init.d/sysctl
下面我們來看一下LFS中rc文件的寫法。
#!/bin/sh
#------------------------------------
#sysconfig/rc只定義了幾個變量,內容如下:
#rc_base=/etc/rc.d
#rc_functions=${rc_base}/init.d/functions
#network_devices=/etc/sysconfig/network-devices
#----------------------------------------------
. /etc/sysconfig/rc
#由上面知rc_function為 "/etc/rc.d/init.d/functions"
#文件只設置了一變量,如PATH="/bin:/usr/bin:/sbin:/usr/sbin".還有一些函數
. ${rc_functions}
# This sets a few default terminal options.
stty sane
# These 3 signals will not cause our script to exit
trap "" INT QUIT TSTP
#如果 ${1}不為空,runlevel 為 ${1}。${1}是腳本的第一個參數
[ "${1}" != "" ] && runlevel=${1}
#如果runlevel為空則退出.${0}為腳本名字
if [ "${runlevel}" = "" ]; then
echo "Usage: ${0} " >&2
exit 1
fi
#當運行級變化時,PREVLEVEL存儲當前runlevel變量.
previous=${PREVLEVEL}
#if previous is null, previous is setted N.
#when boot system,the previous is null.
[ "${previous}" = "" ] && previous=N
#對應runlevel的目錄不存在則退出。
#boot_mesg為一個向屏幕輸出字符串的函數
if [ ! -d ${rc_base}/rc${runlevel}.d ]; then
boot_mesg "${rc_base}/rc${runlevel}.d does not exist." ${WARNING}
boot_mesg_flush
exit 1
fi
# 停止前一個運行級的所有服務,退出這一runlevel
# 當啟動系統時,下面不會運行。不必細看
if [ "${previous}" != "N" ]; then
for i in $(ls -v ${rc_base}/rc${runlevel}.d/K* 2> /dev/null)
do
check_script_status
suffix=${i#$rc_base/rc$runlevel.d/K[0-9][0-9]}
prev_start=$rc_base/rc$previous.d/S[0-9][0-9]$suffix
sysinit_start=$rc_base/rcsysinit.d/S[0-9][0-9]$suffix
if [ "${runlevel}" != "0" ] && [ "${runlevel}" != "6" ]; then
if [ ! -f ${prev_start} ] && [ ! -f ${sysinit_start} ]; then
boot_mesg -n "WARNING:\n\n${i} can't be" ${WARNING}
boot_mesg -n " executed because it was not"
boot_mesg -n " not started in the previous"
boot_mesg -n " runlevel (${previous})."
boot_mesg "" ${NORMAL}
boot_mesg_flush
continue
fi
fi
${i} stop
error_value=${?}
if [ "${error_value}" != "0" ]; then
print_error_msg
fi
done
fi
#開啟當前runlevel的所有服務,主要是這一段要明白。
for i in $( ls -v ${rc_base}/rc${runlevel}.d/S* 2> /dev/null)
do
if [ "${previous}" != "N" ]; then #this if is false when booting.
suffix=${i#$rc_base/rc$runlevel.d/S[0-9][0-9]}
stop=$rc_base/rc$runlevel.d/K[0-9][0-9]$suffix
prev_start=$rc_base/rc$previous.d/S[0-9][0-9]$suffix
[ -f ${prev_start} ] && [ ! -f ${stop} ] && continue
fi
check_script_status #a function judgeing the file if is a file and executable.
case ${runlevel} in
0|6) #if runleve is 0 or 6, stop the service i.
${i} stop
;;
*)
${i} start
;;
esac
error_value=${?}
if [ "${error_value}" != "0" ]; then
print_error_msg
fi
done
# End $rc_base/init.d/rc