1、描述centos6系统开机启动流程;

按下开机按键

--> 主板检测到开机信号

--> 硬件自动将BIOS或者可以引导到BIOS的程序复制到内存指定地址

--> CPU复位内部寄存器 使得CPU从上面指定的内存地址开始执行程序

--> 进入 BIOS 程序(对于UEFI引导的主机 可能略有出入)

--> 系统自检

--> BIOS自检完成后 根据引导选项 选择引导设备

--> 读取引导设备的MBR信息,加载Bootloader程序(对于UEFI引导的主机 GPT分区的磁盘设备及网络启动的设备等 可能略有出入)

--> Bootloader程序(主要是LILO及GRUB)将系统控制权移交至Linux Kernel

--> Kernel 通过RAMFS辅助或者直接运行 完成自身初始化:

探测可识别的所有硬件设备

加载硬件驱动程序

以只读方式挂载根文件系统

运行用户空间的第一个应用程序 /sbin/init

    init 程序主要分为以下三种 Sys-V、Upstart、Systemd

2、描述/etc/rc.d/sysinit脚本功能;
  1. 设置主机名;

  2. 设置欢迎信息;

  3. 激活udev和selinux;

  4. 挂载/etc/fstab文件中定义的文件系统;

  5. 检测根文件系统,并以读写方式重新挂载根文件系统:

  6. 设置系统时钟 (读取硬件时钟并将其设置为当前系统时钟);

  7. 激活swap设备;

  8. 根据/etc/sysctl.conf 文件设置内核参数;

  9. 激活lvm与soft raid设备;

  10. 加载额外设备的驱动程序;

  11. 清理操作

3、总结文本处理工具sed及awk的用法;(必须附带示例)
sed

sed: Stream EDitor, 行编辑器;

用法:

sed [option]... 'script' inputfile...

  script:  '地址命令'

  常用选项:

    • -n:不输出模式中的内容至屏幕;

    • -e: 多点编辑;

    • -f /PATH/TO/SCRIPT_FILE: 从指定文件中读取编辑脚本;

    • -r: 支持使用扩展正则表达式;

    • -i: 原处编辑;

  地址定界:

    • (1) 不给地址:对全文进行处理;

    • (2) 单地址:

      • #: 指定的行;

      • /pattern/:被此处模式所能够匹配到的每一行;

    • (3) 地址范围:

      • #,#

      • #,+#

      • /pat1/,/pat2/

      • #,/pat1/

    • (4) ~:步进

      • 1~2

      • 2~2

  编辑命令:

    • d: 删除;

    • p: 显示模式空间中的内容;

    • a \text:在行后面追加文本;支持使用\n实现多行追加;

    • i \text:在行前面插入文本;支持使用\n实现多行插入;

    • c \text:替换行为单行或多行文本;

    • w /path/to/somefile: 保存模式空间匹配到的行至指定文件中;

    • r /path/from/somefile:读取指定文件的文本流至模式空间中匹配到的行的行后;

    • =: 为模式空间中的行打印行号;

    • !: 取反条件;

    • s///:支持使用其它分隔符,s@@@,s###;

      替换标记:

      • g: 行内全局替换;

      • p: 显示替换成功的行;

      • w /PATH/TO/SOMEFILE:将替换成功的结果保存至指定文件中;

  高级编辑命令:

    • h: 把模式空间中的内容覆盖至保持空间中;

    • H:把模式空间中的内容追加至保持空间中;

    • g: 从保持空间取出数据覆盖至模式空间;

    • G:从保持空间取出内容追加至模式空间;

    • x: 把模式空间中的内容与保持空间中的内容进行互换;

    • n: 读取匹配到的行的下一行至模式空间;

    • N:追加匹配到的行的下一行至模式空间;

    • d: 删除模式空间中的行;

    • D:删除多行模式空间中的所有行;

  示例:

sed -n 'n;p' FILE          # 显示偶数行
sed '1!G;h;$!d' FILE       # 逆向显示文件内容
sed '$!N;$!D' FILE         # 取出文件后两行
sed '$!d' FILE             # 取出文件最后一行
sed 'G' FILE               # 每行后加一空白行 
sed '/^$/d;G' FILE         # 将多个空白行合并为一个空白行
sed 'n;d' FILE             # 显示奇数行;
sed -n '1!G;h;$p' FILE     # 逆向显示文件中的每一行;
 
#删除/boot/grub/grub.conf文件中所有以空白开头的行行首的空白字符;
sed 's@^[[:space:]]\+@@' /etc/grub2.cfg
 
#删除/etc/fstab文件中所有以#开头,后面至少跟一个空白字符的行的行首的#和空白字符;
sed 's@^#[[:space:]]\+@@' /etc/fstab
 
#echo一个绝对路径给sed命令,取出其基名;取出其目录名;
# echo "/etc/sysconfig/" | sed 's@[^/]\+/\?$@@'


awk

gnu awk: gawk,报告生成工具 格式化文本输出 内建有脚本语言解释器 具有一般编程语言所支持的所有功能。

  用法:

基本用法:gawk [options] 'program' FILE ...
  program: PATTERN{ACTION STATEMENTS}
  语句之间用分号分隔

  选项:

    • -F:指明输入时用到的字段分隔符;

    • -v var=value: 自定义变量;

  变量:

    • 内建变量

      • FS:input field seperator,默认为空白字符;

      • OFS:output field seperator,默认为空白字符;

      • RS:input record seperator,输入时的换行符;

      • ORS:output record seperator,输出时的换行符;

      • NF:number of field,字段数量    {print NF}, {print $NF}

      • NR:number of record, 行数;

      • FNR:各文件分别计数;行数;

      • FILENAME:当前文件名;

      • ARGC:命令行参数的个数;

      • ARGV:数组,保存的是命令行所给定的各参数;

    • 自定义变量

      • -v var=value
           变量名区分字符大小写;

      • 在program中直接定义

  运算符:

    • 算术操作符: x+y, x-y, x*y, x/y, x^y, x%y, -x, +x(转换为数值);

    • 字符串操作符:没有符号的操作符,字符串连接

    • 赋值操作符: =, +=, -=, *=, /=, %=, ^=, ++, --

    • 比较操作符: >, >=, <, <=, !=, ==

    • 模式匹配符: ~ (是否匹配), !~ (是否不匹配)

    • 逻辑操作符: &&, ||, !

    • 函数调用: function_name(argu1, argu2, ...)

    • 条件表达式: selector?if-true-expression:if-false-expression

  PATTERN:

    1. empty:空模式,匹配每一行;;

    2. /regular expression/:仅处理能够被此处的模式匹配到的行;

    3. relational expression: 关系表达式;结果有“真”有“假”;结果为“真”才会被处理;(真:结果为非0值,非空字符串;)

    4. line ranges:行范围,
        startline,endline:/pat1/,/pat2/
        注意: 不支持直接给出数字的格式

    5. BEGIN/END模式

      • BEGIN{}: 仅在开始处理文件中的文本之前执行一次;
      • END{}:仅在文本处理完成之后执行一次;

  常用的action:

    1. Expressions

    2. Control statements:if, while等;

    3. Compound statements:组合语句;

    4. input statements

    5. output statements

  控制语句:

    • if(condition) {statments}

    • if(condition) {statments} else {statements}

    • while(conditon) {statments}

    • do {statements} while(condition)

    • for(expr1;expr2;expr3) {statements}

    • break

    • continue

    • delete array[index]

    • delete array

    • exit

    • { statements }

  array:

    • 关联数组:array[index-expression]

      • index-expression:

        1. 可使用任意字符串;字符串要使用双引号;
        2. 如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”;
      • 若要判断数组中是否存在某元素,要使用"index in array"格式进行;

      • 若要遍历数组中的每个元素,要使用for循环:   for(var in array) {for-body}

  函数:

  • 内置函数

    • 数值处理:

      • rand():返回0和1之间一个随机数;

    • 字符串处理:

      • length([s]):返回指定字符串的长度;

      • sub(r,s,[t]):以r表示的模式来查找t所表示的字符中的匹配的内容,并将其第一次出现替换为s所表示的内容;

      • gsub(r,s,[t]):以r表示的模式来查找t所表示的字符中的匹配的内容,并将其所有出现均替换为s所表示的内容;

      • split(s,a[,r]):以r为分隔符切割字符s,并将切割后的结果保存至a所表示的数组中;

  示例:

# 显示/etc/passwd文件中第二行到第十行对应的用户名
awk -F: '(NR>=2&&NR<=10){print $1}' /etc/passwd

# 显示/etc/passwd文件中 所有的用户名及其对应的用户类型
awk -F: '{$3>=1000?usertype="Common User":usertype="Sysadmin or SysUser";printf "%15s:%-s\n",$1,usertype}' /etc/passwd
awk -F: '{if($3>=1000) {printf "Common user: %s\n",$1} else {printf "root or Sysuser: %s\n",$1}}' /etc/passwd

# 显示所有默认使用Bash的用户
awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd

# 一个简单的测试NF用法的程序
awk '{if(NF>5) print $0}' /etc/fstab

# 打印所有以/dev/开头的磁盘设备 如果使用空间百分比大于20 则显示设备路径
#(使用%作为分隔符 之后在用正常分隔符 最后一个字段为已经使用的百分比) 
df -h | awk -F[%] '/^\/dev/{print $1}' | awk '{if($NF>=20) print $1}'

# 显示所有用户ID号为偶数的用户
awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd

# 数组及循环体的练习 打印一周中前两天的英文
awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}'

# 显示处于不同TCP状态的网络连接数量
netstat -tan | awk '/^tcp\>/{state[$NF]++}END{for(i in state) { print i,state[i]}}'

# 显示httpd 服务日志中同一个IP的访问次数
awk '{ip[$1]++}END{for(i in ip) {print i,ip[i]}}' /var/log/httpd/access_log

# 统计/etc/fstab文件中每个文件系统类型出现的次数;
awk '/^UUID/{fs[$3]++}END{for(i in fs) {print i,fs[i]}}' /etc/fstab

# 统计指定文件中每个单词出现的次数;
awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count) {print i,count[i]}}' /etc/fstab

# 统计每个IP创建的TCP连接数量 
netstat -tan | awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++}END{for (i in count) {print i,count[i]}}'

4、写一个脚本,生成10个随机数,并按从小到大进行排序(要求至少使用2种方法);
#!/bin/bash
# used for sort 

declare -a Random_array

bubble_sort(){
local a=($1)
local i
local j
local temp
for ((j=0;j<$[${#a[@]}-1];j++))do
    for ((i=0;i<$[${#a[@]}-1-$j];i++))do
        if [ ${a[$i]} -gt ${a[$[$i+1]]} ]; then
            temp=${a[$i]}
            a[$i]=${a[$(($i+1))]}
            a[$(($i+1))]=$temp
        fi
    done
done
echo ${a[@]}
}


select_sort(){
local a=($1)
local i
local j
local min
local temp
for ((i=0;i<$[${#a[@]}-1];i++))do
    min=$i
    for ((j=$[$i+1];j<${#a[@]};j++))do
        if [ ${a[$min]} -gt ${a[$j]} ]; then
            min=$j
        fi
    done
    if [ $min -ne $j ]; then
        temp=${a[$min]}
        a[$min]=${a[$i]}
        a[$i]=$temp
    fi    
done
echo ${a[@]}
}

for i in {0..9}; do
    Random_array[$i]=$RANDOM
done

echo "original array:"
echo ${Random_array[@]}
echo "sort with bubble sort algorithm:"
bubble_sort "${Random_array[*]}"
echo "sort with select sort algorithm:"
select_sort "${Random_array[*]}"

排序算法执行效果示意

5、在每周二的凌晨1点5分执行脚本/data/get_username.sh,并将脚本的输出至/tmp/get_username.log日志文件中;

需要修改配置文件 /etc/crontab 在其中增加一行:

[root@localhost tmp]# cat /etc/crontab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root

# For details see man 4 crontabs

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name  command to be executed
  5  1  *  *  2 root /data/get_username.sh >> /tmp/get_username.log
6、写一个脚本:如果某路径不存在,则将其创建为目录;否则显示其存在,并显示内容类型;
#!/bin/bash
# file type detection 


if [ $# -ne 1 ]; then
    echo "Only can receive one parameter."
    exit 2
fi
if [ -e $1 ]; then
    echo "$1 exists."
    file $1
else
    mkdir -p $1 >>/dev/null
    [ $? -eq 0 ] && echo "Directory $1 Created."
fi

文件内容类型查看脚本

7、写一个脚本,打印9X9乘法表;

弄个递归的方法试试吧。

#!/bin/bash
# used for print multiplication tables

m_table(){
if [ $1 -eq 1 ]; then
    echo -e "1X1=1\t"
else
    m_table $[$1-1]
    for((i=1;i<=$1;i++))do
        echo -e -n "${i}X${1}=$[$i*$1]\t"
    done
    echo
fi
}

m_table 9

递归打印99乘法表执行效果示意

8、描述dns的工作流程,以及完整搭建一套dns主从服务器,相关域名和ip可自行设定。
DNS工作流程

DNS,Domain Name Service, 基于C/S架构,使用套接字53/udp, 53/tcp来完成数据交换,是一种应用层协议。Linux下常用的服务器端软件为bind

DNS是用来完成域名和IP地址之间的转换的。

DNS的查询类型主要有两种:递归查询迭代查询

一次完整的查询请求经过的流程:

客户端需要进行一次IP/域名解析,发请求;

首先查看本机 hosts文件 (对于Linux位于/etc/hosts 对于Windows位于%WINDOWS%/system32/drivers/etc/hosts)中是否存在解析记录,如果没有执行下一步;

查看本地的DNS缓存中是否存在解析记录,如果没有执行下一步;

向DNS配置中指向的第一个DNS服务器请求获取解析记录

  通过递归查询是否存在解析记录,如果没有执行下一步;

  查看服务端的缓存中是否存在解析记录,如果没有执行下一步;

  访问根服务器,开始迭代查询

搭建一套DNS主从服务器

环境介绍:

主DNS服务器: 192.168.11.100 CentOS 7.1 BIND 9.9.4

从DNS服务器:192.168.11.101 CentOS 6.6 BIND 9.8.2rc1

测试客户端: 192.168.11.102 CentOS7.1

FQDN为 test-dns.com.

>

  主从服务器安装软件环境:

yum install bind bind-libs bind-utils
#(对于生产环境 同时还应该安装上 bind-chroot 以提高安全性)

  主服务器配置:

1) 修改主配置文件 /etc/named.conf ,

# 监听外部地址
    listen-on port 53 { 127.0.0.1; };   
->  listen-on port 53 { 192.168.11.100;127.0.0.1; };

# 允许外部地址访问
    allow-query     { localhost; };
->  allow-query     { any; };

# 关闭dnssec
    dnssec-enable yes;
    dnssec-validation yes;
->  dnssec-enable no;
    dnssec-validation no;

2)在/etc/named.rfc1912.zones 文件中定义区域

# 在文件尾部加入如下的配置项
zone "test-dns.com" IN {
        type master;
        file "test-dns.com.zone";
};

3)创建并定义区域解析库文件:

touch /var/named/test-dns.com.zone
#逐项添加如下资源定义到解析库文件中
$TTL 86400
$ORIGIN test-dns.com.
@ IN SOA ns1.test-dns.com. admin.test-dns.com. (
        2016020601;
        1H
        5M
        7D
        1D )
        IN NS    ns1.test-dns.com.
        IN NS    ns2.test-dns.com.
        IN MX 10 mx1.test-dns.com.
        IN MX 20 mx2.test-dns.com.
ns1     IN A    192.168.11.100
ns2     IN A    192.168.11.101
mx1     IN A    192.168.11.100
mx2     IN A    192.168.11.100
www     IN A    192.168.11.100
mail    IN A    192.168.11.105
nas     IN A    192.168.11.128
*       IN A    192.168.11.100

#修改解析库文件权限
chmod 640 test-dns.com.zone;
chown :named test-dns.com.zone

4)检查配置文件书写正确与否

named-checkconf
named-checkzone "test-dns.com" test-dns.com.zone
rndc status

5)重读配置文件

systemctl reload named.service

wKioL1a2F8OArb10AABTU4_JtlQ284.png

6)本地测试

dig -t A nas.test-dns.com @192.168.11.100
dig -t A www.test-dns.com @192.168.11.100
dig -t A nas.test-dns.com @192.168.11.100

  从服务器配置:

1) 修改主配置文件 /etc/named.conf ,

# 监听外部地址
    listen-on port 53 { 127.0.0.1; };   
->  listen-on port 53 { 192.168.11.101;127.0.0.1; };

# 允许外部地址访问
    allow-query     { localhost; };
->  allow-query     { any; };

# 关闭dnssec
    dnssec-enable yes;
    dnssec-validation yes;
->  dnssec-enable no;
    dnssec-validation no;

2)在/etc/named.rfc1912.zones 文件中定义区域

# 在文件尾部加入如下的配置项
zone "test-dns.com" IN {
        type slave;
        masters { 192.168.11.100; };
        file "slaves/test-dns.com.zone";
};

3)分别在主从服务器上关闭防火墙:

# CentOS 7.1  
service firewalld stop
# CentOS 6.6
/etc/init.d/iptable stop
    

4)检查并重读配置文件

named-checkconf
rndc reload
rndc status

5)本地测试

# 查看日志 确认同步是否正常
tail /var/log/messages

# 测试解析
dig -t A nas.test-dns.com @192.168.11.101
dig -t A www.test-dns.com @192.168.11.101
dig -t A nas.test-dns.com @192.168.11.101

6)测试“通知”机制是否运行正常

主服务器端

# 手动修改主服务器 区域文件内容 /var/named/test-dns.com.zone

# 手动修改序列号 使其+1
# 重载配置
 rndc reload
# 查看日志 确认同步是否已经完成
 tail /var/log/messages
    
>

从服务器端

# 查看日志 确认同步是否已经完成
 tail /var/log/messages