init解析及chkconfig:

init是Centos6系统的第一个进程,位于:/sbin/init

配置文件位于/etc/inittab:定义了系统启动的6个运行级别以及默认运行级别

# cat -n /etc/inittab 
 1# inittab is only used by upstart for the default runlevel.
 2#
 3# ADDING OTHER CONFIGURATION HERE WILL HAVE NO EFFECT ON YOUR SYSTEM.
 4#
 5# System initialization is started by /etc/init/rcS.conf    # 系统初始化使用的配置文件
 6#
 7# Individual runlevels are started by /etc/init/rc.conf    # 个人运行级别使用的配置文件
 8#
 9# Ctrl-Alt-Delete is handled by /etc/init/control-alt-delete.conf
10#
11# Terminal gettys are handled by /etc/init/tty.conf and /etc/init/serial.conf,
12# with configuration in /etc/sysconfig/init.
13#
14# For information on how to write upstart event handlers, or how
15# upstart works, see init(5), init(8), and initctl(8).
16#
17# Default runlevel. The runlevels used are:
18#   0 - halt (Do NOT set initdefault to this)
19#   1 - Single user mode
20#   2 - Multiuser, without NFS (The same as 3, if you do not have networking)
21#   3 - Full multiuser mode
22#   4 - unused
23#   5 - X11
24#   6 - reboot (Do NOT set initdefault to this)
25# 
26id:5:initdefault:    # 系统启动默认的运行级别


/etc/init目录下保存着inittab配置文件的分片配置文件

如上第5行,/etc/init/rcS.conf配置文件:

# more /etc/init/rcS.conf 
# rcS - runlevel compatibility
#
# This task runs the old sysv-rc startup scripts.
#
# Do not edit this file directly. If you want to change the behaviour,
# please create a file rcS.override and put your changes there.
start on startup
stop on runlevel
task
# Note: there can be no previous runlevel here, if we have one it's bad
# information (we enter rc1 not rcS for maintenance).  Run /etc/rc.d/rc
# without information so that it defaults to previous=N runlevel=S.
console output
pre-start script
for t in $(cat /proc/cmdline); do
case $t in
emergency)
start rcS-emergency
break
;;
esac
done
end script
exec /etc/rc.d/rc.sysinit    # 执行系统初始化脚本
post-stop script
if [ "$UPSTART_EVENTS" = "startup" ]; then
[ -f /etc/inittab ] && runlevel=$(/bin/awk -F ':' '$3 == "initdefault" && $1 !~ "^#" { print $2 }' /etc/inittab)
--More--(79%)


系统初始化脚本:/etc/rc.d/rc.sysinit,完成以下任务:

    1、激活udev和selinux;

    2、根据/etc/sysctl.conf文件,来设定内核参数;

    3、设定时钟时钟;

    4、装载键盘映射;

    5、启用交换分区;

    6、设置主机名;

    7、根文件系统检测,并以读写方式重新挂载;

    8、激活RAID和LVM设备;

    9、启用磁盘配额;

    10、根据/etc/fstab,检查并挂载其它文件系统;

    11、清理过期的锁和PID文件;


再看上面第7行,/etc/init/rc.conf配置文件:

# cat /etc/init/rc.conf 
# rc - System V runlevel compatibility
#
# This task runs the old sysv-rc runlevel scripts.  It
# is usually started by the telinit compatibility wrapper.
#
# Do not edit this file directly. If you want to change the behaviour,
# please create a file rc.override and put your changes there.
start on runlevel [0123456]
stop on runlevel [!$RUNLEVEL]
task
export RUNLEVEL
console output
exec /etc/rc.d/rc $RUNLEVEL    # 执行/etc/rc.d/rc对应某个运行级别的脚本


由此我们再看看/etc/rc.d/rc脚本的某些片段:

59# First, run the KILL scripts.    # 先执行KILL脚本
60for i in /etc/rc$runlevel.d/K* ; do    # etc下的rc对应运行级别.d下的以K开头的脚本
61
62# Check if the subsystem is already up.
63subsys=${i#/etc/rc$runlevel.d/K??}
64[ -f /var/lock/subsys/$subsys -o -f /var/lock/subsys/$subsys.init ] || continue
65check_runlevel "$i" || continue
66
67# Bring the subsystem down.
68[ -n "$UPSTART" ] && initctl emit --quiet stopping JOB=$subsys
69$i stop
70[ -n "$UPSTART" ] && initctl emit --quiet stopped JOB=$subsys
71done
72
73# Now run the START scripts.    # 现在执行START脚本
74for i in /etc/rc$runlevel.d/S* ; do    # etc下的rc对应运行级别.d下的以S开头的脚本
75
76# Check if the subsystem is already up.
77subsys=${i#/etc/rc$runlevel.d/S??}
78[ -f /var/lock/subsys/$subsys ] && continue
79[ -f /var/lock/subsys/$subsys.init ] && continue
80check_runlevel "$i" || continue
81    
82# If we're in confirmation mode, get user confirmation
83if [ "$do_confirm" = "yes" ]; then
84confirm $subsys
85rc=$?
86if [ "$rc" = "1" ]; then
87continue
88elif [ "$rc" = "2" ]; then
89do_confirm="no"
90fi
91fi
92
93update_boot_stage "$subsys"
94# Bring the subsystem up.
95[ -n "$UPSTART" ] && initctl emit --quiet starting JOB=$subsys
96if [ "$subsys" = "halt" -o "$subsys" = "reboot" ]; then
97export LC_ALL=C
98exec $i start
99fi
   100$i start
   101[ -n "$UPSTART" ] && initctl emit --quiet started JOB=$subsys
   102done
   103[ "$do_confirm" = "yes" ] && rm -f /var/run/confirm
   104exit 0

上面的脚本大致意思为,先按照etc下的rc对应运行级别.d下的以K开头的脚本按顺序(for循环)执行KILL(关闭K开头的服务),然后按照etc下的rc对应运行级别.d下的以S开头的脚本按顺序(for循环)执行START(开启S开头的服务)。例如,假如当前运行级别为5,那么表示在/etc/rc5.d/目录下以K开头的脚本按顺序关闭,S开头的脚本按顺序开启。


由此我们再看看/etc/rc5.d/下存放的脚本:

# ll /etc/rc.d/rc5.d
total 0
lrwxrwxrwx. 1 root root 15 Jun  3 19:32 K01numad -> ../init.d/numad
lrwxrwxrwx. 1 root root 16 Jun  3 19:32 K01smartd -> ../init.d/smartd
lrwxrwxrwx. 1 root root 17 Jun  3 19:30 K02oddjobd -> ../init.d/oddjobd
lrwxrwxrwx. 1 root root 16 Jun  3 19:32 K10psacct -> ../init.d/psacct
lrwxrwxrwx. 1 root root 19 Jun  3 19:30 K10saslauthd -> ../init.d/saslauthd
lrwxrwxrwx. 1 root root 17 Jun  3 23:08 K50dnsmasq -> ../init.d/dnsmasq
lrwxrwxrwx. 1 root root 20 Jun  3 19:29 K50netconsole -> ../init.d/netconsole
lrwxrwxrwx. 1 root root 13 Jun  3 19:30 K60nfs -> ../init.d/nfs
lrwxrwxrwx. 1 root root 20 Jun  3 19:30 K69rpcsvcgssd -> ../init.d/rpcsvcgssd
lrwxrwxrwx. 1 root root 17 Jun  3 19:29 K73winbind -> ../init.d/winbind
lrwxrwxrwx. 1 root root 14 Jun  3 19:30 K74ntpd -> ../init.d/ntpd
lrwxrwxrwx. 1 root root 18 Jun  4 03:14 K75cgconfig -> ../init.d/cgconfig
lrwxrwxrwx. 1 root root 17 Jun  3 19:30 K75ntpdate -> ../init.d/ntpdate
lrwxrwxrwx. 1 root root 19 Jun  3 19:32 K75quota_nld -> ../init.d/quota_nld
lrwxrwxrwx. 1 root root 16 Jun  3 19:30 K76ypbind -> ../init.d/ypbind
lrwxrwxrwx. 1 root root 24 Jun  4 03:14 K84wpa_supplicant -> ../init.d/wpa_supplicant
lrwxrwxrwx. 1 root root 15 Jun  3 19:30 K86cgred -> ../init.d/cgred
lrwxrwxrwx. 1 root root 21 Jun  3 19:29 K87restorecond -> ../init.d/restorecond
lrwxrwxrwx. 1 root root 14 Jun  4 03:14 K88sssd -> ../init.d/sssd
lrwxrwxrwx. 1 root root 15 Jun  3 19:29 K89rdisc -> ../init.d/rdisc
lrwxrwxrwx. 1 root root 22 Jun  3 23:08 K92pppoe-server -> ../init.d/pppoe-server
lrwxrwxrwx. 1 root root 14 Jun  3 19:32 K99rngd -> ../init.d/rngd
lrwxrwxrwx. 1 root root 17 Jun  3 19:32 S01sysstat -> ../init.d/sysstat
lrwxrwxrwx. 1 root root 22 Jun  3 23:11 S02lvm2-monitor -> ../init.d/lvm2-monitor
lrwxrwxrwx. 1 root root 19 Jun  3 19:30 S08ip6tables -> ../init.d/ip6tables
lrwxrwxrwx. 1 root root 18 Jun  3 19:29 S08iptables -> ../init.d/iptables
lrwxrwxrwx. 1 root root 17 Jun  3 19:29 S10network -> ../init.d/network
lrwxrwxrwx. 1 root root 16 Jun  3 19:32 S11auditd -> ../init.d/auditd
lrwxrwxrwx. 1 root root 21 Jun  3 19:28 S11portreserve -> ../init.d/portreserve
lrwxrwxrwx. 1 root root 17 Jun  3 19:30 S12rsyslog -> ../init.d/rsyslog
lrwxrwxrwx. 1 root root 18 Jun  3 19:32 S13cpuspeed -> ../init.d/cpuspeed
lrwxrwxrwx. 1 root root 20 Jun  3 19:32 S13irqbalance -> ../init.d/irqbalance
lrwxrwxrwx. 1 root root 17 Jun  3 19:28 S13rpcbind -> ../init.d/rpcbind
lrwxrwxrwx. 1 root root 19 Jun  3 19:30 S15mdmonitor -> ../init.d/mdmonitor
lrwxrwxrwx. 1 root root 15 Jun  3 19:32 S20kdump -> ../init.d/kdump
lrwxrwxrwx. 1 root root 20 Jun  3 23:06 S22messagebus -> ../init.d/messagebus
lrwxrwxrwx. 1 root root 24 Jun  3 23:08 S23NetworkManager -> ../init.d/NetworkManager
lrwxrwxrwx. 1 root root 17 Jun  4 03:14 S24nfslock -> ../init.d/nfslock
lrwxrwxrwx. 1 root root 17 Jun  4 03:14 S24rpcgssd -> ../init.d/rpcgssd
lrwxrwxrwx. 1 root root 26 Jun  3 23:06 S25blk-availability -> ../init.d/blk-availability
lrwxrwxrwx. 1 root root 14 Jun  3 19:29 S25cups -> ../init.d/cups
lrwxrwxrwx. 1 root root 15 Jun  3 19:29 S25netfs -> ../init.d/netfs
lrwxrwxrwx. 1 root root 15 Jun  3 19:32 S26acpid -> ../init.d/acpid
lrwxrwxrwx. 1 root root 19 Jun  3 19:29 S26haldaemon -> ../init.d/haldaemon
lrwxrwxrwx. 1 root root 19 Jun  3 19:29 S26udev-post -> ../init.d/udev-post
lrwxrwxrwx. 1 root root 16 Jun  3 19:30 S28autofs -> ../init.d/autofs
lrwxrwxrwx. 1 root root 14 Jun  4 05:51 S55sshd -> ../init.d/sshd
lrwxrwxrwx. 1 root root 17 Jun  3 19:30 S80postfix -> ../init.d/postfix
lrwxrwxrwx. 1 root root 19 Jun  3 19:30 S82abrt-ccpp -> ../init.d/abrt-ccpp
lrwxrwxrwx. 1 root root 15 Jun  3 19:30 S82abrtd -> ../init.d/abrtd
lrwxrwxrwx. 1 root root 15 Jun  3 19:30 S90crond -> ../init.d/crond
lrwxrwxrwx. 1 root root 13 Jun  3 19:29 S95atd -> ../init.d/atd
lrwxrwxrwx. 1 root root 15 Jun  4 03:14 S95jexec -> ../init.d/jexec
lrwxrwxrwx. 1 root root 20 Jun  3 19:30 S99certmonger -> ../init.d/certmonger
lrwxrwxrwx. 1 root root 11 Jun  3 19:29 S99local -> ../rc.local

可以看出,这些脚本实际上都是链接到父目录下的init.d里面的具体服务(也就是/etc/rc.d/init.d),/etc/rc.d/init.d(和/etc/init.d是一样的)下保存的都是各种服务的启动脚本。


由此我们看看一下服务启动脚本:

# cat -n /etc/rc.d/init.d/sshd
 1#!/bin/bash
 2#
 3# Init file for OpenSSH server daemon
 4#
 5# chkconfig: 2345 55 25
 6# description: OpenSSH server daemon
 7#
 8# processname: sshd

可以看出,所有启动脚本都会有第4和5行,这两行的内容是为了接受chkconfig命令的执行:

# chkconfig: 2345 55 25    # 2345表示启动级别,55表示START的次序,25表示在2345外的启动级别KILL的次序
# description: OpenSSH server daemon    # 简单描述信息


chkconfig命令:

chkconfig --add SERVICE_NAME     # 添加某项服务为开机启动

如:当执行chkconfig --add sshd时,chkconfig会搜索有以上5、6行内容的脚本,同时在rc2.d、rc3.d、rc4.d、rc5.d四个启动级别目录下都创建一个S55sshd的链接文件,表示在这四个启动级别下系统启动会在(执行完所有KILL后)第55个启动(START)这个服务;在剩下的rc0.d、rc1.d、rc6.d三个启动级别目录下创建K25sshd的链接文件,表示在这三个启动级别下系统启动会第25个关闭(KILL)这个服务。由此可见,执行chkconfig命令实际上是一个创建链接以实现在某个运行级别下自动开启在某个启动级别下自动关闭的过程。如下:

# ll `find /etc/rc.d/ -name "*sshd*"`
-rwxr-xr-x. 1 root root 1766 Jun  4 04:36 /etc/rc.d/init.d/sshd
lrwxrwxrwx. 1 root root   14 Jun  4 05:50 /etc/rc.d/rc0.d/K25sshd -> ../init.d/sshd
lrwxrwxrwx. 1 root root   14 Jun  4 05:50 /etc/rc.d/rc1.d/K25sshd -> ../init.d/sshd
lrwxrwxrwx. 1 root root   14 Jun  4 05:51 /etc/rc.d/rc2.d/S55sshd -> ../init.d/sshd
lrwxrwxrwx. 1 root root   14 Jun  4 05:51 /etc/rc.d/rc3.d/S55sshd -> ../init.d/sshd
lrwxrwxrwx. 1 root root   14 Jun  4 05:51 /etc/rc.d/rc4.d/S55sshd -> ../init.d/sshd
lrwxrwxrwx. 1 root root   14 Jun  4 05:51 /etc/rc.d/rc5.d/S55sshd -> ../init.d/sshd
lrwxrwxrwx. 1 root root   14 Jun  4 05:50 /etc/rc.d/rc6.d/K25sshd -> ../init.d/sshd

chkconfig [--level RUNLEVELS] SERVICE_NAME {on|off}     # 如果省略级别--level指定,默认为2345级别