Kernel (2)


ramdisk管理:

ramdisk文件是在操作系统安装完成之后,由特定的应用程序根据当前硬件设备信息,文件系统信息等量身定制而成;


ramdisk文件的制作工具:

CentOS 5:

mkinitrd

mkinitrd - creates initial ramdisk p_w_picpaths for preloading modules


mkinitrd initrd-KERNEL-VERSION.img kernel-version



CentOS 6/7:

dracut

dracut - create initial ramdisk p_w_picpaths for preloading modules


dracut initramfs-KERNEL-VERSION.img kernel-version


mkinitrd脚本


内核信息输出的两个重要的伪文件系统:

/proc:内核状态及统计信息的主要的输出接口;同时,还提供了一个能够输入配置信息,完成内核参数实时配置的接口——/proc/sys;

/proc/*(除了sys目录):信息输出,只读;

/proc/sys:可读写,可以接受用户指定的"新值",来实现对内核相应功能或特性的实时配置;


查看内核输出的状态信息或统计信息,直接使用cat命令即可;


修改或设置内核功能或特性:

使用echo命令,借助于覆盖输出重定向进行修改或设置即可;


echo "VALUE" > /proc/sys/PATH/TO/PARAMETER


查看内核参数以及配置/proc/sys中的诸多功能,还可以使用:

sysctl命令:

sysctl - configure kernel parameters at runtime


查看内核参数:

sysctl -a:查看所有可以被修改的内核参数;

sysctl variable:查看指定内核参数的设定值;


配置某个内核参数(功能或特性)的值:

sysctl -w variable=value 

注意:在此方法中,"="两端不能写空格字符;


sysctl -p:根据配置文件设置内存参数值;重新读取并加载配置文件中所有的设置参数并且使其生效;


常用的几个内核参数:

net.ipv4.ip_forward:Linux的核心转发功能,路由功能;取值0,1

net.ipv4.icmp_echo_ignore_all:忽略所有来源于外部主机的ping操作请求,取值0,1

vm.drop_caches:清理buffer和cache,释放物理内存,取值:0,1,2

kernel.hostname:当前生效的主机名;



DDOS:Dynamic Deny Of Service,动态拒绝服务***;

DHCP:IP地址耗尽策略,发送大量随机MAC地址DHCP discover消息

DNS:ARP***,ARP欺骗,

网关欺骗

源IP地址欺骗

dead ping:


/sys:sysfs

专门为用户提供的伪文件系统,输出内核识别出来的各硬件设备的相关属性信息,也包括内核对硬件特性的可设定的信息;对于某些参数进行特定格式的修改,以调整或设定硬件的工作特性;


echo '- - -' > /sys/class/scsi_host/host2/scan


udev:

通过读取/sys目录下的硬件设备的信息,按需为各硬件设备创建设备文件;


udev是运行在用户空间的进程;


专用工具:udevadmin,hotplug...


当内核已经被加载至内存中,加入操作系统被安装到sda磁盘上,则内核需要先标识出sda磁盘并且将其标记为设备(创建设备文件),而后才能挂载此设备;


为了能够让这样的设备以后也能正常使用,内核通过内置的devtmpfs为每个内核所要使用的设备创建设备文件;而这样的文件可以在被当做文件系统挂载之后,从内核直接转移到真正的rootfs中的dev目录内的;对于操作系统启动之后被新插入的设备,就必须要依靠udev来识别并创建设备文件了;


udev之所以能够为设备创建设备文件,主要依赖于其事先定义好的规则;而这样的规则一般保存在udev的规则配置文件中;

/etc/udev/rules.d

/usr/lib/udev/rules.d


定制内核——编译内核源代码:

http://kernel.org 内核维护的官方站点,可以获取内核源代码包;


编译源代码的前提条件:

1.开发环境:

开发工具:gcc,make,automake,qt,GTK,ncurses

程序包组:

"Development Tools", "Server Platform Development"

"开发工具", "服务器平台开发"


ncurses-devel


头文件:/usr/include/*.h


2.获取目标主机上各硬件设备的相关信息;

CPU:

# cat /proc/cpuinfo

# lscpu

# x86info -a


PCI设备:

# lspci [-v|-vv]


USB设备:

# lsusb [-v|-vv]


块设备:

# lsblk 


了解更多的硬件设备的信息:

# hal-device (CentOS6可用,包名:hal-0.5.14-14.el6.x86_64)


3.获取目标主机系统功能的相关选项:

比如:目标主机需要使用哪种文件系统;

目标主机是否需要启用安全防护机制;

...


编译安装应用程序的一般步骤:

1) # ./.configure ARG1 [ARG2...]

2) # make

3) # make install


编译安装内核的一般步骤:

1.需要准备或生成一个.config的文件,该文件记录了内核的编译细节:

哪些功能直接编译进内核;

哪些功能编译成内核模块;

哪些功能在此次编译中不启用;


make menuconfig|xconfig|gconfig|config


2.开始编译内核

make [-j #]

多线程编译,可以将编译进程在多个CPU核心上并行进行,加快编译速度;


3.安装模块:

make modules_install


4.安装内核核心文件,并生成grub的启动菜单;

make install

安装的是bzImage文件,安装到/boot/vmlinuz-VERSION-release;

生成与内核版本完全匹配的initramfs文件;

编辑grub的配置文件,生成启动菜单项;


screen命令:

开启screen:

# screen

拆除screen:

ctrl+a,d

列表显示screen:

# screen -ls

恢复连接至指定的screen:

# screen -r SCREEN_ID

关闭screen:

# exit


内核的配置选项:

64-bit kernel

是否支持64位内核


General setup  --->

通用配置项

() Local version - append to kernel release

自定义本地版本号,附加到内核版本号后面的信息,由编译者定义;

((none)) Default hostname

定义当没有设置主机名时的默认主机名;


Enable loadable module support

是否支持内核模块的动态装卸载;


Enable the block layer

是否支持启用块层,通常是选择支持;


processor type and features:

处理器类型和特性

Processor family (Generic-x86-64) --> (Core 2/newer Xeon)

选择处理器类型


Power management and ACPI options:

电源管理及高级电源管理接口选项


Executable file formats / Emulations

指定可执行文件的格式,默认为ELF,以#!开头的文件也具备可执行特性;


Networking support:

内核中的网络协议栈

Networking options

[ ] IPv6 support 


Device drivers:

设备驱动程序


File system:

DOS/FAT/NT file systems

[M] NTFS support


Kernel hacking:

内核调试的相关内容


Security options:

NSA SELInux support

安全选项


Cryptographic API:

加密解密的应用编程接口;


Virtualization:

虚拟化相关


配置内核方式:


1. make config:基于单行命令行以遍历内核所有功能的方式进行内核配置,因此每个内核选项的配置都是交互式的;


2. make menuconfig:基于curses的文本模式的配置窗口;


3. make gconfig:基于GTK开发环境的窗口配置界面;一般情况下,只要安装了"桌面平台开发"程序包组就可以了;


4. make xconfig:基于QT开发环境的窗口配置界面;一般情况下,只要安装了"桌面平台开发"程序包组就可以了;


5. make defconfig:基于内核为目标平台提供默认配置模版进行配置;


6. make allnoconfig:所有的功能全部不编译(全部选no)配置方式;


7. make allyesconfig:所有的功能全部编译进核心(全部选yes)的配置方式;


内核的编译方式:

1.全编译:make [-j #]

2.部分编译:

a.只编译某个子目录中的相关源代码;

# cd /usr/src/linux

# make [-j #] DIR_NAME/

b.只编译特定的模块

# cd /usr/src/linux

# make [DIR/]file.ko


示例:

# cd /usr/src/linux

# make drivers/net/ethernet/intel/e1000/e1000.ko

3.交叉编译:编译的目标平台与当前编译的平台不相同;

make ARCH=arch_name


示例:

make ARCH=arm 


内核重新编译:

1.将所有/usr/src/linux-VERSION目录的内容直接删除,重新从源代码包释放;随后可以重复之前的步骤重新编译即可;


2.先清理之前的编译结果:

make clean:

清理大多数的编译生成的文件,但是会保留.config文件;


make mrproper:

清理所有编译生成的文件,包括.config以及其他的备份文件;


make distclean:

相当于make mrproper,但是还会额外清理各种patches以及编译器自身的备份文件;


编译安装内核实例

~]# tar xf linux-3.10.99.tar.xz -C /usr/src

~]# cd /usr/src

src]# ln -sv linux-3.10.99 linux

src]# cd /usr/src/linux

linux]# cp /boot/config-$(uname -r) ./.config

linux]# make menuconfig

linux]# make -j 4

linux]# make modules_install

linux]# make install

linux]# reboot


重启之后在grub菜单中选择新编译的内核来启动,如果可以看到登录提示符,则说明内核编译升级成功!

然后可以尝试编译其他与当前操作系统版本不同的其他更高级版本的内核,多试几个版本,了解一下各个不同版本的内核的特性;


Linux系统安装:CentOS系


POST --> BootSequence(BIOS) --> BootLoader(GRUB --> 1_5 stage -->2nd stage) --> Kernel (devtmpfs) --> [ ramdisk (dev,proc,sys) -->] rootfs(ro) --> /sbin/init (SysV Init, upstart Init, systemd) 


对于所安装的CentOS操作系统来说,其一级子目录中,有一些绝对不能单独分区,有一些可以单独分区;


绝对不能分区:bin, sbin, lib, lib64

建议单独分区:boot, home, var, usr


安装Linux系统:

/boot

swap

/

/home

/var

/usr


磁盘分区规划:

启动分区

根分区

swap


规划文件系统:

/sbin/init, /sbin/systemd

所有的应用程序存放的路径

应用程序所依赖的库文件存放的路径

应用程序所使用的配置文件存放的路径



CentOS系/RHEL系操作系统的安装程序:anaconda

在安装操作系统的过程中,系统的启动流程:

POST --> BootLoader --> kernel --> initrd --> rootfs --> anaconda


anaconda给我们提供了两种操作界面:

TUI:基于curses的文件配置窗口;

GUI:图形界面

CLI:命令行界面


以光盘为例,CentOS系统的安装启动流程:

1.POST

2.读取MBR:boot.cat,就是光盘的bootloader;/isolinux/boot.cat

3.stage2:/isolinux/isolinux.bin

配置文件:/isolinux/isolinux.cfg

label linux

标签名称,可以用来引用下述所有命令的通用名称;

 menu label ^Install or upgrade an existing system

  菜单项的具体内容以及对应的热键;

 menu default

  将此菜单项做为默认菜单项;

 kernel vmlinuz

  指定内核文件名称

 append initrd=initrd.img

  向内核传递附加参数;常用的参数有:

  initrd=initrd.img

  text:从文本界面启动

  method:手动选择安装方式

  ip=ADDRESS

  netmask=MASK

  gateway=GW

  dns=DNS_SERVER

  rescue:启用紧急救援模式

  dd:device drivers,装载额外的设备的启动程序;

  ks:使用kickstart启动无人值守安装,指明kickstart配置文件的所在位置:

  光盘上:ks=cdrom:/PATH/TO/KICKSTART_FILE

  本地硬盘:ks=hd:/DEVICE/PATH/TO/KICKSTART_FILE

  某个远程web站点:ks=http://HOST[:PORT]/PATH/TO/KICKSTART_FILE

  某个远程FTP站点:ks=ftp://[username@]HOST[:PORT]/PATH/TO/KICKSTART_FILE

  某个远程安全WEB站点:ks=https://HOST[:PORT]/PATH/TO/KICKSTART_FILE


4.装载rootfs,并启动anaconda

注意:如果内存不够512M,则anaconda是以文本界面启动的;如果内存大于512M,anaconda默认以图形界面启动;


"ESC"键 --> boot: linux text


注意:上述的所有内容一般位于引导设备,而后续的anaconda及其他安装时所用的程序包或程序包组等可来源于yum仓库,yum仓库的位置:

本地光盘

本地硬盘

FTP服务器

HTTP服务器

NFS服务器


如果想手动指定程序包安装源:

ESC键 --> boot: linux method


anaconda的工作过程:

安装前的准备配置阶段

1.安装过程中使用的语言:简体中文

2.键盘布局类型:美国英语式

3.系统安装的目标存储设备:

Basic Storage,本地磁盘

Special Storage,网络存储,iSCSI,NAS,SAN, ...

4.设置主机名称

5.配置网络接口

6.选择时区

7.管理员密码

8.设定分区方式及MBR安装的位置

9.选择要安装的程序包或程序包组;


安装阶段:

1.有可能运行某些预安装脚本,完成初始化工作;

2.根据准备阶段规划的分区格式进行分区创建并执行格式化安装文件系统并挂载所有文件系统至指定挂载点;

3.将选定的程序包或程序包组安装至目标位置;

4.安装bootloader至MBR及boot分区中;

5.制作ramdisk文件;

6.如果有必要,可能会运行安装后脚本;


首次启动:

1.选择许可证信息;

2.创建普通用户;

3.配置内核核心转储(Kdump,Core dump),如果内存小于2GB,Kdump不开启;

当某一时刻,内核核心崩溃时,kdump会将内核崩溃时内存中的所有数据创建成一个映像文件保存到磁盘上;通过分析此文件的内容,查找出内核崩溃的直接或间接原因;


1.是否配置iptables防火墙;初学者建议关闭;

2.是否配置SELinux安全机制的启动,初学者建议关闭;


kickstart文件的格式:

命令段:指明各种安装前的配置;

必备命令:

authconfig:认证方式的配置

authconfig --useshadow --passalgo=sha512

bootloader:定义bootloader的安装位置和相关配置选项

bootloader --location=mbr --driveorder=sda --append="crashkernel=auto rhgb quiet"

keyboard:设定键盘的类型

keyboard us

lang:安装过程中的语言类型

lang zh_CN.UTF-8

part:分区布局及分区使用方式的定义;

part /boot --fstype=ext4 --size=200

part swap --size=2048

part PV_NAME --size=51200 --grow

clearpart:清除分区

clearpart --none --drives=sda

volgroup:创建卷组的命令

volgroup VG_NAME --pesize=8192 PV_NAME 

logvol:创建逻辑卷的命令

logvol /home --fstype=ext4 --name=lv_home --vgname=VG_NAME --size=10240

logvol / --fstype=ext4 --name=lv_root --vgname=VG_NAME --size=30720

logvol /var --fstype=ext4 --name=lv_var --vgname=VG_NAME --size=10240

logvol /usr --fstype=ext4 --name=lv_usr --vgname=VG_NAME --size=10240

rootpw:指明超级用户root的密码

rootpw --iscrypted $6$SALT$ENCRYPTED_PASS

timezone:时区

timezone Asia/Shanghai

可选择命令:

install:全新安装操作系统

upgrade:升级安装操作系统

text:使用文本界面安装操作系统,默认是GUI;

network:配置网络接口

network --onboot yes --device eth0 --bootproto static --ip 172.16.254.1 --netmask 255.255.0.0 --noipv6 --hostname a.link.com --gateway= --dns=

firewall:防火墙设置

firewall --disabled

firewall --service=ssh

selinux:SELinux的设置

selinux --disabled

selinux --enforcing


题外话:

如果计划在已经开启防火墙和SELinux的强制模式时,可以通过这样的几种方式将其关闭:

防火墙:

CentOS 6:

# service iptables stop

# chkconfig iptables off

CentOS 7:

# systemctl stop firewalld.service

# systemctl disable firewalld.service


如果想要让防火墙临时不生效:

# iptables -F 适用于所有的CentOS系统;


SELinux:

1.编辑SELinux的配置文件/etc/sysconfig/selinux(/etc/selinux/config),在配置文件中,有一行语句为: 

SELINUX=disabled


2.编辑grub的启动配置文件/boot/grub/grub.conf

kernel /vmlinuz-VERSION-release ARGS selinux=0


如果想要SELinux临时不限用户行为:

# setenforce 0  == Enforcing --> Permissive

# setenforce 1  == Permissive --> Enforcing

# getenforce

repo:安装系统是所使用的repository

repo --name="CentOS" --baseurl=cdrom:sr0 --cost=100

repo --name="CentOS" --baseurl=http://host[:port]/PATH --cost=100

reboot:安装完成之后重新启动

halt/poweroff:安装完成之后关闭系统

url:指明安装时使用的repository,但必须使用url格式;

url --url=http://host[:port]/PATH

firstboot:控制首次启动

firstboot --disable

脚本段:

%pre:安装前脚本的开始部分

运行环境:运行于安装介质上的微型Linux系统环境;

%end


%post:安装后脚本的开始部分

运行环境:安装以后的操作系统

%end

程序包/程序包组段:指明要安装的程序包或程序包组以及不安装程序包;

%packages

@PACK_GROUP_NAME:安装一个程序包组

PACK_NAME:安装单个指定的程序包

-PACK_NAME:明确指出不安装的程序包;有时即便明确指出该项,被指定的程序包也可能会被安装上;

%end


如何创建kickstart文件:

1.直接以anaconda-ks.cfg为模版,复制之后修改即可;

2.可以使用工具来创建:

如果命令不存在,则yum install system-config-kickstart安装即可;

# system-config-kickstart &


可以全新创建,也可以依据其他的ks文件(如anaconda-ks.cfg)来修改生成新的配置文件;


3.检测ks文件的语法是否存在错误:

ksvalidator


如果该命令不存在,可以安装pykickstart-1.74.20-1.el6.noarch


http://172.16.72.1/ks.cfg


利用一台CentOS7构建web server,方法如下:

临时清理防火墙规则,并将selinux设置为permissive模式:

~]# iptables -F

~]# setenforce 0

启动WEB服务

~]# systemctl start httpd.service

查看web服务的运行状态,只要有绿色文字显示的active(running),即为服务正常启动;

~]# systemctl status httpd.service 

为CentOS 6提供repository

~]# mkdir /var/www/html/centos_6_repo

~]# mount /dev/sr0 /mnt/cdrom  

注意:光驱中放的是CentOS6的安装光盘的CD1;

~]# cp -a /mnt/cdrom/* /var/www/html/centos_6_repo


到此,web服务器的配置完成;


利用一台已经安装好的CentOS 6操作系统,创建启动光盘:

将下述内容写入kickstart文件;

~]# vim /root/centos6-ks.cfg

#platform=x86, AMD64, or Intel EM64T

#version=DEVEL

# Firewall configuration

firewall --disabled

# SELinux configuration

selinux --disabled

# Install OS instead of upgrade

install

# Use network installation

network --onboot yes --device eth0 --bootproto dhcp

url --url="http://172.16.72.1/myrepo"

# Root password

rootpw --iscrypted $1$iRHppr42$VMesh73wBqhUTjKp6OYOD.

# System authorization information

auth  --useshadow  --passalgo=sha512

# Use text mode install

text

firstboot --disable

# System keyboard

keyboard us

# System language

lang en_US

# SELinux configuration

selinux --disabled

# Reboot after installation

reboot

# System timezone

timezone  Asia/Shanghai

# System bootloader configuration

bootloader --append="rhgb crashkernel=auto quiet" --location=mbr --driveorder="sda"

# Clear the Master Boot Record

zerombr

# Partition clearing information

clearpart --all  

# Disk partitioning information

part /boot --fstype="ext4" --size=200

part pv.008 --size=61440


volgroup myvg --pesize=4096 pv.008

logvol / --fstype=ext4 --name=root --vgname=myvg --size=20480

logvol swap --name=swap --vgname=myvg --size=2048

logvol /usr --fstype=ext4 --name=usr --vgname=myvg --size=10240

logvol /var --fstype=ext4 --name=var --vgname=myvg --size=20480


#repo --name="CentOS"  --baseurl=cdrom:sr0 --cost=100


%post

echo -e 'Qhdlink Linux for Learning Services\nhttp://www.linklinux.com\n' >> /etc/issue


sed -i '1,$s@id:[0-9]:initdefault:@id:3:initdefault:@g' /etc/inittab


ifconfig eth0 172.16.69.2/16


%end


%packages

@base

@core

@debugging

@basic-desktop

@desktop-debugging

@desktop-platform

@desktop-platform-devel

@development

@directory-client

@fonts

@general-desktop

@graphical-admin-tools

@input-methods

@internet-applications

@internet-browser

@java-platform

@legacy-x

@network-file-system-client

@office-suite

@print-client

@remote-desktop-clients

@server-platform

@server-platform-devel

@server-policy

@workstation-policy

@x11

mtools

pax

python-dmidecode

oddjob

wodim

sgpio

genisop_w_picpath

device-mapper-persistent-data

systemtap-client

abrt-gui

desktop-file-utils

jpackage-utils

samba-winbind

certmonger

pam_krb5

krb5-workstation

openmotif

libXmu

libXp

%end


创建引导光盘:

~]# mkdir myiso

~]# cp -r /mnt/cdrom/isolinux /root/myiso/

注意:这样的复制方法是将isolinux目录直接复制到myiso目录中,也就是说isolinux是myiso的子目录;

~]# vim /root/myiso/isolinux/isolinux.cfg

label linux

  menu label ^Install or upgrade an existing system

  menu default

  kernel vmlinuz

  append initrd=initrd.img ks=cdrom:/centos6-ks.cfg


~]# cp /root/centos6-ks.cfg /root/myiso/

~]# mkisofs -R -J -T -v --no-emul-boot --boot-load-size 4 --boot-info-table -V "CentOS 6 x86_64 boot" -b isolinux/isolinux.bin -c isolinux/boot.cat -o /root/boot.iso myiso/


创建U盘启动盘

方法一:

~]# dd if=/dev/sr0 of=/dev/sdb

方法二:

~]# fdisk /dev/sdb (将整个U盘分为一个分区,并将其分区类型修改为vfat,即在fdisk交互式模式中使用t --> b命令完成转换)

~]# mkfs.vfat /dev/sdb1

~]# mount /dev/sdb1 /mnt/usb

~]# mkidr -p /mnt/usb/grub

~]# cp /mnt/cdrom/isolinux/{vmlinuz,initrd.img} /mnt/usb

~]# vim /mnt/usb/grub/grub.conf

default=0

timeout=5

title the linux boot from usb

root (hd0,0)

kernel /vmlinuz

initrd /initrd.img ks=http://172.16.72.1/ks.cfg (将centos6-ks.cfg文件放置于CentOS7的/var/www/html目录中,改名为ks.cfg即可)

~]# grub

grub> root (hd1,0)

grub> setup (hd1)






#!/bin/bash

#

# myservice - my self testing service script.

#

# chkconfig: 2345 88 10

# description: testing script for my service.

#

prog=$(basename $0)

LOCK_FILE=/var/lock/subsys/$prog


start() {

if [ -f $LOCK_FILE ] ; then

echo "$prog is running now..."

return 10

else

touch $LOCK_FILE

echo "$prog is starting..."

fi

}


stop(){

if [ -f $LOCK_FILE ] ; then

rm -f $LOCK_FILE

echo "$prog is stopped."

else

echo "$prog is not running."

return 11

fi

}


status(){

if [ -f $LOCK_FILE ] ; then

echo "$prog is running now..."

else

touch $LOCK_FILE

echo "$prog is stopped..."

fi

}


usage(){

echo "$prog {start|stop|restart|status}"

}


case $1 in

start)

start

;;

stop)

stop

;;

restart)

stop

start

;;

status)

status

;;

*)

usage

exit 12

;;

esac
















find . | cpio -o -H newc | gzip > p_w_picpath.cpio.gz

cpio -i -F initramfs_data.cpio.gz --no-absolute-filename