Linux 开机脚本启动顺序:
第一步:启动内核
第二步:执行init (配置文件/etc/inittab)
第三步:启动相应的脚本,执行inittab脚本,并且执行里面的脚本/etc/init.d rc.sysinit rc.d rc.local。。。
第四步:启动login登录界面 login
第五步:在用户登录的时候执行sh脚本的顺序:每次登录的时候都会完全执行的 /etc/profile /etc/bashrc /root/.bashrc /root/.bash_profile
inittab脚本:
init的进程号为1,是所有进程的父进程,内核初始化完毕之后,init程序开始运行。其他软件也同时开始运行。init程序通过/etc/inittab文件进行配置。
/etc/inittab文件每一行包括四个字段:label:runlevel:action:process。详细解释如下。
1.label
登记项标志符,是一个任意指定的、4个字符以内的序列标号,在本文件内必须唯一。
label是1到4个字符的标签,用来标示输入的值。一些系统只支持2个字符的标签。鉴于此原因,多数人都将标签字符的个数限制在2个以内。该标签可以是任意字符构成的字符串,但实际上,某些特定的标签是常用的,在Red Hat Linux中使用的标签是:
id 用来定义缺省的init运行的级别
si 是系统初始化的进程
ln 其中的n从1~6,指明该进程可以使用的runlevel的级别
ud 是升级进程
ca 指明当按下Ctrl+Alt+Del是运行的进程
pf 指当UPS表明断电时运行的进程
pr 是在系统真正关闭之前,UPS发出电源恢复的信号时需要运行的进程
x 是将系统转入X终端时需要运行的进程
2.runlevels
系统运行级,即执行登记项的init级别。用于指定相应的登记项适用于哪一个运行级,即在哪一个运行级中被处理。如果该字段为空,那么相应的登记项将适用于所有的运行级。在该字段中,可以同时指定一个或多个运行级,其中各运行级分别以数字0, 1, 2, 3, 4, 5, 6或字母a, b, c表示,且无须对其进行分隔。
0–>Halt,关闭系统.
1–>单用户,在grub启动时加上为kernel加上参数single即可进入此运行等级
2–>无网络多用户模式.
3–>有网络多用户模式.
4–>有网络多用户模式.
5–>X模式
6–>reboot重启系统
S/s–>同运行等级1
a,b,c–>自定义等级,通常不使用.
3.action
表示进入对应的runlevel时,init应该运行process字段的命令的方式,有效的action值如下。
boot:只有在引导过程中,才执行该进程,但不等待该进程的结束。当该进程死亡时,也不重新启动该进程。
bootwait:只有在引导过程中,才执行该进程,并等待进程的结束。当该进程死亡时,也不重新启动该进程。实际上,只有在系统被引导后,并从单用户模式进入多用户模式时,这些登记项才被处理;如果系统的默认运行级设置为2(即多用户模式),那么这些登记项在系统引导后将马上被处理。
initdefault:指定系统的默认运行级。系统启动时,init将首先查找该登记项,如果存在,init将依据此决定系统最初要进入的运行级。具体来说,init将指定登记项”run_level”字段中的最大数字(即最高运行级)为当前系统的默认运行级;如果该字段为空,那么将其解释为”0123456″,并以”6″作为默认运行级。如果不存在该登记项,那么init将要求用户在系统启动时指定一个最初的运行级。
off:如果相应的进程正在运行,那么就发出一个告警信号,等待20秒后,再通过关闭信号强行终止该进程。如果相应的进程并不存在,那么就忽略该登记项。
once:启动相应的进程,但不等待该进程结束便继续处理/etc/inittab文件中的下一个登记项;当该进程终止时,init也不重新启动该进程。在从一个运行级进入另一个运行级时,如果相应的进程仍然在运行,那么init就不重新启动该进程。
ondemand:与”respawn”的功能完全相同,但只用于运行级为a、b或c的登记项。
powerfail:只在init接收到电源失败信号时,才执行该进程,但不等待该进程结束。
powerwait:只在init接收到电源失败信号时,才执行该进程,并在继续对/etc/inittab文件进行任何处理前等待该进程结束。
respawn:如果相应的进程还不存在,那么init就启动该进程,同时不等待该进程的结束就继续扫描/etc/inittab文件;当该进程终止时,init将重新启动该进程。如果相应的进程已经存在,那么init将忽略该登记项并继续扫描/etc/inittab文件。
sysinit:只有在启动或重新启动系统并首先进入单用户模式时,init才执行这些登记项。而在系统从运行级1~6进入单用户模式时,init并不执行这些登记项。”action”字段为”sysinit”的登记项在”run_level”字段不指定任何运行级。
wait:启动进程并等待其结束,然后再处理/etc/inittab文件中的下一个登记项。
ctrlaltdel:用户在控制台键盘上按下Ctrl+Alt+Del组合键时,允许init重新启动系统。注意,如果该系统放在一个公共场所,系统管理员可将Ctrl+Alt+Del组合键配置为其他行为,比如忽略等。
4.process
具体应该执行的命令。并负责在退出运行级时将其终止(当然在进入的runlevel中仍要运行的程序除外)。当运行级别改变,并且正在运行的程序并没有在新的运行级别中指定需要运行时,那么init会先发送一个SIGTERM 信号终止,然后是SIGKILL。
实例分析
# /etc/inittab # # Copyright (C) 2001 Erik Andersen <andersen@codepoet.org> # # Note: BusyBox init doesn't support runlevels. The runlevels field is # completely ignored by BusyBox init. If you want runlevels, use # sysvinit. # # Format for each entry: ::: # # id == tty to run on, or empty for /dev/console # runlevels == ignored # action == one of sysinit, respawn, askfirst, wait, and once # process == program to run # Startup the system ::sysinit:/bin/mount -t proc proc /proc ::sysinit:/bin/mount -o remount,rw / ::sysinit:/bin/mkdir -p /dev/pts /dev/shm ::sysinit:/bin/mount -a ::sysinit:/sbin/swapon -a null::sysinit:/bin/ln -sf /proc/self/fd /dev/fd null::sysinit:/bin/ln -sf /proc/self/fd/0 /dev/stdin null::sysinit:/bin/ln -sf /proc/self/fd/1 /dev/stdout null::sysinit:/bin/ln -sf /proc/self/fd/2 /dev/stderr ::sysinit:/bin/hostname -F /etc/hostname # now run any rc scripts ::sysinit:/etc/init.d/rcS # Put a getty on the serial port #console::respawn:/sbin/getty -L console 0 vt100 # GENERIC_SERIAL console::respawn:-/bin/sh # Stuff to do for the 3-finger salute #::ctrlaltdel:/sbin/reboot # Stuff to do before rebooting ::shutdown:/etc/init.d/rcK ::shutdown:/sbin/swapoff -a ::shutdown:/bin/umount -a -r
下面是启动文件rcS文件内容:脚本/etc/init.d/S[0-9][0-9]* 会依次运行
#!/bin/sh
# Start all init scripts in /etc/init.d
# executing them in numerical order.
#
for i in /etc/init.d/S??* ;do
# Ignore dangling symlinks (if any).
[ ! -f "$i" ] && continue
case "$i" in
*.sh)
# Source shell script for speed.
(
trap - INT QUIT TSTP
set start
. $i
)
;;
*)
# No sh extension, so fork subprocess.
$i start
;;
esac
done
#cd /usr/sbin
#./dropbear
#cd /
ls /etc/init.d/ 从rcS 可以看出所有脚本会根据脚本名字排序依次执行,注意rcK是反序;并且rcS 启动参数是start rcK 参数是stop
S01syslogd S10mdev S40network S80mount-opt rcK S02klogd S20urandom S50dropbear S90startApp rcS
S10mdev 热插拔支持
#!/bin/sh # # Start mdev.... # #mount -t tmpfs none /media #这个是方对media的处理 我认为有问题,因为这个脚本在系统启动/重启 都会调用,而且也只有这2个时候会调用 case "$1" in start) echo "Starting mdev..." echo /sbin/mdev >/proc/sys/kernel/hotplug #确保系统每次有热插拔设备都会调用"/proc/sys/kernel/hotplug"这个命令 /bin/rm -rf /media/* #在热插拔挂载前先删除文件夹 /bin/rm -rf /mnt/sdcard #在热插拔挂载前先删除文件夹 /sbin/mdev -s #开机进行一次热插拔处理 注意看mdev.conf配置文件 # coldplug modules find /sys/ -name modalias -print0 | xargs -0 sort -u | tr '\n' '#!/bin/sh # # Start mdev.... # #mount -t tmpfs none /media #这个是方对media的处理 我认为有问题,因为这个脚本在系统启动/重启 都会调用,而且也只有这2个时候会调用 case "$1" in start) echo "Starting mdev..." echo /sbin/mdev >/proc/sys/kernel/hotplug #确保系统每次有热插拔设备都会调用"/proc/sys/kernel/hotplug"这个命令 /bin/rm -rf /media/* #在热插拔挂载前先删除文件夹 /bin/rm -rf /mnt/sdcard #在热插拔挂载前先删除文件夹 /sbin/mdev -s #开机进行一次热插拔处理 注意看mdev.conf配置文件 # coldplug modules find /sys/ -name modalias -print0 | xargs -0 sort -u | tr '\n' '\0' | \ xargs -0 modprobe -abq ;; stop) ;; restart|reload) ;; *) echo "Usage: $0 {start|stop|restart}" exit 1 esac exit $?' | \ xargs -0 modprobe -abq ;; stop) ;; restart|reload) ;; *) echo "Usage: $0 {start|stop|restart}" exit 1 esac exit $?
下面是rcK文件内容:
#!/bin/sh # Stop all init scripts in /etc/init.d # executing them in reversed numerical order. # for i in $(ls -r /etc/init.d/S??*) ;do # Ignore dangling symlinks (if any). [ ! -f "$i" ] && continue case "$i" in *.sh) # Source shell script for speed. ( trap - INT QUIT TSTP set stop . $i ) ;; *) # No sh extension, so fork subprocess. $i stop ;; esac done