logo  

运维备忘录

运维备忘录
作者: 陈安廉

摘要:软件开发进阶系列


linux开机启动


2022-01-10 10:24:53


一、关于/etc/init.d

     如果你使用过linux系统,那么你一定听说过init.d目录。这个目录到底是干嘛的呢?它归根结底只做了一件事情,但这件事情非同小可,是为整个系统做的,因此它非常重要。init.d目录包含许多系统各种服务的启动和停止脚本。它控制着所有从acpid到x11-common的各种事务。当然,init.d远远没有这么简单。(译者注:acpid 是linux操作系统新型电源管理标准 ;X11也叫做X Window系统,X Window系统 (X11或X)是一种位图显示的 视窗系统 。它是在 Unix 和 类Unix 操作系统 ,以及 OpenVMS 上建立图形用户界面 的标准工具包和协议,并可用于几乎已有的现代操作系统)。

    当你查看/etc目录时,你会发现许多rc#.d 形式存在的目录(这里#代表一个指定的初始化级别,范围是0~6)。在这些目录之下,包含了许多对进程进行控制的脚本。这些脚本要么以"K"开头,要么以"S"开头。以K开头的脚本运行在以S开头的脚本之前。这些脚本放置的地方,将决定这些脚本什么时候开始运行。在这些目录之间,系统服务一起合作,就像运行状况良好的机器一样。然而,有时候你希望能在不使用kill 或killall 命令的情况下,能干净的启动或杀死一个进程。这就是/etc/init.d能够派上用场的地方了!

    如果你在使用Fedora系统,你可以找到这个目录:/etc/rc.d/init.d。实际上无论init.d放在什么地方,它都发挥着相同的作用。

     为了能够使用init.d目录下的脚本,你需要有root权限或sudo权限。每个脚本都将被作为一个命令运行,该命令的结构大致如下所示:

     /etc/init.d/command 选项

     comand是实际运行的命令,选项可以有如下几种:

start

stop

reload

restart

force-reload

       大多数的情况下,你会使用start,stop,restart选项。例如,如果你想关闭网络,你可以使用如下形式的命令:

     

         /etc/init.d/networking stop

        又比如,你改变了网络设置,并且需要重启网络。你可以使用如下命令:

        /etc/init.d/networking restart

        init.d目录下常用初始化脚本有:

       

networking

samba

apache2

ftpd

sshd

dovecot

mysql

         当然,你可能有其他更多常用的脚本,这个取决于你安装了什么linux操作系统。

 二、关于/etc/rc.local

      rc.local也是我经常使用的一个脚本。该脚本是在系统初始化级别脚本运行之后再执行的,因此可以安全地在里面添加你想在系统启动之后执行的脚本。常见的情况是你可以再里面添加nfs挂载/mount脚本。此外,你也可以在里面添加一些调试用的脚本命令。例如,我就碰到过这种情况:samba服务总是无法正常运行,而检查发现,samba是在系统启动过程中就该启动执行的,也就是说,samba守护程序配置保证了这种功能本应该正确执行。碰到这种类似情况,一般我也懒得花大量时间去查为什么,我只需要简单的在/etc/rc.local脚本里加上这么一行:

          /etc/init.d/samba start

     这样就成功的解决了samba服务异常的问题。

 

 三、总结

         Linux是灵活的。正因为它的灵活性,我们总是可以找到许多不同的办法来解决同一个问题。启动系统服务的例子就是一个很好的佐证。有了/etc/init.d目录下的脚本,再加上/etc/rc.local这个利器,你可以放心的确保你的服务可以完美的启动和运行。



这个问题涉及到Linux初始化init系统,RHEL 5为SysVinit,RHEL 6为Upstart,RHEL 7为Systemd,为更好地解释这个问题,以下选取RHEL 5.x进行说明。


如流程图所示,RHEL的启动过程按步骤大致可以分为:

POST加电自检-->BIOS(Boot Sequence)-->加载对应引导上的MBR(bootloader) -->主引导设置加载其BootLoader-->Kernel初始化-->initrd—>/etc/init进程加载/etc/inittab


从加载BootLoader(RHEL下为Grub)开始,会发生以下事情.

1. 藉由Grub的管理,读取Kernel内核文件(/boot/vmlinuz),解压至主内存,利用内核的功能,进行第二次硬件检测(第一次发生在POST开机自检时)

2. 加载Initial RAM Disk(/boot/initrd),使之在内存中解压缩为根目录,kernel藉此完成驱动程序的加载,,最终释放虚拟文件系统,并挂载实际的根目录文件系统.

3. 在核心加载完毕,进行完硬件侦测与驱动程序加载后,内核会启动第一个进程/sbin/init, init进程将会读取/etc/inittab,在/etc/inittab中,大致规定了以下动作:

取得 runlevel 亦即默认运行等级的相关等级.

使用 /etc/rc.d/rc.sysinit 进行系统初始化

根据runlevel调用相关启动脚本,以启动相应的系统服务

其他一些系统设置,最终完成系统启动.


/sbin/init 最主要的功能就是准备软件运行的环境,包括系统的主机名称、网络配置、语系处理、文件系统格式及其他服务的启动等,而所有的动作都根据在/etc/inittab中的配置.


/etc/rc.d, 里面存放了rc.local, rc.sysinit, init.d, rcX.d (X包括0-6对应相对runlevel)


/etc/rc.d/init.d, 存放了各种系统服务的启动关闭的管理脚本,/etc/init.d是他的一个目录链接.


/etc/rc.d/rcX.d, 里面存放了一些脚本,脚本名字以K开头的,表示STOP动作,名字以S开头,表示Start动作,名称中的数字表示执行次序,数字越小表示越先执行.

/etc/rcX.d是他的目录链接,但事实上rcX.d下文件本身就是指向/etc/rc.d/init.d下脚本的链接文件.


/etc/rc.d/rc.local, 有一个链接文件,路径在/etc/rc.local,

系统根据runlevel启动完rcX.d中的脚本之后,会调用rc.local脚本,如果你有一个脚本命令不论在3和5都想开机启动,那么就添加与此,免去rc3.d和rc5.d分别增加启动脚本工作量.


启动过程每个不同的Linux发行版有些许的不同,参照ArchLinux的启动过程,简单描述如下:

1. Boot Loader(如Grub) 加载Linux内核镜像

2. Linux内核加载初始内存文件系统(intramfs),并执行/init进程,这是系统中的第一个进程。

3. 内核模块初始化完毕后,真正的物理文件系统加载,/sbin/init进程替换之前启动的/init进程。

4. init进程读取/etc/inittab,开始执行各种初始化脚本

下面是ArchLinux的启动脚本执行的过程(BSD-Style),和其他发行版有一定的区别

5. 首先执行的是/etc/rc.sysinit

6. 根据Run Level,执行/etc/rc.single(1或S)或者/etc/rc.multi(2-5),在这一步,就会执行/etc/rc.d下所有的脚本

7. 最后执行/etc/rc.local


ArchLinux的系统启动脚本是很简单,不像Redhat。不清楚其他的发行版启动过程,但是/etc/inittab文件应该是一样的功能,就是控制在不同的Run Level中如何进行系统脚本启动。