2008年10月22日 星期三

使用/etc/init.d/rc 轉換runlevel

轉換規則如下所敘述:

1. scan /etc/rcX.d/ 和 /etc/rcY.d/ 下的scripts X表目前的runlevel Y表欲轉換的runlevel

2. 首先判斷目前的runlevel 是否為N ,若不是就依序實行/etc/rcY.d/下的stop scripts, 但在執行之前會先依下面規則過慮:

在 /etc/rcY.d/ 下的某一個script若在/etc/rcX.d/有對應的stop script但沒有start script則該script不執行。


3. 依序實行/etc/rcY.d/下的start scripts, 但在執行之前會先依下面規則過慮:

(1) 若ACTION==start

在 /etc/rcY.d/ 下的某一個script若在/etc/rcX.d/有對應的start script但沒有stop script則該script不執行。

(2) 若ACTION != start

在 /etc/rcY.d/ 下的某一個script若在/etc/rcX.d/有對應的stop script但沒有start script則該script不執行。

P.S.

(1)當表欲轉換的runlevel為0,6 ACTION=stop; runlevel為S或其他level, ACTION=start

(2)一般Debain系統開機是從N->2 關機是從2->0 重開機是從2->6

(3)我們可以由以下的 scripts來驗證我上面所說的事:

#! /bin/sh

previous=2 # current runlevel
runlevel=0 # next runlevel



export previous runlevel
case "$runlevel" in
0|6)
ACTION=stop
;;
S)
ACTION=start
;;
*)
ACTION=start
;;
esac

echo "ACTION:"$ACTION
echo

# First, run the KILL scripts.
if [ "$previous" != N ]
then
# Run all scripts with the same level in parallel
CURLEVEL=""
for s in /etc/rc$runlevel.d/K*
do
# Extract order value from symlink
level=${s#/etc/rc$runlevel.d/K}
level=${level%%[a-z]*}
if [ "$level" = "$CURLEVEL" ]
then
continue
fi
CURLEVEL=$level
SCRIPTS=""
for i in /etc/rc$runlevel.d/K$level*
do
# Check if the script is there.
[ ! -f $i ] && continue

#
# Find stop script in previous runlevel but
# no start script there.
#
suffix=${i#/etc/rc$runlevel.d/K[0-9][0-9]}
previous_stop=/etc/rc$previous.d/K[0-9][0-9]$suffix
previous_start=/etc/rc$previous.d/S[0-9][0-9]$suffix
#
# If there is a stop script in the previous level
# and _no_ start script there, we don't
# have to re-stop the service.
#
[ -f $previous_stop ] && [ ! -f $previous_start ] && continue

# Stop the service.
SCRIPTS="$SCRIPTS $i"
done
echo $SCRIPTS
echo
done
fi
echo
echo "-----------------------------------------------------------------"
echo
CURLEVEL=""
for s in /etc/rc$runlevel.d/S*
do
# Extract order value from symlink
level=${s#/etc/rc$runlevel.d/S}
level=${level%%[a-z]*}
if [ "$level" = "$CURLEVEL" ]
then
continue
fi
CURLEVEL=$level
SCRIPTS=""
for i in /etc/rc$runlevel.d/S$level*
do
[ ! -f $i ] && continue

suffix=${i#/etc/rc$runlevel.d/S[0-9][0-9]}
if [ "$previous" != N ]
then
#
# Find start script in previous runlevel and
# stop script in this runlevel.
#
stop=/etc/rc$runlevel.d/K[0-9][0-9]$suffix
previous_start=/etc/rc$previous.d/S[0-9][0-9]$suffix
#
# If there is a start script in the previous level
# and _no_ stop script in this level, we don't
# have to re-start the service.
#
if [ start = "$ACTION" ] ; then
[ -f $previous_start ] && [ ! -f $stop ] && continue
else
# Workaround for the special
# handling of runlevels 0 and 6.
previous_stop=/etc/rc$previous.d/K[0-9][0-9]$suffix
#
# If there is a stop script in the previous level
# and _no_ start script there, we don't
# have to re-stop the service.
#
[ -f $previous_stop ] && [ ! -f $previous_start ] && continue
fi

fi
SCRIPTS="$SCRIPTS $i"
done
echo $SCRIPTS
echo
done

沒有留言: