歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Unix知識 >> 關於Unix >> 試析FreeBSD 6.2的rc腳本系統

試析FreeBSD 6.2的rc腳本系統

日期:2017/2/28 11:19:02   编辑:關於Unix


一、從mysql的啟動腳本說起
mysql_enable="YES"
這樣在重新啟動系統的時候,就可以自動運行 mysqlserver.
如果需要運行時,停止 mysqlserver 或者重新啟動 mysqlserver,可以使用下面的命令:
停止mysqlserver: shell>/usr/local/etc/rc.d/mysql-server stop
重新啟動mysqlserver: shell>/usr/local/etc/rc.d/mysql-server restart
其實無論是mysqlserver還是apache等系統服務,都可以利用上面提到的參數“stop“,”restart“等進行程序維護
這屬於FreeBSD系統rc腳本系統的具體應用。
FreeBSD的rc腳本系統在服務程序的管理上,主要是體現在 /etc/rc.d 和 /usr/local/etc/rc.d 這兩個目錄下的可執行腳本,系統級別的服務程序的腳本大都安裝在 /etc/rc.d目錄下,而用戶級別的服務程序的腳本都安裝在 /usr/local/etc/rc.d 目錄下。如 mysql server 在安裝的時候會在 /usr/local/etc/rc.d目錄下安裝一個 mysql-server 的腳本文件。
服務程序的管理,其實運行的就是對應的腳本文件。如上面舉例的停止服務,重新啟動服務,運行的都是mysql-server腳本。
二、mysql-server 啟動腳本的說明
下面的腳本代碼是freebsd 6.2中mysqlserver 5.0的啟動腳本。具體的功能在腳本代碼中注釋!
#!/bin/sh
#
# $FreeBSD: ports/databases/mysql50-server/files/mysql-server.sh.in,v 1.3 2006/03/07 16:25:00 ale Exp $
#
# PROVIDE: mysql
# REQUIRE: LOGIN
# KEYWORD: shutdown
#
# mysql_enable (bool): Set to "NO" by default.
# Set it to "YES" to enable MySQL.
# mysql_limits (bool): Set to "NO" by default.
# Set it to yes to run `limits -e -U mysql`
# just before mysql starts.
# mysql_dbdir (str): Default to "/var/db/mysql"
# Base database directory.
# mysql_args (str): Custom additional arguments to be passed
# to mysqld_safe (default empty).
#
# 下面的這行代碼非常重要,作用是在mysql-server的腳本代碼中插入 /etc/rc.subr 文件的代碼!
# 在 /etc/rc.subr 文件中,提供了 mysql-server 調用的函數的實現,也提供了很多rc腳本系統中用到的函數。
# mysql-server 中能夠使用的 start,stop,restart,rcvar等參數的具體運作,也是在 /etc/rc.subr 中提供的。
. /etc/rc.subr
# 在 /etc/rc.subr 中,首先運行一些初始化命令,跟蹤運行,執行了以下命令:
if [ -z "${_rc_subr_loaded}" ]; then
_rc_subr_loaded="YES"
SYSCTL="/sbin/sysctl"
SYSCTL_N="${SYSCTL} -n"
CMD_OSTYPE="${SYSCTL_N} kern.ostype"
OSTYPE=`${CMD_OSTYPE}`
ID="/usr/bin/id"
JID=`ps -p $$ -o jid=`
IDCMD="if [ -x $ID ]; then $ID -un; fi"
case ${OSTYPE} in
FreeBSD)
SYSCTL_W="${SYSCTL}"
;;
NetBSD)
SYSCTL_W="${SYSCTL} -w"
;;
esac
# 定義name變量
name="mysql"
# 調用 /etc/rc.subr 文件中定義的 set_rcvar 函數
# 函數的執行結果是給幾個變量賦值
rcvar=`set_rcvar`

# set_rcvar的執行結果
base_var=mysql
echo mysql_enable
rcvar=mysql_enable
# 調用 /etc/rc.subr 文件中定義的 load_rc_config 函數,參數是 name 變量的值。
load_rc_config $name
# 定義一些變量
: ${mysql_enable="NO"}
: ${mysql_limits="NO"}
: ${mysql_dbdir="/var/db/mysql"}
: ${mysql_args=""}
# 定義一些變量,通過這些變量,能夠組合出mysqlserver啟動的具體參數。涉及mysqlserver的一些具體工具的使用。
mysql_user="mysql" # 啟動用帳戶
mysql_limits_args="-e -U ${mysql_user}" # 啟動參數
pidfile="${mysql_dbdir}/`/bin/hostname`.pid"
command="/usr/local/bin/mysqld_safe" # 啟動命令
procname="/usr/local/libexec/mysqld"
start_precmd="${name}_prestart" # 定義一個函數接口,關聯到本腳本文件中定義的 mysql_prestart()函數
mysql_install_db="/usr/local/bin/mysql_install_db"
mysql_install_db_args="--ldata=${mysql_dbdir}"
# 下面這個函數用來建立mysql數據苦,初始化授權表,並且建立一個test數據庫
mysql_create_auth_tables()
{
eval $mysql_install_db $mysql_install_db_args >/dev/null
[ $? -eq 0 ] && chown -R ${mysql_user}:${mysql_user} ${mysql_dbdir}
}
# 下面這個函數用來定義程序啟動前的一些動作。
# 檢查mysql數據庫目錄是否存在,如果沒有存在,運行建立數據庫,初始化授權表。
mysql_prestart()
{
if [ ! -d "${mysql_dbdir}/mysql/." ]; then
mysql_create_auth_tables || return 1
fi
if checkyesno mysql_limits; then
eval `/usr/bin/limits ${mysql_limits_args}` 2>/dev/null
else
return 0
fi
}
# 下面的一行代碼是運行 /etc/rc.subr 中的 run_rc_command 函數
# 如果我們執行 /usr/local/etc/rc.d/mysql-server start
# 那麼執行的就是 run_rc_command "start"
run_rc_command "$1"
######## mysql-server 腳本到此結束
余下運行的都是根據本腳本運行過程中定義的各種變量來執行 /etc/rc.subr 中的run_rc_command 函數。
三、/etc/rc.subr中的run_rc_command 函數
這個函數中提供了很多參數的處理過程,諸如start,stop,restart,rcvar,pull等過程。
也提供了可選參數fast,force,one的具體執行代碼。具體的代碼就不作解釋了,
如果這些參數的處理過程沒有在服務程序的腳本中進行定義,那麼運行的就是函數中定義的處理過程。
通過腳本分析獲知使用rc腳本系統中一些細節。
1、如果運行具體服務程序的rc腳本沒有帶參數,rc_rc_command會打印出幫助信息
Usage: ./mysql-server [fast|force|one](start|stop|restart|rcvar|status|poll)
沒有使用[force][one]選項,start,stop,restart,status是沒有運行結果的。
[force]的作用是強制 {rcvar} 有效,使得 mysql_enable="yes"臨時有效
shell> /usr/local/etc/rc.d/mysql-server forcestart
shell> /usr/local/etc/rc.d/mysql-server forcerestart
[one]的作用和[force]類似,不同的是one 只是設置 {$rcvar}有效。
四、階段性小結
通過上面的代碼分析,以及參考更多的服務程序的rc腳本,大致可以理出rc腳本系統中服務程序管理的大致原理。
freebsd系統提供的 rc.subr 是整個rc腳本系統的核心,它提供了系統利用rc腳本管理服務程序的基石。
在這個基礎上,實現了服務程序rc腳本的框架結構。定義了統一的運行規則。並且為服務程序諸如mysqlserver提供了很大的靈活性。
但rc.subr的作用不只如此,從rc.subr的代碼可知,它提供的功能實際是架構起了FreeBSD整個系統的rc腳本系統。
五、系統啟動自動運行服務程序的機制
1、rc腳本系統什麼時候啟動
按照《FreeBSD操作系統設計與實現》中的說法,rc腳本系統是在加載完系統內核,出現freebsd啟動模式選擇界面,選擇運行方式,啟動init之後開始運行。在多用戶模式啟動系統的情況下,init首先產生一個shell,默認的是 /bin/sh,所有的rc腳本都是用這個shell來解釋執行。
選擇不同的啟動模式會導致下面的變量被賦值:
_boot
如果系統是自動運行,_boot=faststart
如果系統不是自動運行,_boot=start
這個變量的值會影響到後續的啟動過程
2、rc腳本系統的始祖 /etc/rc
# 初始化設置
stty status '^T'
# Set shell to ignore SIGINT (2), but not children;
# shell catches SIGQUIT (3) and returns to single user.
#
trap : 2
trap "echo 'Boot interrupted'; exit 1" 3
HOME=/
PATH=/sbin:/bin:/usr/sbin:/usr/bin
export HOME PATH
# 設置 _boot 變量的值
if [ "$1" = autoboot ]; then
autoboot=yes
_boot="faststart"
rc_fast=yes # run_rc_command(): do fast booting
else
autoboot=no
_boot="start"
fi
dlv=`/sbin/sysctl -n vfs.nfs.diskless_valid 2> /dev/null`
if [ ${dlv:=0} -ne 0 -o -f /etc/diskless ]; then
sh /etc/rc.initdiskless
fi
# Run these after determining whether we are booting diskless in order
# to minimize the number of files that are needed on a diskless system,
# and to make the configuration file variables available to rc itself.
# 包含 /etc/rc.subr,又見到“rc.subr“的蹤跡 :-)
. /etc/rc.subr
# 顯示提示信息,表示開始啟動系統rc腳本
echo "Loading configuration files."
# 調用 /etc/rc.subr 中的 load_rc_confg 參數是 XXX
# 調用 /etc/rc.subr 文件中定義的 load_rc_config 函數,參數是 name 變量的值。
load_rc_config 'XXX'
skip="-s nostart"
# jailed相關,目前還不太了解
if [ `/sbin/sysctl -n security.jail.jailed` -eq 1 ]; then
skip="$skip -s nojail"
if [ "$early_late_divider" = "mountcritlocal" ]; then
early_late_divider=NETWORKING
fi
fi
# Do a first pass to get everything up to $early_late_divider so that
# we can do a second pass that includes $local_startup directories
#
# rcorder根據這些腳本文件的關聯進行排序,為後面的循環加載 /etc/rc.d/目錄下腳本文件作准備
files=`rcorder ${skip} /etc/rc.d/* 2>/dev/null`
# 進入一個循環,對排序後的腳本文件,使用 _boot 變量的值(start,faststart)運行每一個rc腳本
# 跟蹤這個循環,可知服務程序的加載順序。
for _rc_elem in ${files}; do
run_rc_script ${_rc_elem} ${_boot}
case "$_rc_elem" in
*/${early_late_divider}) break ;;
esac
done
unset files local_rc
# Now that disks are mounted, for each dir in $local_startup
# search for init scripts that use the new rc.d semantics.
# 參數是 _boot變量的值(start,faststart)
case ${local_startup} in
[Nn][Oo] | '') ;;
*) find_local_scripts_new ;;
esac
files=`rcorder ${skip} /etc/rc.d/* ${local_rc} 2>/dev/null`
_skip_early=1
for _rc_elem in ${files}; do
case "$_skip_early" in
1) case "$_rc_elem" in
*/${early_late_divider}) _skip_early=0 ;;
esac
continue
;;
esac
run_rc_script ${_rc_elem} ${_boot}
done
echo ''
date
exit 0
3、小結:
FreeBSD系統提供的rc腳本系統由以下的部分組成
shell
/etc/rc
/etc/rc.d/
/usr/local/etc/rc.d/
整個rc腳本系統的核心是 /etc/rc.subr 和 rcorder 組成,籍由這個機制,很多的系統功能都是通過rc腳本運行起來的,例如 login 等等
《freebsd操作系統設計與實現》中文版中所提到的reorder應該就是rcorder,估計是排版錯誤。
系統啟動時自動運行特定的服務程序的大致流程是:
通過/etc/rc.subr提供的函數,使用 faststart或者start參數運行諸如 mysql-server這樣的腳本,啟動相關服務
六、FreeBSD的rc腳本系統總結
通過跟蹤整個rc腳本系統的運作,給我一個特殊的印象,一個不太恰當的比喻,rc腳本系統相當於系統內核和具體服務程序的黏合劑和管理中樞。有了rc腳本系統,磁盤檢查,用戶登錄等等服務才得以在系統中運行。
Copyright © Linux教程網 All Rights Reserved