第七十讲——攒系统之外的杂项 我们可能已经能够将攒的小linux在虚拟机上挂载启动了,看着启动起来的界面是不是感觉也不是那么难?我们在复制命令及其依赖的库文件时是不是觉得太繁琐了,实在是辛苦,当然写个脚本也是能够代替手工操作的,以之前的脚本功底按理说实现起来并不复杂。 那么接下来就介绍一个逆天的工具,其实也不是工具,是一个程序,叫buybox,这个程序能够实现多个命令的操作,仅依靠一个二进制的程序,听起来是不是很厉害的样子? 我们下载buybox并安装,进入/bin下有许多的连接文件,这些链接文件名称都是系统中的命令,且都指向buybox,也就是说名字不一样功能也就不一样,实在是厉害。 所以我们完全可以使用buybox+内核搭建一个平台,也就是说,我们可以使用buybox做成一个initrd文件,即虚拟根文件系统,再使用buybox来作为真正的根文件系统+kernel,但是buybox上面没有bash,但是我们可以移植过去,busybox自带的shell有ash和hash。 查看本机的硬件信息: cat /proc/cpuinfo lsusb列出本机的usb属性信息 lspci 显示出pci总线的所有设备类型 hal-device更为详细的硬件信息 Hardware Abstract Layer硬件抽象层 驱动可以做进内核,也可以做成模块,一般来说核心硬件,如硬盘驱动最好做进内核,而网卡驱动一类做成模块。 内核的编译: 一配置: #make menuconfig #make gconfig #make kconfig 二编译整个内核 #make 三模块的安装位置/lib/mudles/KERNEL_VERSION #make install 四是安装 make install 我们可能会遇到当编译完内核后,还需要添加模块,这个时候我们只需要编译一个模块或者一个目录,即实现部分编译。 一是只实现编译某子目录下的相关代码 #make /dir(指定相应的目录即可) 在我们解压内核后会看到arch目录,此目录下为根硬件平台相关的内核核心,但是在编译核心时也会编译模块,因为我们选择了哪些模块以及内核支持哪些模块,核心得知道,核心会将模块遍历一遍,可能不会安装或者编译。 二是只编译部分模块 make /device/net 三是只编译某一模块 make */device/net/pcnet32.ko 四是将编译完成的结果放到别的目录 make o=/tmp/kernel 编译buybox,同内核编译。 make menuconfig make make install 交叉编译:用A平台编译非A平台上的程序的方式叫做交叉编译。 bash特性: 变量的默认赋值: 当一个变量为空或者不存在时(用户没有从键盘上输入),我们可以这么操作: ${A:-30}即当$A存在且不为空时为$A中的值,否则将30赋值给$A ${A:+30} 与-相反,如果A不空使用后面的值,如果A为空,则A为空。 ${parameter:+word} 如果parameter未定义或者为空,则变量展开为word的值,并将展开后的值赋值给parameter 变量的切片: ${A:3:4}表示截取变量A略过前三个字符后,截取四个字符,截取字段可以省略,表示至末尾字符。 3:略过几个字符 4:截取几个字符 我们知道服务脚本是支持配置文件的,一般说来服务脚本位于/etc/rc.d/init.d下,配置文件位于/etc/sysconfig下 服务脚本的配置文件一般与服务脚本同名 局部变量,使用local进行定义,只在函数中有效。 #mktmp 用于创建临时文件或目录 #mktmp /tmp/file.## ##为随机生成的数值,该命令的返回值为一个文件的路径。 #mktmp –t 创建一个临时目录。 信号:进程间通信的一种方式 kill –SIGNAL PID 1 HUP 2 INT 9 KILL 15 TERM 我们在脚本中可以实现(9、15)信号外的信号捕捉 ctrl + c 发送的是2号信号 在脚本内部使用trap命令进行命令的捕捉 trap ‘COMMAND’(执行的命令)信号列表(需要捕捉的信号列表) 一行中执行多个语句时使用分号分隔即可。 当我们退出时需要执行很多的操作,此时我们可以定义一个函数,将一些创建的临时文件删除,或其它保护操作。 给自己讲linux 2017-02-08 评论 1894 次浏览
第六十九讲——手动攒系统(二) 当我们攒完一个小系统后,添加所需要的命令,但是我们经过尝试使用halt、init命令并不能实现关机、重启,原因是我们使用halt –p/init 0都是先进行运行级别的切换,再执行对应级别下的脚本,K##、S##等等,所以执行halt命令并不能在命令行下关机。 exec halt –p使用exec后指令替换父进程,然而exec helt –p也不能完成在新攒的系统上关机。 因此我们需要将脚本写入对应级别下,并在inittab文件中声明级别。 10:0:wait:/etc/rc.d/rc.sysdone(脚本名字随意,自己要能够看懂) 我切换级别的时候,应该是先将对应级别下K开头的stop掉,S开头的脚本start起来。 在我们攒系统的过程中因为硬盘的同步可能不是实时的,我们使用sync命令同步数据到硬盘,否则会因为数据不全或者文件系统中的inod号异常而造成文件系统崩溃。当文件系统损坏时,我们应当进行修复,修复之前应当先将所有文件打包存放到其他地方。 首先cd到损坏的文件系统中 find . |cpio –H newc –quit –o |gzip -9>/root/sysroot.gz 卸载损坏的文件系统,umount 挂载点 修复文件系统,其实也就是重新格式化文件系统 mke2fs –j /dev/sd# 重新挂载文件系统到指定的挂载点,mount命令实现挂载,不再赘述。 cd 进入修复好的文件系统中,将打包的文件还原回来 zcat /root/sysroot.gz |cpio –id 展开归档后继续重新以新的硬盘作为启动盘尝试启动攒的linux系统。 在红帽系列系统启动时,如果服务正确启动,我们会看到显示绿色的OK字样,如果服务启动失败,则显示FAIL红色,且总是显示在行末,其实现的机制为输出打印时计算屏宽。 例如: A=”12346” echo ${#A}在变量名前加#,取变量中所包含字符串的长度。 ${#VARNAME},使用此特性计算[ok]/[fail]字符的长度。 stty –F /dev/console size 显示物理终端的屏幕大小 输出为25 80 25行 80列(又叫屏宽) 使用屏宽减去字符的长度得到空格的长度,然后将[OK]/[FAIL]追加在行末。 当我们在脚本中调用一个文件中定义的函数的时候,得先装载,装载的方法为: . /path/to/function_name(函数所在目录) 函数文件在头部不用声明魔数,即!#/bin/bash等等 我们在登录操作系统后,会发现下面会有一些打印的信息,这些信息实际上是从一个文件中读取的并输出的,这个文件为/etc/isue,而内核在使用这个文件的时候并不是全部打印,因为在/etc/issue文件中存在逃逸字符,例如\r、\m分别代表uname –r、uname –m,这是由mingetty调用完成的。 #man mingetty可以查看到在/etc/issue文件中支持的逃逸字符。/etc/issue为终端的提示信息,在要求用户登录时显示,也可以使用mingetty指定显示。 grub.conf(/boot/grub/) ############## timeout=5 title linuxhobby.top root (hd0,0) kernel /vmlinuz ro root=/dev/hda#(指定根的位置) quiet(静默模式) 内核的初始化信息 ############## 我们需要知道的是,我们在操作系统启动起来之后看见的登录界面是由login程序所提供的页面。 login也可以实现用户的验证,在编译login时需要依赖pam模块,pam是红帽验证用户的插入式模块,对于系统来说,认证用户是到特定的位置实现的,这个特定的位置就是/etc/passwd、/etc/shadow。 而实际上,操作系统并不是这么工作的(直接访问passwd、shadow文件),我们的用户账号是放在别的位置,例如放在NIS、LDAP、MYSQL数据库中,只是我们传统是放在这两个文件当中。 这也就意味着我们在编译login程序时,将其直接连接到/etc/passwd、/etc/shadow文件,这样一来我们想要变更认证方式就变得比较困难,所以在/etc/passwd、/etc/shadow文件之间有一个中间层(nsswitch) nsswitch:network service switch网络服务转换/切换 nsswitch是一个柜架,它能够完成到哪儿去找用户的账号密码,在我们想要变更认证方式的时候,只需要修改/etc/nsswitch.conf即可实现。 nsswitch实现的功能叫做网络服务转换,也叫做名称解析开关,它只是定义了名称解析是如何工作的:用户的名称转换成ID号,将用户的组名转换成ID号,将主机名转换成ID号。 nsswitch既然是一个服务(程序),那么就可能会依赖库文件,nsswitch依赖的库文件都是以libnss开头的,32位的操作系统存在/lib下,64位存在于/lib64.在/usr/lib(64)下也存在库文件。 我们在攒一个操作系统的时候,需要将必须的库文件复制过去,nsswitch中间层所需要的库文件也是。 /lib(64)/libnss* files(链接文件) 指定、/etc/passwd、/etc/passwd的位置 在复制时保留链接文件使用-d选项 cp –d 复制链接时,保持连接属性。 我们在执行mingetty程序的时候,mingetty会启动一个终端,在启动终端后再在这个终端上执行一个login的程序(打印登录提示符) --loginprog=/bin/login默认调用的登录程序,我们可以定义/bin/bash让其直接执行bash程序 mount –n –o remount,rw /将根重新挂载为读写 stty –F /dev/console speed 显示当前显示器的速率,显示器属于线性设备,一般为38400. e2fsck –f /dev/sd# 强制检查文件系统,检查文件系统是相当耗费资源的,所以在服务器上一般将自动检查文件系统关闭,避免服务器瞬间超负荷运转。 小技巧: 在虚拟机中添加一块SCSI硬盘不能被立即识别的办法(重启一般能够解决) #cd /sys/class/scsi_host/ ls当前目录会发现有几个或一个以host#开头的文件,我们向其中echo一句话 #echo “- - -” >host#/scan 此时我们使用fdisk –l查看会发现scsi类型的硬盘已经显示出来了。 给自己讲linux 2017-02-07 评论 1868 次浏览
第六十八讲——手动攒linux系统 当我们自己攒一个系统的时候,我们需要拿一块硬盘,先对其分区,boot应单独分区,避免空间使用殆尽操作系统无法启动,在分区上应有根目录,且要有/boot目录(挂载点的名称),分区好之后将分区挂载到对应的目录。 根目录下应有: /sbin、/bin、/etc、/var、/tmp、proc、/sys、/dev、/lib、/usr、/home 在目录建立好之后,我们应对硬盘安装grub引导程序,用于引导操作系统、 安装grub:grub-install –root-directory=/tmp /dev/sd# 我们把init程序及其依赖的库文件拷贝到对应目录。 将/boot/vmlinuz...cp到挂载点为*/boot的目录下,接下来生成initrd脚本。 对于rhel5来说,生成initrd的命令为mkinitrd 对于rhel6来说,生成initrd的命令为dracut,当然,也是支持mkinitrd命令的。 #mkinitrd initrd文件路径 #mkinitrd /boot/initrd-`uname -r`.img`uname -r`为当前系统创建initrd文件,uname –r调用的是当前系统的内核版本。我们需要注意的是,此命令不能对我们新的内核创建 initrd文件,所以我们需要将/boot/目录下的initrd-*.img文件展开进行修改,而后再组装起来,我们先拷贝一份initrd文件。 此init文件是一个压缩格式的文件,在拷贝时注意添加上.gz的后缀,使得解压缩时程序能够识别,我们可以使用file命令查看initrd文件的类型,可以看到是gzip格式的文件。 我们使用gzip –d将initrd文件进行解压缩,再次使用file命令查看initrd文件,会发现这是一个cpio类型的文件,这是一个比较古老的归档格式,我们还需要对其进行展开,为了避免展开后产生小文件,我们应当在目录中进行展开。在展开cpio类型的文件时,我们使用的是cpio命令。 cpio –id -i 进入copy-in模式,也就是解压缩模式 -d 在需要的地方创建开始目录。 在展开之后我们会发现有很多的目录,和根目录下的目录结构相似,简直就是一个linux操作系统,在对initrd文件进行操作的时候我们可以简化操作: zcat /boot/initrd-*.img |cpio –id 不解压缩查看压缩包的内容,并将其送给cpio命令,此命令只能解压到当前目录下。 我们需要编辑init文件(nash脚本),rhel5中init页末有指定根的位置,在修改完之后我们还需要对文件进行归档(cpio归档),依旧是在当前目录下对所有的文件进行归档: find . |cpio –H newc –quiet –o |gzip -9>/tmp/boot/initrd.gz -H newc 指定类型 --quiet 静默模式 -o 归档 gzip -9指定压缩比 并定向到指定目录下。 在sysroot挂载点目录下创建必要的目录(根目录下的文件) cd /path/to/somewhere mkdir –p /sbin /bin /lib /proc /sys /usr/{sbin,bin}/var/log /etc/rc.d /boot /dev /tmp 在创建完目录后,我们将常用的程序以及依赖的库文件cp到对应的目录下。 我们使用ldd查看对应程序所依赖的库文件,并将这些文件cp到lib目录下。 在正常的操作系统下有/etc/inittab文件,因此我们需要手动创建并写入几句: id:3:initdefault 设置默认的启动级别 我们可以将需要开机启动的脚本或者程序写入rc.local中,因为rc.local是最后启动的一个脚本。 我们在拷贝一个命令的时候,如果不知道命令的位置在哪里,我们可以使用which命令 #which COMMAND 查看命令的位置 #ldd COMMAND 查看命令所依赖的库文件。 bash的特性: 在刚才我们在mkdir命令中使用到了花括号展开{},这是bash的特性,其实bash的特性还有很多。为了使应用程序及其所依赖的库文件能够快速复制,我们应当写成脚本的形式,为了更方便的操作,我们需要介绍一下一个bash特性,距离来说明。 FILE=/etc/rc.d/rc/local echo ${FILE#/} 输出的结果为etc/rc.d/rc.local #号后为指定的关键字,关键字左边的内容会被统统去除。 echo ${FILE##*/} 输出的结果为rc.local ##*表示最后一次关键词左边的内容全部去除,包括关键字本身。 “#”以指定的字符为分隔符,从左向右第一次匹配到的字符串内容去除。只保留第一次匹配之后的字符串。 这个方法常用来取出一个文件的名称,我们还可以使用一种方法来提取一个文件的目录 %:从右向左去除关键字后的内容。 FILE=/tmp/1/2/3/4/5 echo ${FILE%/*} 输出结果为/etc/rc.d 即取得了一个文件的目录。 echo ${FILE%%/*}输出结果为空行,%%为最后一次匹配。 “%”以指定的字符为分隔符,而后从右往左第一次匹配到的字符串内容移除,只保留第一次匹配之前的字符串 为了实现手动攒系统的目的,我们还需要继续弄清楚系统的启动流程: POST加电自检,将ROM中的程序映射到内存中,以实现硬件的检 -->BIOS(boot sequence)引导程序,根据BIOS启动顺序去找到对应存储设备上的MBR,MBR存在则寻找MBR中的boot loader,boot loader中配置了所需要引导的操作系统的位置,当boot loader载入内存时,BIOS会将系统的控制权限移交给boot loader,boot loader会依靠配置寻找操作系统的内核(根据用户的选择),将内核装载进内存并解压缩,内核完成初始化后将权限移交内核。 -->kernel(initrd,initramfs) 内核初始化完成的工作: 一是硬件探测 二是装在驱动,借助initrd或者initramfs过渡到根 三是挂载根文件系统(rootfs) 四是启动用户空间中的第一个进程init initrd或者initramfs可以实现将真正的根文件系统同内核连接起来 -->执行init,配置文件为/etc/inittab,在红帽6上init不再是传统意义上的init,而是一个被称为upstart的程序,为了兼容还是命名为init upstart的配置文件为/etc/inittab、/etc/init/*.conf init完成的工作主要取决于/etc/inittab文件 一是设定默认的运行级别 二是系统初始化的脚本rc.sysinit 三是启动指定级别的服务脚本 /etc/rc.d/init.d/* 使用ln –s链接到/etc/rc.d/rc#.d,即0-6各级别下,链接文件以K/S开头 四是启动虚拟终端,如果运行级别为init5,还需要启动图形终端 以上就是init的工作 -->执行/etc/rc.d/rc.sysinit(系统初始化脚本),系统初始化完成的任务,我们再次强调,内核在装载根文件系统时为了避免根文件系统的损坏,是以只读方式挂载的。 第一步此脚本会检测并且以读写的方式重新挂载根文件系统 第二步是设置主机名 第三步是挂载文件系统,需要挂载的文件系统定义在/etc/fstab配置文件中,以实现开机自动挂载 第四部启用swap分区 第五步可能需要装载外围硬件设备驱动,内核的初始化只加载最核心的设备驱动(CPU内存等),网卡、显卡等设备都是在init的执行过程中完成驱动的。 第六步根据/etc/sysctl.conf设定内核参数 第七部激活udev、SElinux 第八步激活lvm、RAID设备 第九步清理过期的锁文件和PID文件 第十步装载键映射(键盘上的每一个键的具体功能) 给自己讲linux 2017-02-06 评论 1801 次浏览
第六十七讲——内核的编译 在内核中,除了最核心的功能不能选择,需要做进内核外,其它的大多数功能在编译的时候都有三种选择: 一是不使用此功能 二是编译成内核模块 三是编译进内核文件,即成为内核的一部分。 编译内核: 红帽系列有一个特性,即在5.x、6.x时使用的都是同一内核,如果我们突然将内核升级到最新,可能会造成不兼容,所以内核的升级一定要慎重。 编译内核需要安装所需的工具: development tools development libraries 下载内核文件并解压缩,一般下载的为源码包。 tar –xf linux-2.6.23.10.tar.gz –C /usr/src指定解压缩目录为/usr/src,/usr/src下为源码 内核解压后是源代码,内核的编译不能像编译软件那样config,因为内核的编译选项非常的多,解压后我们需要创建一个链接文件,一般来说,我们当前使用的内核或当前编译的内核为linux,类似于将解压后的目录改名为linux。 切换到linux目录下: */arch/ 目录下为各类平台 */mm/ 内存管理 */net/ 和网络功能相关 */virt/ 虚拟化的相关功能 /kernel/ 内核相关 /ipc/ 进程间通信 /documentation/文件 应当看一看,在后期深入学习linux时应当学习。 手动编译内核提供了两种方式选择内核的特性: 一是编译时图形环境下内核特性的选择 make gconfig make gconfig为Gnome桌面环境 makekconfig make kconfig 为KDE桌面环境 需要安装图形开发库: GNOME software development(GNOME环境) KDEsoftware development(KDE桌面环境) 需要依赖桌面环境,所以并不是很常用。 二是命令行界面下的操作: 我们在命令行下使用较多,所以在命令行下的操作方式 make menuconfig:打开一个图形的文本窗口,这个窗口必须要能够容纳19行,80列,否则就会报错—>#least 19 lines by 80 columns 我们使用uname –r会发现除了内核的版本还有一长串的字符,这一串字符为本地版本号,我们在make menuconfig弹出的菜单中general setup中有一项local version即为设置此版本号。 在弹出的图形选择界面上使用空格进行选择项的切换,M表示做成模块,*表示做进内核。在选择结束后会询问是否保存,若保存则会在当前目录下生成.config的隐藏配置文件。接下来的编译就和其他软件一样了。 一是执行make,此过程出错的可能性很大,我们可以借助红帽公司的模板/boot/config,在此基础上进行修改,cp到解压缩的目录下更名为.config。 下载内核源码包 tar –xf ./linux /usr/src/ cd /usr/src ln –sv linux.. linux cd linux cp /boot/config ./.config make menuconfig 等待make等待编译结束 make modules-install先安装模块 make install 当安装结束后需要重启操作系统,在引导界面有内核的选择(在内核安装完成后,会自动将信息写入grub) 我们在编译内核时,一定不要使用远程连接,一旦连接中断编译过程也就中断。如果非要使用远程编译内核,我们可以安装screen工具,这个工具可以模拟很多个窗口。 yum install screen 当中断连接断开,重新登录即可,使用screen –ls可以查看模拟的窗口。 我们使用screen –r ID 返回窗口。 screen –ls 显示已经建立的窗口 screen –r ID 还原回某屏幕 ctrl+a,d拆除当前屏幕(类似后台) screen 建立一个新的屏幕 exit退出 二次编译时需要清理之前的编译。 make clean清理之前编译好的二进制模块 make mrproper清理此前编译的任何操作,包括.config也会被清理,在make mrproper清理之前,应当备份配置文件。 我们也可以只编译内核中的一部分,甚至可以只是一个目录。 给自己讲linux 2017-02-05 评论 1894 次浏览
第六十六讲——linux启动(内核) 我们从之前讲过的只是可以知道,内核是由两部分组成的: 核心:位于/boot目录下,/boot/vmlinuz-version(版本号) 内核模块(KO):/lib/modules/version/以版本号命令的目录 内核的设计有两种风格: 单内核:模块化设计(采用了微内核的思想) 微内核 模块化设计的好处是缩小内核的体积,在需要时才将模块载入内核,装载内核的命令: insmode modprobe 内核版本的区分: 主版本号.次版本号.修正号 次版本号为奇数时为测试版,此版本为偶数时为稳定版 但是在2.6.*以后的区分不同。 每一个版本出来后会有两个分支,稳定版本的编号为2.6.*.*多一个次修正号,为了方便记忆这么理解。 测试版的编号为2.6.*+1-rc* 如果测试版的编号从2.6.*+1-rc.1----2.6.*+1-rc.5如果rc..5稳定以后,则发行下一个版本,下一个版本再分为两个分支。 我们在服务器上应当选择稳定版,我们可以使用uname –r查看内核的版本。 内核虽是运行在内核空间,但是我们用户是可以跟内核打交道的,用户空间访问和监控内核的方式是通过两个目录完成。 /proc /sys 用户空间通过执行一些命令进行修改/proc、/sys目录下的某个文件来完成的。 /proc、/sys目录下的文件通常为内核中某个参数的映射,对于/proc目录来说,目录下的大多数文件为只读,对于/sys目录来说,/sys目录下的大多数文件是可以读写的。这就意味着我们可以修改文件中的内容,以达到修改内核运行特性。但是对于这类文件我们不能使用vim编辑器,而是使用echo重定向的方式写入。 设定内核参数的方法: echo 1 >/proc/sys/vm/drop_caches清空缓冲和缓存。 sysctl –w vm.drop_caches=1 sysctl –w *=value(参数) sysctl –w所指定的对象在/proc/sys目录下,且文件与文件父目录之间使用点隔开,这两种方式能立即生效,但是不能永久有效,需要永久有效需要写入配置文件。 我们可以将需要修改的参数写进/etc/sysctl.conf文件中,语句的格式类似sysctl命令,为sysctl –w所指定的部分。 即vm.drop_caches=1的格式 sysctl –w默认指定的是/proc/sys/目录下的文件,命令中目录使用点‘.’作为分隔符。 sysctl –p 通知内核重新读取/etc/sysctl.conf配置文件。 sysctl –a显示所有内核参数,及其值,这些参数并不是所有的都能够修改,而且每个参数的值和范围不一样。 /proc/sys/net/ipv4/ip_forward 当这个参数启用(为1时),如果本机有两块网卡,当一块网卡出现ping不通的情况时,会将数据通过另一张网卡进行发送。 也就是说/proc/sys/net/ipv4/ip_forward的值为1时,本机充当网关,将故障网卡的信息进行收发。 我们来说一说调优的几个参数,调优其实就是通过/proc、/sys目录下的内核参数映射文件来进行调整参数,调优都是通过访问这些接口完成的。 /proc/sys/kernel/hostname 修改主机名 /proc/sys/vm/drop_caches 清空缓存 /proc/sys/net/ipv4/ip_forward 是否允许本机充当路由。 内核的模块管理: #lsmod 查看,显示已经装载的模块,分为三列:moudle(模块名称) size(模块大小) used by(被调用了几次,由谁调用) #modprobe MOD_NAME:装载模块 #modprobe –r MOD_NAME:卸载模块(从内核上拆除),手动实现内核模块的装载,卸载。 #modinfo MOD_NAME:查看内核模块信息,其中有一列为depends(依赖关系,所依赖的模块名称) #insmod /PATH/TO/MODULE_NAME 装载内核模块,使用insmod装载模块时,必须要指定文件路径。 #rmmod MOD_NAME 卸载模块,卸载模块时无需指定路径 #depmod /PATH/TO/MODULES_DIR 指定模块的存放路径,并生成模块间的依赖关系,生成后会保存在对应目录下,使用不多。 如果有一个硬件设备没有驱动,则需要我们到官网去下载源代码手动编译成ko的模块,放在/lib/modules/下,且内核模块要与内核完全匹配,否则不能运行。即2.6.32-1的内核只能在2.6.32-1上编译驱动。 给自己讲linux 2017-02-04 评论 1917 次浏览
第六十五讲——kernel初始化的过程 一是设备探测 二是驱动初始化(从initrd文件中装在驱动模块) 三是以只读方式挂载根文件系统,为了文件系统的安全选择只读挂载,避免写入或者损坏数据。 四是装在第一个PID为1的进程:init。 在第三步以只读方式挂载,避免了BUG影响整个根文件系统,当装载完成后由init重启文件系统为读写。 /sbin/init (/etc/inittab) 早先这个init可能是一个脚本,也可能是一个二进制程序,但是在rhel6.0之后,使用的就不再是传统的Unix init了。 在6.0之后,使用的是upstart,但是名称依然是init,另一个版本的init(可执行程序)。 upstart由Ubuntu组织开发,upstart可以实现并行的启动进程,但是有些服务是有依赖关系的,这些依赖关系各自都有体现。 upstart的配置文件/etc/inittab只有一行,因为upstart使用d-bus进行通信,所以不再需要各种指定的子系统。(IPC机制,进程间通信,实现事件驱动基于d-bus各子系统之间的通信) 理解init的工作机制有助于理解其他类型的机制,所以先讲一讲6.0之前的inittab。 /etc/inittab 由三个冒号分隔为四段: 首先是id,标识符,区分不同的行 其次是runlevels,在哪些级别下会执行此命令。 接下来是action,采取的动作,即什么时候启动进程。 最后是process,执行的进程,即需要运行的程序。 id:runlevels:action:process 所以/etc/inittab中每一行都代表一个要启动的进程。 省略级别则表示所有级别生效。 id::sysinit:/etc/rc.d/rc.sysinit 系统的初始化脚本:rc.sysinit ACTION: initdefault:设定默认的运行级别 sysinit:系统的初始化 wait:等待级别切换,级别切换一次就执行一次,但是只是在切换到指定级别时执行。 respawn:重新启动,可能会启动多次,一旦程序终止会重新启动(指定级别下) 下面来说一说系统初始化脚本/etc/rc.d/rc.sysinit的任务: 系统初始化执行的脚本位于/etc/rc.d/rc.sysinit,此脚本间隙详细阅读,前两百行可以略过。 一是激活udev和SELinux 二是根据/etc/sysctl.conf文件来设定内核参数 三是设定系统时钟 四是装在键盘映射 五是启用交换分区 六是设置主机名 七是根文件系统检测,并以读写方式重新挂载 八是激活RAID和LVM设备 九是启用磁盘配额 十是根据/etc/fstab,检查并挂载其他文件系统 十一是清理过期的锁文件和PID文件 在/etc/rc#.d下的文件,K*、S* K# 后面为数字,表示关闭的优先级,数字越小越优先关闭 S# 后面跟数字,表示开启服务的优先级,数字越小越优先。 我们应当遵循先关闭后启动的原则,先关闭以K开头的程序,在启动S开头的程序,都是链接文件。 只要一个陈故乡支持start,restart等等放入/etc/initrd/目录下,可以通过命令自动创建链接文件到/etc/rc.d/下的各级别下。 服务类脚本: 红帽在编排时遵循sys-V风格,在/etc/rc.d/init下的脚本,至少支持(接受)四个参数:start|stop|restart|status 额外的参数: reload:无需重启读取配置文件,1号信号也能够重新加载配置文件 configtest:用于检测配置文件中是否有语法错误。 /etc/rc.d/init/下所有的脚本有两行: #chkconfig:定义 `#description` 这一类脚本依靠这两个能够实现称为系统服务。 chkconfig命令:指定/etc/init.d下的这一类脚本,能够自动给他们创建连接到/etc/rc.d/rc#.d目录下,这一类脚本必须要有chkconfig、description两行。 `#chkconfig #1# #2# #3#` 1启动的级别,runlevels(345等等), 2SS启动的游优先顺序 3KK关闭的优先顺序 当chkconfig命令来为此脚本在rc#.d目录创建连接时,runlevels表示默认创建默认为S#开头的连接,除此之外的级别默认创建为K#。 description:描述信息 用于说明此脚本的简单功能,“\”为换行,每一行不能超过80个字符,否则在图形化界面显示不出来。 chkconfig、description为注释的内容,但是chkconfig命令会读取这两行中的内容。 一般来说,先开启的服务后关闭,后开启的服务先关闭。因为开启的服务可能有其他服务依赖。 当一个程序启动起来之后,就在/var/lock下创建一个锁文件,当程序关闭时就删除锁文件,我们可以通过锁文件判断程序是否运行。 chkconfig –list查看所有独立守护进程的启动设定 chkconfig—list [SERVICE_NAME]查看特定的进程 我们将脚本文件放在/etc/init.d目录下,使用chkconfig –add SERVICE_NAME 将脚本加入服务列表,加入由chkconfig控制的服务中去。 但凡能够在对应级别下可以设置其启动、停止状态的服务都叫独立守护进程(可以管理在哪些级别下是开启的,在哪些级别下是关闭的。) 卸载对应的进程: chkconfig –del SERVICE_NAME 将创建连接的文件全部删除。 chkconfig –level RUNLEVES_NSME(on|off)改变守护进程的启动级别开关。 chkconfig runlevels SS KK runlevels可以为一个短横线:- 表示没有级别默认为S#开头的链接,即所有的链接都以K#开头。 /etc/rc.d/rc.local脚本 /etc/rc.d/rc3.d/S99local S99为所有服务的最后一个脚本,所以一些不期望写成服务加入守护进程,也不希望特别麻烦的操作,都可以写入到这个脚本中,随开机启动,在用户登录前执行。 local是系统启动时最后执行的脚本。 action: respawn,只要进程停止就会重启,启动终端0-6,respawn用于终端和图形界面 继续讲一讲/etc/inittab的任务 一是设定默认的运行级别 二是运行系统初始化脚本 三是运行指定运行级别对应目录下的脚本 四是设定Ctrl+Alt+Del组合键的操作 五是设定UPS电源在电源故障/恢复时执行的操作 六是启动虚拟终端(2345级别) 七是启动图形终端(只在对应的级别下启动) 守护进程的类型: 独立守护进程 瞬时守护进程:不需要关联运行级别,由一个独立守护进程xinetd进行管理,xinetd被称为超级守护进程,对瞬时守护进程进行管理,需要时才启动。 xinetd超级守护进程: 用于管理瞬时守护进程,xinetd默认是没有安装的,当xinetd安装的时候,会有许多的瞬时守护进程,它没有运行级别的概念,有xinetd调用,我们需要知道的是,当我们将一个程序加入守护进程的时候,对当前的服务是没有影响的,重启才会生效,有需要时可以直接将对应的服务启动。 chkconfig [--level RUNLEVELS] SERVICE (on|off) 指定的级别如果省略。默认为2345级别。 给自己讲linux 2017-02-03 评论 1957 次浏览