管理员命令杂项

Linux文件系统
磁盘管理
RAID
LVM
程序安装
网络功能
sed命令
进程
内核管理
系统启动流程
定制、并编译内核
裁减Linux
系统安装:kickstart, pxe
shell编程:case,function, array, signal
gawk

Linux文件系统:
存储空间:数据区,元数据区

    stat命令:元数据
        文件名,大小,时间戳,权限,属主、属组,对应的数据存储在哪些磁盘块上;

        index node: 索引区域中每个文件元数据条件
            每个inode都有其编号:ls -i

            如果某inode指向的常见类型的文件(f, d),指定向磁盘的数据区中的某个或某些个磁盘块

            目录:数据区存储的是(直接附属于此目录)文件名,以及与其对应的inode编号,
                dentry: 目录项

        格式化:创建文件系统

        bitmap:位图索引
            inode位图

            block bitmap

    块:块组

    super block:

    链接文件:
        /var/log/messages
        /tmp/log/abc inode: /var/log/messages

        一个inode可以被引用多次,其有计数器:在引用次为降为0之前是不会被标记为未用的。

        两个路径的文件名:指向同一个inode,此时,一个文件就称为另一个文件的硬链接

    创建链接:
        ln [-sv] SRC DEST

        硬链接:
            不能对目录文件创建硬链接;
            硬链接不能跨分区
            创建硬链接会增加inode引用计数

        符号链接:
            可以对目录创建
            不受分区限制
            对文件创建符号链接不会增加引用计数


    文件被删除:inode被标记为空闲,此inode指向的磁盘块被标记为空闲;
        如果inode被引用了多次,且此次删除未使得其引用计数降低为的话,这意味着文件被删除仅删除了一个访问路径;

    文件复制:创建一个新文件,并原文件中数据在新文件指向的磁盘块中再写一次的过程;

    文件移动:
        在同一个分区移到:移动文件仅是改变了文件访问路径;
        跨分区移到:在新分区创建文件,把数据复制过去,删除原分区数据;

Linux的文件系统的类型:
    ext(2,3,4), xfs, ffs, ufs, reiserfs, jfs, vfat(fat32), ntfs

    交换文件系统:swap

    网络文件系统:nfs, smbfs(cifs)

    分布式文件系统:ceph

    光盘文件系统:isso9660

    btrfs, 

磁盘管理:

I/O设备:
    磁盘
    网卡

文件:read, write, open, close

设备文件:特殊文件
    只有inode,而没有数据

    关联至一个驱动程序,进而跟对应的硬件设备打交道;

    /dev: b, c

        设备号:
            主设备号:用于标记设备类型
            次设备号:用于标记同一类型中的不同设备

        mknod [OPTION]... NAME TYPE [MAJOR MINOR]

        设备文件的命名:由ICANN

磁盘设备文件:
    /dev/hd:
        IDE: 并口, 133MB/s
    /dev/sd:
        USB: 串行
        SATA: 串行,6Gbps/8
        SCSI: 并行,(Small Computer System Interface)
        SAS:串行,

    /dev/sd[a-z]
        分区:数字
            /dev/sda1
            /dev/sda2

            分区编号:
                主+扩展:1-4
                逻辑:5

硬盘分区:
    磁道:track
        扇区:sector

    柱面:cylinder:
        分区根据柱面划分


    MBR:Master Boot Record
        主引导记录
        512Bytes: 引导启动OS
            446bytes: 程序,bootloader
            64bytes: 分区表,每16bytes标记一个分区,一共4分区
            2bytes: 5A, MBR有效性标记

        1T: 3主+1扩展(切割1个或多个逻辑)

    /proc: 

分区创建:
    查看:fdisk -l [DEVICE]...

    创建分区:fdisk [DEVICE]
        交互式界面,有许多子命令
            p: 显示磁盘分区表
            n: new,新建分区
            d: delete,删除分区
            t: 修改分区的系统ID
            l: 列表出所有已经的系统ID
            w: 保存并退出
            q: 不保存退出

        对于已经有分区处于使用状态的磁盘来讲,新建分区后需要让内核重读其分区表:
            CentOS 5:
                # partprobe [DEVICE]
            CentOS 6:
                partx -a [DEVICE]
                kpartx -af  [DEVICE]

        分区创建工具:sfdisk和parted

练习:写一个脚本
    1、提示输入一个对其执行分区的新硬件设备文件;
    2、提醒用户接下来的操作销毁所有的数据,你继续吗?
        y或yes: 继续
        n或no:退出
        其它字符:提醒输错了,再来一次;
    3、对磁盘新建分区:
        主分区1:大小512M,
        主分区2:大小2G
    4、创建完成后显示创建的结果;

回顾:
Linux文件系统:ext(2,3,4), xfs, reiserfs(suse),
VFS

    硬链接和符号链接:

    设备文件:
        b
        c

        mknod [option] NAME TYPE [MAJOR MINOR]

            /dev/null: 软件模拟的设备

    /dev/sd[a-z]#
        1-4: 
        5+: 

        IDE:/dev/hd

    分区:柱面 cylinder

    fdisk, sfdisk, parted

创建文件系统:
mkfs : make file system
-t FSTYPE [DEVICE]

    mkfs -t FSTYPE = mkfs.FSTYPE
        mkfs -t ext4 = mkfs.ext4

注意:CentOS
    Linux内核是模块化的,这些模块支持动态装载和卸载;
        文件系统可能会被直接打包进内核,也可以被编译成内核模块;

            # lsmod 

    如果期望将某分区格式化成某特定文件系统,通常需要一个与之对应的在用户空间可使用命令行工具来实现;
        # yum -y install xfsprogs

    文件系统的日志功能:Journal
        ext2: 无日志功能
        ext3, ext4, xfs: 日志文件系统

mke2fs:
    -t {ext2|ext3|ext4}:指定文件系统 
    -b {1024|2048|4096}:指定块大小
    -L LABEL: 打标
    -j: 相当于 -t ext3
    -i #: 每多少字节给创建一个inode,此字节数不应该少小块大小
    -N #: 直接指定可用的inode数;
    -m #: 指定预留空间占整个分区空间的百分比;默认为5;

    -O:指定分区特性


blkid: 查看指定块设备的信息

e2label:查看或设定卷标
    e2label DEVICE [LABEL]

查看超级块信息:
    # tune2fs -l DEVICE
    # dumpe2fs -h DEVICE

修改分区属性:tune2fs
    块大小无法调整;

    -j: ext2 --> ext3
    -L LABEL:修改卷标
    -m #: 修改预留空间百分比;
    -O [^]FEATURE: 启用指定特性,特性前加^,表示关闭此种特性

    -o [^]mount-options: 开启或关闭指定的挂载选项

因进程意外中止或系统崩溃等情况导入写入操作非正常中止时,可能会导致文件损坏;此时,应该修复文件系统:
    注意:离线修复

    fsck
        -t fstype
        -a: 自动修复错误
        -r: 交互式修复错误

    e2fsck: 专用于修改ext系列文件系统
        -y: 对问题自动回答为yes 
        -f: 强制进行检测

补充:windows不能识别Linux的文件系统
    U盘的文件系统FAT32
        # mkfs -t vfat 

交换分区:swap
    缓解物理内存资源不够用的情况;

    创建交换分区:
        mkswap [-L LABEL] DEVICE

文件系统挂载:默认只有管理员才有权限
    将额外的分区与根文件系统上的某目录建立关联关系的过程;
        目录中的原有文件会被隐藏

    挂载点:另一个文件系统的访问入口

    挂载: mount DEVICE MOUNT_POINT

        固定挂载点:/mnt, /media

        mount [option]... [-t fstype] [-o option]  设备  挂载点
            挂载点:
                1、事先存在;
                2、使用空闲目录;

            常用的挂载选项:
                -t fstype:指定文件系统类型
                -r: readonly, 只读挂载
                -w: read and write, 读写挂载
                -L LABEL:以卷标方式指定设备, mount -L MYDATA 挂载点
                -U UUID: 以UUID的方式指定设备,mount UUID='uuid' 挂载点, mount -U uuid 挂载点
                -a: 自动挂载所有(/etc/fstab文件中定义的)的支持自动挂载设备
                -n: 挂载时,不更新/etc/mtab文件

            -o option: 
                async:异步I/O,数据写操作先于内存完成,而后再根据某种策略同步至持久设备中
                sync: 同步I/O,
                atime/noatime: 文件和目录被访问时是更新最近一次的访问时间戳
                auto/noauto:设备是否支持mount的-a选项自动挂载
                diratime/nodiratime: 目录被访问时是更新最近一次的访问时间戳
                dev/nodev: 是否支持在此设备上使用设备;
                exec/noexec: 是否允许执行此设备上的二进制程序文件
                suid/nosuid: 是否支持在此设备的文件上使用suid
                remount: 重新挂载,通常用于不卸载的情况下重新指定挂载选项
                ro: 只读
                rw: 读写
                user/nouser: 是否允许普通挂载此文件设备
                acl: 在此设备是支持使用facl,默认不支持;

            例如:以指定挂载后支持acl为例:
                方法1:
                    mount -o acl DEVICE MOUNT_POINT

                方法2:
                    tune2fs -o acl DEVICE
                        为设备设定默认挂载选项

                    mount DEVICE MOUNT_POINT


        查看所有已经挂载的设备:
            # mount
            # cat /proc/mounts
            # cat /etc/mtab

            卸载:挂载点没有被进程访问时方可以卸载 ;


    卸载:umount DEVICE
          umount MOUNT_POINT

         查看哪些进程正在访问挂载的设备:
            fuser -v 挂载点

         中止正在此挂载点的进程:
            fuser -km 挂载点

    df: disk free
        -h: human-readable
        -i: 显示inode的使用信息而非默认的磁盘空间使用信息

    du: disk usage
        -s: 
        -h: 

    练习:创建一个20G的分区,块大小为2048,预留百分比为3,卷标为MYDATA,要求挂载后支持acl,使用UUID的方式挂载至/mydata目录;
        使用重新挂载的功能,让其不支持dev功能;

交换分区:
    mkswap

    free: 查看内存及交换分区的使用信息

    启用某交换分区设备
        swapon [DEVICE]
            -a: all, 启用所有交换分区
            -p #: 指定此交换设备的优先级

    禁用某交换分区设备
        swapoff [DEVICE]
            -a: 禁用所有

自动挂载的设备的配置文件:/etc/fstab
    6字段:
        挂载的设备:
            设备文件
            LABEL
            UUID
        挂载点:
        文件系统类型
        挂载选项:
            挂载选项可以有多个,彼此间使用逗号分隔;
        转储频率:
            0:从不转储
            1: 每天转储
            2: 每隔一天
        自检次序:
            0:不自检,额外创建的文件系统都无须自动自检
            1:首先自检,通常只有根文件系统需要首先自检
            2:次级自检,不同的设备可以使用同一个自检次序
            3
            ...



练习:写一个脚本,完成如下功能
    1、列出当前系统上的所有磁盘设备;
    2、让用户选择一个磁盘设备,并在选择后显示指定设备上的所有分区信息;
    3、询问用户是否擦除此磁盘上的所有现存分区后重新添加三个分区;
        y或yes: 继续
        n或no: 中止脚本
        其它字符则提醒用户重新输入合法的字符
    4、在用户选择是后执行相应的分区操作
        创建三个分区
            主分区1:512M,ext4
            主分区2: 512M,swap
            主分区3:2G,ext4
    5、将创建的分区按如上说明分别格式为相应的文件系统;
    6、将主分区1挂载至/mnt/boot目录,主分区3挂载至/mnt/sysroot目录;

    扩展:在上述第3个步骤开始之后,先查看此设备上是否有分区被挂载,如果有,则先卸载之;

    # fdisk -l | awk '/^Disk \/dev\/[sh]d[a-z]/{print $2}' | tr -d ':'
    /dev/sda
    /dev/sdb

回顾:
/etc/fstab:
挂载的设备:
设备文件:/dev/sda3
LABEL:LABEL=MYDATA
UUID:UUID=
挂载点:
文件系统类型:swap, ext4, xfs
挂载选项:defaults,
转储频率
自检次序

tune2fs:
    -m

df 
    -h
    -i

命令总结:fdisk, mkfs, mke2fs, mkswap, mount, umount, swapon, swapoff, fsck, e2fsck, dumpe2fs, tune2fs, df, du, mknod, ln, free, e2label, blkid, fuser

Linux RAID

IDE, SCSI

RAID: Redundant Array Inexpensive Disks

RAID: Independent

RAID Level
    raid0: 读、写性能提升,无容错能力,空间n*disk
    raid1: 写性能略有下降,读性能提升,容错,空间:1*disk
    raid4: 读、写性能提升,有容错能力(最多坏一块磁盘),空间:(n-1)*disk
        1 & 0 = 1
    raid5: 读、写性能提升,有容错能力(最多坏一块磁盘),空间:(n-1)*disk

    raid10, raid01

    raid10: 读、写性能提升,有容错能力(每一组可坏一块盘),空间:n*disk/2

    raid6: 有两块校验盘,容许同时坏两块,至少需要4块盘,空间:(n-2)*disk

md: multidisks
    mdadm

    ext4(kernel)
    mke2fs(user)

dm: device mapper
    lvm 

mdadm工具:
    md: 支持将任何块设备组织成RAID

        sda, 
        raid5: sda1, sda2, sda3
            3*200G: 400G

    mdadm: 模块式化命令
        -A: 装配模式,重新识别此前实现的RAID
        -C:创建模式,创建RAID
        -F:监控模式

        管理模式:-f, -r, -a

    -C: 创建模式中专用选项
        -n #: 用于创建RAID设备的磁盘个数;
        -l #: 级别
        -a yes: 自动为创建的RAID生成设备文件;
        -c Chunk_Size: 

        md设备的设备文件,一般在/dev目录下,以md开头,后跟一个数字来区别

        # cat /proc/mdstat
            /proc/mdstat: 当前系统上所有已启用的软件RAID设备及其相关信息

    例如:创建一个10G空间的RAID0
        # mdadm -C /dev/md0 -a yes -n 2 -l 0 /dev/sdb{1,2}

    例如:创建大小为10G空间的RAID5:
        3*5G,6*2G
            (n-1)*2G

        # mdadm -C /dev/md1 -a yes -n 3 -l 5 /dev/sda{3,5} /dev/sdb3

RAID: 组织多块硬盘当一个设备来使用
    硬件RAID:
        硬件控制器:创建RAID通过BIOS进行
            在OS中看到的仅是一个单独的设备

    软件RAID:
        无需任何硬件的RAID设备,仅需多个块设备(磁盘分区即可)
            在OS中看到的是多个基本的磁盘设备、磁盘分区等,而后将这多个块设备可以组织一个单独的设备使用
            即为软RAID


        装配模式:在某OS上创建的软件RAID,被迁移到其它主机上,并启动OS之后,
            Linux auto detect

    mdadm: 命令行工具,结果md模块实现软件RAID
        模式化工具:-C, -F, -A, 
            -a, -r, -f

        mdadm -D /dev/md#
            显示指定的软RAID的详细信息

        mdadm /dev/md# -f /dev/some_device
            将/dev/md#中的/dev/some_device手动设置为损坏

        mdadm /dev/md# -r /dev/some_device
            将/dev/md#中的损坏状态的/dev/some_device移除

        mdadm /dev/md# -a /dev/new_device
            新增设备

    练习:创建一个10G的RAID1?

    练习:创建一个可用空间为10G的RAID5设备,要求其chunk大小为256K,文件系统为ext4,开机可自动挂载至/backup目录,支持acl功能;有一个空闲盘;
    练习:创建一个可用空间为10G的RAID1设备,chunk大小为1024k,有一个空闲盘,开机自动挂载至/users目录,不支持dev设备文件;

停止软件RAID:
    mdadm -S /dev/md#

重新启用RAID:
    mdadm -A /dev/md# /dev/DEVICE...

    mdadm的配置文件/etc/mdadm.conf

RAID:理解RAID各级的特性


watch [-n #] <COMMAND>:
    阶段性地执行指定的COMMAND
        -n #: 指定间隔时间

bash编程:
循环:
循环次数已知:遍历
for
循环次数未知:
while
until

for格式:
    for 变量名 in 列表; do
        循环体
    done

    循环体:依赖于调用变量来实现其变化;

    循环可以嵌套;

    退出条件:遍历列表完成

while格式:


    while 测试条件; do
        循环体
    done

    测试条件为真,进入循环;测试条件为假,退出循环;
        测试条件一般通过变量来描述,需要在循环体不变量地改变变量的值,以确保某一时刻测试条件为假,进而结束循环;

until格式:


    until 测试条件; do
        循环体
    done

    测试条件为假,进入循环;测试条件为真,退出循环;
        测试条件一般通过变量来描述,需要在循环体不变量地改变变量的值,以确保某一时刻测试条件为真,进而结束循环;

for的第二种使用格式 :
    for ((初始条件;测试条件;修改表达式)); do
        循环体
    done

    求100以内所有正整数之和:
        while的实现:

            #!/bin/bash
            declare -i counter=1
            declare -i sum=0

            while [ $counter -le 100 ]; do
                let sum+=$counter
                let counter++
            done

            echo $sum

        for的实现:
            #!/bin/bash
            #
            declare -i sum=0

            for ((counter=1;$counter <= 100; counter++)); do
                let sum+=$counter
            done

            echo $sum

        练习:求100以内所有偶数之和;

            declare -i evensum=0
            for ((counter=2; $counter <=100; counter+=2)); do
                let evensum+=$counter
            done

while循环:遍历文本文件

    格式:

    while read 变量名; do
        循环体
    done < /path/to/somefile

    变量名,每循环一次,记忆了文件中一行文本

    
    练习:显示其ID号为偶数的用户的用户名、ID号和SHELL

        #!/bin/bash
        #

        while read line; do
            userID=`echo $line | cut -d: -f3`
            if [ $[$userID%2] -eq 0 ];then
                echo $line | cut -d: -f1,3,7
            fi
        done < /etc/passwd

    练习:显示ID号为偶数,且ID号同GID的用户的用户名、ID和SHELL;
    while read line; do
        userID=`echo $line | cut -d: -f3`
        groupID=`echo $line | cut -d: -f4`
        if [ $[$userID%2] -eq 0 -a $userID -eq $groupID ]; then
                echo $line | cut -d: -f1,3,7
            fi
        done < /etc/passwd              

    练习:显示当前系统上所有挂载的文件系统中空间使用百分比大于10的设备和空间使用百分比;使用while循环实现;

        提示:此题目可以使用管道

回顾:
RAID, md, mdadm, for, while

容错:1, 4, 5, 6, 10
写性能:0, 4, 5, 6, 10
raid5: D
    (n-1)*D
    6: (n-2)*D
    10: n*D/2

LVM: Logical Volumn Manager
lvm, lvm2

dm: device mapper

将一个或多个底层块设备组织一个逻辑的工具

lv, multipath

Block Devices:
    Pysical Extent
        PE: 大小固定

    存储空间边界:
        物理边界:
        逻辑边界

    逻辑卷:
        扩展:物理 --> 逻辑
        缩减:逻辑 --> 物理
            缩减不能少于已经存储的所有数据空间的大小

    卷组: 

    快照:snapshot

        数据:100G

LVM:
    块设备:分区,RAID
        pv --> vg --> lv

        pv:
            pvcreate, pvs, pvdisplay, pvremove, pvmove, pvscan
        vg:
            vgcreate, vgs, vgdisplay, vgremove, vgextend, vgreduce, vgscan
        lv:
            lvcreate, lvs, lvdisplay, lvremove, lvextend, lvreduce, lvscan

        例如:10G的vg,
            1:10G PV
            2: 3+7G PV

    创建逻辑卷:
        lvcreate
            -n lv_name
            -L #UNIT   {mMgGtT}
            VG_NAME

        lv的访问路径:
            1、/dev/VG_NAME/LV_NAME
                /dev/myvg/mylv

            2、/dev/mapper/VG_NAME-LV_NAME
                /dev/mapper/myvg-mylv

            此两者均为符号链接,指向的文件为/dev/dm-#


    如何扩展逻辑卷:
        1、先确定扩展的目标大小;并确保对应的卷组中有足够的空闲空间可用;
            2G, 目标为4G
                +2G
                4G
        2、扩展物理边界
            lvextend -L 4G /dev/myvg/mylv
        3、扩展逻辑边界
            resize2fs  /dev/myvg/mylv

缩减很危险!!!!
    缩减要离线
    1、先确定缩减后的目标大小;并确保对应的目标逻辑卷大小中有足够的空间可容纳原有所有数据;
    2、先制裁文件系统,并要执行强制检测
        e2fsck -f 
    3、缩减逻辑边界
        resize2fs DEVICE
    4、缩减物理边界
        lvreduce

        慎独

创建快照卷:
    lvcreate 
        -L 
        -n
        -s 
        -p r

    注意:快照卷是对某逻辑卷进行的,因此必须跟目标逻辑卷在同一个卷组中;无须指明卷组;

练习:
1、创建一个由至少两个物理卷组成的大小为10G的卷组;要求,PE大小8M;而后在卷组中创建大小为5G的逻辑卷mylv1,格式化为ext4文件系统,开机自动挂载至/users目录;
2、新建用户mageedu,其家目录为/users/mageedu,而后su至mageedu用户,复制/etc/fstab文件至自己的家目录;
3、扩展mylv1至7G,确保/users/mageedu的数据不受影响;而后su至mageedu用户,验正数据可正常访问;
4、缩减mylv1至4G,确保/users/mageedu的数据不受影响;而后su至mageedu用户,验正数据可正常访问;
5、对mylv1创建快照卷snap-mylv1,并通过其cp内部的数据至/backups/目录中,要求保留原有属主属组等信息;

逻辑卷

dd
if=/path/to/src_file
of=/path/to/dest_file
bs=256K
count=#

100M

dd if=/dev/zero of=/dev/sdb bs=512 count=1

/dev/null: 吞进所有数据,直接丢弃
/dev/zero: 泡泡机,吐零

dd if=/dev/sdb of=/backup/mbr.backup bs=1 count=512
dd if=/backup/mbr.backup of=/dev/sdb bs=512 count=1

swap空间吃紧,创建新的swap设备

Linux压缩和解压缩工具

压缩:根据一定算法
    文本文件

compress/uncompress, .Z

gzip/bzip2/xz

    gzip/gunzip
            后缀名:.gz
        -#: 压缩比,默认为6,范围为0-9;
        -d : gunzip
        -c: 将压缩后的结果输出至标准输出,
            gzip -c /path/to/somefile > /path/to/somecfile.gz

        zcat somefile.gz: 不解压查看gzip压缩后的文件的内容

    bzip2/bunzip2
        .bz2
        -#: 压缩比,默认为6,范围为1-9;
        -d: bunzip2
        -k: 保留原文件

        bzcat somefile.bz2: 


    xz/unxz
        .xz
        -#: 压缩比,默认为6,范围为0-9;
        -d: unxz
        -k: 保留原文件

        xzcat somefile.xz

    zip/unzip
        zip ZIPFILE.zip src_file...
        unzip ZIPFILE.zip

归档工具:tar
    能实现将多个文件打包成单个文件,即为归档文件

    tar [option]... -f tarfile.tar src_file...

    创建归档:
        tar
            -c: create
            -f FILE.tar: 指定归档后的文件
            -v: 显示执行过程

    展开归档:
        tar 
            -x: extract
            -v:
            -f FILE.tar

    查看归档后的文件中包含了哪些原文件:
        tar
            -t: 
            -f FILE.tar

    tar可直接通过选项调用压缩工具执行压缩或解压:
        -z: gzip
        -j: bzip2
        -J: xz

cpio: 

命令总结:dd, gzip, gunzip, zcat, bzip2, bunzip2, bzcat, xz, unxz, xzcat, zip, unzip, tar

挂载光盘:
mount /dev/cdrom /media/cdrom

文件系统:iso9660

eject

挂载U盘:

练习:写一个脚本
1、显示如下信息:
Plz choose a compress tool:
用户可键入:gzip, bzip2或xz;
2、提醒用户指定要归档压缩的文件
3、将用户归档压缩至/tmp目录中,文件名为原名加上相应的后缀;

网络配置与管理:

冲突域:
    网桥:
    多接口:交换机

    学习:

广播域:

8位2进制数据:0-255

0-255.0-255

1.1 --> 2.2

1111 1111. 0000 0000

1.0
2.0

IP: 4段
1.1.1.1

32位:
大:0 000 0000 - 0 111 1111:0-127
中:10 00 0000 - 10 11 1111:128-191
小:110 0 0000 - 110 1 1111:192-223
d 1110 0000 - 1110 1111:224-239
e 1111 0000 - 1111 1111:240-255

全0:网络地址
全1:广播地址

A:1-126
126个网络
每个网络中的主机:2^24-2
B:128-191
2^14个网络
每个网络中的主机:2^16-2
C:192-223
2^21个网络
每个网络中的主机:2^8-2

172.16.0.0
255.255.0.0

172.16.0.0/255.255.255.0
172.16.255.0/255.255.255.0

172.16.255.255

192.168.0.0/255.255.255.0 --> 192.168.255.0/255.255.255.0

192.168.0.0/255.255.0.0

子网,超网

IANA, ICNAA

A类:
1-126个网络,127用于回环,2^7-1
容纳的主机数:2^24-2
默认掩码:255.0.0.0
主机位全0:网络地址
主机位全1:广播地址

B类:
2^14个网络
容纳的主机数:2^16-2
默认掩码:255.255.0.0

C类:
2^21个网络
容纳的主机数:2^8-2
默认掩码:255.255.255.0

A类:
1个:10.0.0.0/255.0.0.0

B类:
16个:172.16.0.0/255.255.0.0-172.31.0.0/255.255.0.0

C类:
256个:192.168.0.0/255.255.255.0-192.168.255.0/255.255.255.0

路由表:
静态设置
动态生成

cost: 成本
    经过的跳数越少就越小
    时长

    路由协议:RIP2, OSPF, EIGRP
    可路由协议:IP协议

物理介质:物理层,物理层协议
链路层:数据帧,链接层协议
网络层:数据包,IP协议
传输层:传输层 (TCP,UDP)
TCP:0-65535
UDP:0-65535
应用层:标记资源

端口:用于标记进程
0-65535:

Socket: IP:port
172.16.100.7:80
172.16.100.8:80

协议栈:内核
TCP/IP协议簇

主机名:FQDN
Full Qulified Domain Name
www.magedu.com

名称解析:DNS

MTU:Maximum Translate Unit

Fragment: IP分片

有限状态机

FSM: Finite State Machine

网络基本知识:
TCP/IP:
物理层:
链路层:MAC
网络层:IP报文
传输层:TCP/UDP
应用层:

链路层:从设备到设备主机通信,MAC地址,IP<-->MAC (ARP/RARP)
    MTU:
网络层:从源主机到目标主机之间通信,IP地址,IP报文
传输层:从源主机进程到目标主机特定进程之间通信,TCP/UDP
应用层:

ISO/OSI:七层
    1-4:通信
    5-7:资源
        会话层
        表示层
        应用层

TCP:有连接协议,建立逻辑连接
    SYN, ACK, FIN, RST, PSH, URG

    三次握手:
        SYN=1, ACK=0, FIN=0
        SYN=1, ACK=1, FIN=0
        SYN=0, ACK=1, FIN=0

    四次断开:

    有限状态机:

主机:TCP/IP协议栈

回顾:IPV4:5类地址:
A:10.0.0.0/8
B: 172.16.0.0/16, 172.31.0.0/16
C: 192.168.0.0/24, 192.168.255.0/24
D
E

OSI:7 layers
    4 :
        TCP, UDP        

tcp三次握手:
    1次:SYN=1,ACK=0,FIN=0
    2次:SYN=1, ACK=1, FIN=0
    3次:SYN=0,ACK=1,FIN=0

A --> B, B --> A

IP首部,TCP首部

VLAN: 

Linux网络属性配置:
IP/NETMASK
路由:
主机路由
网络路由
默认网关
DNS服务器:
主DNS服务器
备用DNS服务器
主机名

配置网络属性:
    静态配置
    动态配置:DHCP
        Dynamic Host Configuration Protocol
        

配置IP:
    用户空间工具:ifconfig (net-tools), ip (iproute2)
    网络设备服务配置文件: /etc/sysconfig/network-scripts/
        主机名:/etc/resolv.conf
    GUI/TUI

网络设备的配置方式:
    内核识别硬件设备:驱动
        
    设备名称:
        以太网:ethX
            eth0, eth1, eth2, ...
        PPP网络:pppX
        loopback: 本地回环,lo

ifconfig:
    默认为显示所有处于激活状态的连接
    -a

    ifconfig IFNAME:仅显示指定接口的信息
    ifconfig IFNAME ADDRESS
        ip/mask
            长格式:ifconfig IFNAME IP netmask MASK
            短格式:ifconfig IFNAME IP/MASK

route: 
    route:显示路由信息
        -n: 数字格式的地址

    route add
        -host:目标为主机
            -host HOST_IP gw NEXT_HOP [dev DEVICE]
        -net:目标是网络
            -net NET_ADDRESS gw NEXT_HOP [dev DEVICE]

            -net 0.0.0.0: 表示目标为任意地址

        route add default gw GW_ADD
    
    route del
        -host HOST_IP
        -net NET_ADDRESS

DNS服务器地址:
    本地解析: /etc/hosts
    DNS服务器解析:指定DNS服务器地址

    dig -t A FQDN
        Full Qualified Domain Name
        www.magedu.com

    dig -x IP:
        反解IP至FQDN

使用命令配置的信息直接送往内核(TCP/IP协议栈)并立即生效;

IP/NETMASK:
    配置文件有两类(/etc/sysconfig/network-scripts):
        配置IP、掩码和网关:
            以太网:ifcfg-IFNAME
            PPP: ifcfg-pppX
        配置路由:route-IFNAME

    CentOS 5: /etc/rc.d/init.d/network
    CentOS 6: /etc/rc.d/init.d/network
            /etc/rc.d/init.d/NetworkManager

/etc/rc.d/init.d/,/etc/init.d/*
    SysV风格的脚本:多数脚本都用于控制Linux的后台进程,接受参数{start|stop|restart|status}
    
    # /etc/init.d/network start
    # service network start 
    
    配置某服务是否开机自动运行:
        # chkconfig SRVNAME on|off
    查看哪些服务开机自动运行:
        # chkconfig --list 


ifcfg-IFNAME配置文件的格式:
    DEVICE=IFNAME: 此配置文件所关联到的设备,设备名称要与本文件名ifcfg-后面保持一致; 
    BOOTPROTO={bootp|dhcp|static|none}
    HWADDR=00:11:22:33:44:55:66 :当前设备的MAC地址; 
    NM_CONTROLLED={yes|no}: 是否接受NetworkManager服务脚本来配置此设备; 
    ONBOOT={yes|no}: 是否在开机过程中,自动激活此接口
    TYPE={Ethernet|Bridge}: 网络接口类型
    UUID=
    IPADDR=
    NETMASK=
    GATEWAY=
    DNS1=
    DNS2=
    IPV6INIT={yes|no}
    USERCTL={yes|no}: 是否允许普通用控制此接口
    
    PEERDNS={yes|no}: 不接受DHCP服务器指派的DNS服务器地址

route-IFNAME: 
    配置文件的格式1:每行一个路由条目
        DESTINATION via NETX_HOP

    配置文件格式2: 每三行一个路由条目
        ADDRESS#=DESTINATION
        NETMASK#=MASK
        GATEWAY#=GW

如何配置主机名:
    hostname
    hostname HOSTNAME

    配置文件:/etc/sysconfig/network
        HOSTNAME=主机名


如何在一个网络接口配置多个IP地址:

    通过网络接口的别名来实现:IFNAME:#
        ens33, ens33:0, ens33:1, ens33:2
        eth0,eth0:0, eth0:1

    命令配置:立即生效
        ifconfig IFALIAS IP

    配置文件配置:别名不支持使用DHCP进行配置
        ifcfg-IFALIAS
            DEVICE=IFALIAS
            BOOTPROTO={static|none}
            IPADDR=
            NETMASK=
            ONBOOT=
            USERCTL=


TUI或者GUI:
    TUI: system-config-network-tui
    GUI:system-config-network-gui

    setup --> Network Configuration


    修改的结果会保存至相应的网络接口的配置文件ifcfg-IFNAME,因此,不会立即生效;

网络管理相关的工具:
    ping: ICMP
        ping [option]... IP
            -c #: 报文的个数
            -W timeout: 等待响应报文的超时时长;

    traceroute: 
        traceroute HOST
            获取从当前主机到达目标主机所经由的所有网关;

    mtr HOST

    netstat: (ss)
        -t: tcp协议相关
        -u: udp协议相关
        -n: 显示数字格式的地址
        -l: listen,显示处于监听状态的连接
            -tunl
        -a: 所有状态的连接
            -tan
        -p: 显示会话中的进程程序名及进程号
        -r: routing,显示路由表
            -rn

        名称解析:
            FQDN <==> IP
            Service Name <==> PORT

显示网络接口设备的属性信息:
    ethtool IFNAME
        -S: 显示设备接口的统计数据

课外任务:nmap, ncat, tcpdump

ip命令:
    ip link : 管理接口
        show [IFNAME]
        set IFNAME {up|down}
            multicast {on|off}

        # ifconfig IFNAME {up|down}
        # ifup IFNAME
        # ifdown IFNAME

    ip addr: 管理协议地址
        ip addr {show|flush} [dev DEVICE] 

        ip addr {add|del} ADDRESS dev DEVICE  [label IFALIAS] [broadcast BCAST_ADDRESS]

            # ifconfig IFNAME ADDRESS broadcast BCAST_ADDRESS

    ip route: 管理路由
        ip route list

        ip route flush 

        ip route add DESTINATION [via NEXT_HOP] [src SOURCE_ADDRESS] [dev DEVICE]
        ip route del DESTINATION

命令总结:ifconfig, ifup, ifdown, route, netstat, ping, traceroute, mtr, ethtool, setup, dig, ip, ss

ss:
    -t: tcp
    -u: udp
    -p: process
    -l: listening
    -n: numeric
    -a: all
    -e: 扩展信息
    -m: 套接字相关的内存使用信息
    -o state {established,fin_wait_1, fin_wait_2, listening}
        '( dport =   or sport =  )'
        只显示指定状态的连接,还可以指定过滤条件

练习:写一个脚本
扫描172.16.250.0/16内的所有主机;在线的,使用绿色显示;不在线,使用红色显示;

最后分别显示:在线和不在线各有多少主机;

for (())
    if ping -c 1 -W 1 172.16.250.$host &> /dev/null; then

练习:写一个脚本
1、提示用户输入一个IP地址;如果用户输入的地址不正确,则提醒其重新输入直到正确为止;
2、如果正确,则添加至eth0上的辅助地址;
3、得出正确的掩码;

if [[ $ip =~  ]]; then
    ip addr add

Bonding的模式一共有7种:

define BOND_MODE_ROUNDROBIN 0 (balance-rr模式)网卡的负载均衡模式

define BOND_MODE_ACTIVEBACKUP 1 (active-backup模式)网卡的容错模式

define BOND_MODE_XOR 2 (balance-xor模式)需要交换机支持

define BOND_MODE_BROADCAST 3 (broadcast模式)

define BOND_MODE_8023AD 4 (IEEE 802.3ad动态链路聚合模式)需要交换机支持

define BOND_MODE_TLB 5 自适应传输负载均衡模式

define BOND_MODE_ALB 6 网卡虚拟化方式

bonding模块的所有工作模式可以分为两类:多主型工作模式和主备型工作模式,balance-rr 和broadcast属于多主型工作模式而active-backup属于主备型工作模式。(balance-xor、自适应传输负载均衡模式(balance-tlb)和自适应负载均衡模式(balance-alb)也属于多主型工作模式,IEEE 802.3ad动态链路聚合模式(802.3ad)属于主备型工作模式

回顾:
Linux网络功能:TCP/IP
IP包头,TCP包头

IP/NETMASK
路由
DNS服务器地址
主机名
    www.magedu.com

ifconfig, route, netstat, ip, ss

Linux程序包管理:

Linux: GPL, BSE, Apache,

    源程序包:C, C++, perl

        预处理--> 编译  --> 汇编 --> 链接

    库:功能模块
        名称、函数(参数)
            函数名,所能够接受的参数个数,类型

            输入输出、数学计算、字符串处理
                函数

            头文件:head

include <stdio.h>

库:程序(无执行入口,不能独立执行,只能被能独立运行的程序调用时执行)
    库:源代码 --> 二进制格式

应用程序程序员:开发环境 (API)
    依赖于:头文件
            库文件(开发库,运行库)

    POSIX API

终端用户:
    程序(编译完成)
        依赖于:
            静态编译
            动态编译:
                运行库
                dll, so (shared object)

            ABI: Application Binary Interface

源代码:终端用户
    安装:编译
        X86_64(64bits): 
        i686(32bits):
        ppc

    二进制格式:依赖于硬件平台

API:一种源代码
    arm: 编译出以后,严重依赖于arm

程序员:testapp.tar.gz

    testapp.x86_64
    testapp.i686
    testapp.arm

    testapp.noarch

有些程序不依赖于硬件运行,依赖于虚拟机,不再依赖于低层硬件平台,noarch

程序包的组成格式:
    二进制程序
        /bin, /sbin, /usr/bin, /usr/sbin, /usr/local/bin, /usr/local/sbin, /usr/local/APP/{bin,sbin}
        
        注意:
            有些特殊的应用程序放置于libexec目录中
            有些第三方应用默认安装于/opt目录
    库文件(开发库、运行库)
        /lib64, /usr/lib64, /usr/local/lib64, /usr/local/APP/lib
    配置文件
        /etc, /usr/local/APP/etc或conf目录
    帮助文件
        /usr/share/man, /usr/local/share/man, /usr/local/APP/man

        帮助文件:man, info, 
            doc: README, INSTALL, ChangeLog

    ldd:
        ldd /path/to/binary_file


程序包管理器:
    1、数据库
        程序名及版本
        依赖关系:X --> Y,Z 
        功能性说明
        安装生成的各文件路径及校验码
    2、程序的组成清单
        文件清单
        安装卸载时运行的脚本

    功能:将编译好的程序打包成一个文件或有限的几个文件,可用于实现安装、卸载、升级、查询等功能;

应用程序的命名格式:
    源代码:name-version.tar.{gz,bz2,xz}
        version: major.minor.release

        name-major.minor.release.tar.gz
            bash-4.2.3.tar.gz



包管理器:
    Debian: dpkg, .deb
    RedHat: rpm(redhat package manager), .rpm
        RPM is Package Manager.

包管理器的功能:
    打包
    安装
    卸载
    升级
    校验
    数据库管理

程序间的依赖关系:繁杂
    X --> Y,Z 
        Y--> M,N
        Z --> A,B

前端工具
    dpkg --> apt-get
    rpm --> yum 

程序包管理器:
    打包:包括编译,打包

1、rpm包
2、yum
3、源代码编译安装

rpm包的使用:

源代码:
    name-version.tar.{gz,bz2,xz}
        version:major.minor.release

rpm包的命名格式
    name-version-relase.arch.rpm

        version: major.minor.release,同源代码
        release: rpm自身的发行号,与程序源码的发行号无关,仅用于标识对rpm包不同制作的修订;同时,release还包含此包适用的OS
            bash-4.2.3-3.centos5
        arch: 适用于的硬件平台,
            x86: i386, i486, i586, i686等;
            x86_64: x86_64
            powerpc: ppc
            noarch: 依赖于虚拟机
                例如:bash-4.2.3-3.centos5.x86_64.rpm

    一个程序有20个功能:常用功能有8个,特殊A:3个,特殊B:6个,二次开发相关功能:3
        分包机制:
            核心包,主包:命名与源程序一致
                bash-4.2.3-3.centos7.x86_64.rpm
            子包:
                bash-a-4.2.3-3.centos7.x86_64.rpm
                bash-b-4.2.3-3.centos7.x86_64.rpm
                bash-devel-4.2.3-3.centos7.x86_64.rpm

            OS Vendor: 系统发行商提供的包

        获取rpm包的途径:
            1、发行的光盘或站点服务器
                镜像:
                    http://mirrors.163.com
                    http://mirrors.sohu.com
            2、项目的官网
                源代码
                rpm包
            3、很多第三方机构或个人制作并公开发布许多rpm包
                http://rpmfind.net
                http://rpm.pbone.net

            可靠的途径:EPEL
                Fedora-EPEL

    rpm包的合法性验正:
        包制作者制作完成之后会附加数字签名于包上;
            来源合法性
            包的完整性

            包的制作者使用单向加密提取原始数据的特征码,而后使用自己的私钥加密这段特性码,附加原始数据后面。
            验正过程:
                前提:必须有可靠机制获取到包制作者的公钥;
                1、使用制作者的公钥解密加密的特征码,能解密则意味着来源合法;
                2、使用与制作者同样的意向加密算法提取原始数据的特征码,并与解密出来的特征作比对,相同,则意味着完整性没问题;

rpm包管理器的常见使用场景:


    安装程序包:
        rpm [option] /path/to/package_file 
            -i: install
            -v:
            -vv:
            -vvv:
            -h: 

            组合选项:-ivh

            --test: 仅作测试,有真正执行安装

            如果依赖于其它包:
                1、解决依赖关系
                2、忽略依赖关系
                    能安装上,但有可能无法运行;
                    --nodeps

            重新安装:
                --replacepkgs

                    如果原有配置文件作了修改,很有可能不执行替换,而是将应该安装生成的配置文件重命名为 .rpmnew

    卸载程序包:
        rpm [option] package_name
            -e: erase

            如果被其它包所依赖:
                1、将依赖于此包的所有包一并卸载
                2、忽略依赖关系
                    能卸载,但依赖于此包程序包可能会运行不正常;
                    --nodeps

            如果包的配置文件安装后曾被改动过,卸载时,此文件将不会卸载,而是被重命名并保留,例如
                warning: /etc/zprofile saved as /etc/zprofile.rpmsave

    升级程序包:
        新版本替换老版本
        rpm [option] /path/to/package_file
            1、升级或安装
                -Uvh

            2、纯升级
                -Fvh

            X --> Y-2.2.1
                Y-2.2.3
                升级后的版本冲突等;

            --force: 强制升级

        注意:不应该对内核执行升级操作,而是安装
            系统允许多内核并存

    查询操作:
        1、查询某包是否安装
            rpm -q package_name...

        2、查询所有已经安装的包
            rpm -qa 

            按条件过滤:rpm -qa | grep 'PATTERN'

        3、查询包的描述信息
            rpm -qi package_name

        4、查询某包安装生成了哪些文件
            rpm -ql package_name

            (1) 查询某包安装生成了哪些配置文件
            rpm -qc package_name

            (2) 查询某包安装生成了哪些帮助文件
            rpm -qd package_name

            (3) 查询程序包的相关脚本
            rpm -q --scripts package_name

                脚本有四类:
                    preinstall:安装前脚本
                    postinstall: 安装后脚本
                    preuninstall: 卸载前脚本
                    postuninstall: 年前后脚本

        5、查询某文件是由哪个包安装生成的
        rpm -qf /path/to/some_file

        6、对尚未安装的包执行查询
        rpm [option] /path/to/package_file
            -qpi
            -qpl
            -qpc
            -qpd


    校验:
        用于检查包安装生成的文件属性是否发生变化

        rpm -V package_name

           S file Size differs
           M Mode differs (includes permissions and file type)
           5 digest (formerly MD5 sum) differs
           D Device major/minor number mismatch
           L readLink(2) path mismatch
           U User ownership differs
           G Group ownership differs
           T mTime differs
           P caPabilities differ

          某属性无变化,显示为.

rpm包来源合法性及完整性检验:

    前提:在当前系统上导入包的制作者的公钥
        导入:
            rpm --import /path/to/key_file

            # rpm -qa gpg-pubkey*
            显示所有已经导入的gpg格式的公钥

            # rpm -qi gpg-pubkey-NAME
            显示密钥的详细信息

        检查包:安装过程中会自动执行

        手动检查:
            rpm -K /path/to/package_file
            rpm --checksig /path/to/package_file

                不检查包完整性:
                    rpm -K --nodigest
                不检查来源合法性:
                    rpm -K --nosignature

数据库重建:
    数据库目录:/var/lib/rpm

    重建:
        rpm --initdb:初始化
            如果事先没有库,会新建一个;如果有,则不新建;

        rpm --rebuilddb: 重建
            直接重建,覆盖原有的数据库

总结:安装、卸载、查询、升级、校验、公钥导入、合法性验正、库重建

第三篇博客作业:rpm包管理

Linux: dpkg, rpm
debian
centos

制作包:
    分包机制:
        核心包(name)、子包(name-subfunction)

    spec: 编写此文件

rpm
    安装:
        X --> Y,Z

    rpm --> yum
         YUM --> Yellowdog Update Modifier

    C/S架构:Client --> Server
        X --> Y,Z

        yum repository: yum仓库
            数据:
                各个rpm包;
            元数据:
                数据文件
                    包名、版本信息、各包所包含的文件列表、依赖关系、包分组信息

                    centos5: xml, centos6,7: sqlite

                    createrepo: 制作yum仓库元数据的工具

        yum客户端:以安装为例
            第一步:获取仓库元数据
                缓存于本地:/var/cache/yum

            第二步:安装程序包
                yum客户端程序在本地分析元数据文件,并结合本地系统环境(已安装的包)做出要安装的程序包的决策
                    X --> Y,Z,M,N

            第三步:获取程序包
                根据决策联系Yum仓库,下载各程序包缓存于本地后,一并进行安装;

        yum仓库:
            base库:通常为系统发行版所提供的程序包
            updates库:
            extra库:
            epel库:


    使用yum机制:
        1、确保有yum repo可用;
            rpm包的文件服务器,repodata目录所在父目录就是一个可用仓库;

            ftp     ftp://server/path/to/repository
            http    http://server/path/to/repository
            nfs     nfs://server/nfs_path
            file    file:///path/to/repository
                file:///media/cdrom

        2、yum客户端
            指供repo配置文件,指明仓库访问路径及各种属性信息

            主配置文件(中心配置文件):/etc/yum.conf
            一个或几个相关仓库的配置信息可保存为一个文件,文件名都以.repo结尾:/etc/yum.repos.d/

            在.repo文件定义一个yum repo指向的格式:
            [REPOID]
            name=Some name for this repository
            baseurl=file:///media/cdrom
                    ftp://172.16.0.1/pub/ftp/centos

                     Must  be  a  URL  to  the  directory where the yum repository's 'repodata' directory lives
            enabled={0|1}
            gpgcheck={0|1}
            gpgkey=URL

            mirrorlist=URL to a file
                mirrorlist  Specifies a URL to a file containing a list of baseurls

            cost={1..n}
                默认为1000,指定访问此仓库的开销


    教室的repository:
        CentOS 6.5 x86_64的发行版
            http://172.16.0.1/cobbler/ks_mirror/centos-6.5-x86_64/

        CentOS 6.5的发行版:
            http://172.16.0.1/centos/6/extras/{i386,x86_64}

        fedora-epel
            http://172.16.0.1/fedora-epel/6/{i386,x86_64}

    yum客户端命令的使用:
        1、列出所有可用repo
            yum repolist {enabled|disabled|all}

        2、列出rpm包
            yum list {all|installed|available} 

            yum list KEYWORD*

        3、包的描述信息
            yum info package_name

        4、列出所有的包组信息
            yum grouplist

        5、显示包组的信息:例如组中包含的程序包列表
            yum groupinfo "GROUP NAME"

            CentOS6 跟开发相关的包组:
            Development Tools
            Server Platform Development
            Desktop Platform Development

        6、清理缓存
            yum clean {all|packages|metadata|expire-cache|rpmdb|plugins}

        7、安装程序包
            yum install package_name

            重新安装:
            yum reinstall package_name

        8、升级
            yum check-update: 检查可用的升级包

            yum update package_name

                x-1.3.1
                x-1.3.2, x-1.3.3, x-2.0.1

                yum update x-1.3.2

            yum downgrade package_name

        9、卸载
            yum remove|erase package_name

        10、查询某文件是由哪个包安装生成的
            yum whatprovides|provides /path/to/somefile

        11、安装包组
            yum groupinstall "GROUP NAME"

        12、卸载包组
            yum groupremove "GROUP NAME"

        

    假设:从其它处获得一个rpm包,如果此包依赖于其它包(在仓库中),如何安装?
        如果仅是单次安装需要:
            yum install /path/to/packe_file


练习:安装开发环境包组,确保如下命令能执行
    # gcc --version
    gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-4)
    Copyright (C) 2010 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


    baseurl=http://mirrors.sohu.com/centos/$releasever/os/$basearch

    centos5, test.repo
    centos6, test.repo






yum配置文件中可用的四个变量:
    $releasever: 程序的版本,对Yum而言指的是redhat-release版本;只替换为主版本号,如RedHat 6.5,则替换为6; 
    $arch: 系统架构
    $basearch: 系统基本架构,如i686,i586等的基本架构为i386;
    $uuid: 
    $YUM0-9: 在系统中定义的环境变量,可以在yum中使用;

    获取当前系统相应变量替换结果的办法:
        # python
        Python 2.6.6 (r266:84292, Nov 22 2013, 12:16:22) 
        [GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2
        Type "help", "copyright", "credits" or "license" for more information.
        >>> import yum,pprint
        >>> yb = yum.YumBase()
        >>> pprint.pprint(yb.conf.yumvar,width=1)
        Loaded plugins: fastestmirror, refresh-packagekit
        {'arch': 'ia32e',
         'basearch': 'x86_64',
         'releasever': '6',
         'uuid': 'ea249181-2f82-4c40-8c42-d51b3fce319a'}
        >>> quit()

yum支持插件

如何自建yum仓库:
    1、如何自建基于光盘镜像的yum repo

    2、自建提供yum仓库的中心服务器
        ftp, http, nfs

        以http为例,步骤:
            (1) 安装httpd程序,并启动服务
                # rpm -ivh httpd-
                或者
                # yum install httpd

                启动服务
                # service httpd start
                # chkconfig httpd on

            (2) httpd的文档根目录为/var/www/html:
                创建子目录,存放某相关的所有rpm包
            
            (3) 为仓库生成元数据文件,以使能够作为仓库使用
                # rpm -ivh createrepo-
                或者
                # yum install createrepo    

                # createrepo /path/to/rpm_repo/ 

            (4) 配置yum客户端使用此仓库即可



编译安装源代码包:
    依赖于开发环境

    程序源码:
        c/c++
        perl
        python

    制作好的rpm包:编译过的
        20,
            主包:6
            分包1:2
            分包2:4

    开源应用程序:
        自建站点:
            apache, ASF
            mysql
            drbd
        代码托管:
            SourceForge
            github.com
            code.google.com

    编译工具:gcc
        gnu c complier
        gcc-c++

    源代码的组织格式:
        多文件:
            文件中的代码有依赖关系

        项目管理工具:
            GNU make(gcc)

            项目:50文件
                项目的制作者:利用make工具,为make提供一个配置文件

                autoconf: 生成编译环境检查及编译功能配置脚本
                    生成configure
                automake: Makefile.in --> makefile

        编译源程序的步骤:
            # tar xf testapp-version.tar.{xz|bz2|gz}
            # cd testapp-version
            # ./configure
                还需通过许多选项指定编译特性
            # make
            # make install

        ./configure脚本的使用:
            1、获取帮助
                ./configure --help

            2、较通用的一些选项
                安装路径相关:
                    --prefix=/path/to/somewhere: 指定安装路径
                    --sysconfdir=/path/to/somewhere: 指定配置文件安装路径
                指定启用/禁用的特性
                    --enable-FEATURE: 例如--enable-fpm
                    --disable-FEATURE: 例如--disable-socket
                指定所依赖的功能、程序或文件
                    --with-FUNCTION[=/path/to/somewhere]
                    --without-FUNCTION

        安装后的配置:

        程序运行:
            1、让二进制程序直接,而无须输入路径
            # vim /etc/profile.d/APPNAME.sh
            export PATH=$PATH:/path/to/somewhere

            2、导出手册页:
            编辑/etc/man.config配置文件,添加一项MANPATH,路径为新安装的程序的man目录;
            
            # man -M /path/to/somewhere KEYWORD

        程序开发:如果其它应用程序依赖此程序的开发环境,或针对此程序做二次开发
            1、导出库文件
            第一步:指定让系统搜索定制的路径
                编辑/etc/ld.so.conf.d/APPNAME.conf
                    一行一个库文件路径

            第二步:触发系统重新搜索所有的库文件并生成缓存
                # ldconfig 
                    -v

            2、导出头文件
                /usr/local/nginx/include

                系统找头文件的路径是:/usr/include

                导出方式:创建链接进行
                    ln -sv /usr/local/nginx/include /usr/include/nginx


总结:yum, 源代码安装

回顾:
程序安装:rpm、yum(C/S)、源代码编译

    rpm: 分包机制
        核心包、支包

    管理:打包、安装、卸载、查询、升级、校验、数据库管理、验正

    yum: yum + yum repo
        yum: yum command
        yum repo: file server (rpm包+元数据(repodata))

        配置文件:/etc/yum.conf + /etc/yum.repos.d/*.repo
        [repoid]
        name=
        baseurl=URL
                url
                url
        enabled={0|1}
        gpgcheck={0|1}
        gpgkey=url
        cost=

    yum install x
        -y:
        --nogpgcheck 

    ./configure, make, make install
        gcc, gcc-c++

    包:绿色软件,解压直接使用

进程管理:

程序文件:静态文件
    指令+数据
        指令:CPU ,加工数据
            输出机制:

运行中程序:进程
    CPU:(ring0: kernel, ring3: user program)
        mkdir --> system call (由内核执行代码)


用户态,用户模式:--> 内核态、内核模式
    软中断:soft interrupt, si

Linux: 多用户、多任务

    内存:分段、分页

    进程:进程+内核
        内存:4G,
            1G:内核
            3G:进程

        线性地址空间
        物理地址空间

        内核:精心编造一个数据结构
            tast structure:任务结构

        进程调度:
            程序,算法
                算法复杂度:
                    O(1): 

                mmu: memory management unit

        进程分类:
            CPU-Bound: 
            I/O-Bound: 

    内核:进程调度、内存管理
        CFS

    进程分类:
        批处理进程
        交互式进程
        实时进程

    进程优先级:0-139
        实时优先级:0-99,数字越大,优先级越高
        静态优先级:100-139,数字越小,优先级越高
            nice值:-20, 19
                进程启动,默认nice值为0
        动态优先级:由内核维护,动态调整

    进程状态:
        运行态:running
        睡眠态:sleeping
            可中断睡眠:interruptable
            不可中断睡眠:等待外部满足之前无法继续运行, uninterruptable
        停止态:不会被内核调度并运行,stopped
        僵死态:zombie

    进程创建机制:每一个进程都是由其父进程fork()自身而来;

    进程间通信:IPC (InterProcess Communication)
        同一主机:
            signal
            shm:共享内存
            semerphor: 旗语

        不同主机:
            rpc: Remote Procedure Calling
            socket: 

    CPU虚拟化:时间片, timeslice
        5ms

        保存现场、恢复现场

        5ms, 2ms, 5ms
        1ms, 2ms, 1ms, 2ms

        抢占式多任务

    线程:比进程更小的可以被单独调度的单位;
        thread: lwp


Linux进程管理工具:ps, pstree, pidof, top, htop, pmap, vmstat, dstat, kill, job, glance

pstree: 查看进程树

ps: 显示进程状态的命令,快照式、一次性
    支持两种风格:SysV, BSD

    进程:
        与终端相关的进程: a
        与终端无关的进程:x

        常用组合:ps aux
            VSZ: Virtual memory SiZe
            RSS: 常驻内存集

        STAT状态:
            R: running
            S: 可中断睡眠
            D:不可中断睡眠
            T:stopped
            Z:zombie

            s: session leader
            +:前台进程
            l: 多线程进程
            N:低优先级进程
            <: 高优先级进程

        COMMAND:包含在方括号中的进程表示为内核线程

        常用组合:ps -ef
            -e: 显示所有进程
            -f: 显示完整格式的信息

        常用组合:ps -eFH
            -F: 显示额外信息
            -H:显示进程的层次结构

        自定义要显示的信息:-o
            ps axo pid,command,psr,pri,ni
                ni: nice值
                pri: 优优级
                psr: 运行的CPU

        pgrep 
            -U UID:仅显示由指定用户启动的进程
            -G GID:仅显示与指定组相关的进程
            -t term...: 仅显示与指定终端相关的进程
            -l: 同时显示进程号和程序名

        pidof:显示指定命令所启动的进程的ID
            pidof COMMAND

    top: 
        M: 内存百分比
        P: CPU百分比
        T: 累积占用的CPU时间

        l: 显示或不显示负载信息
            过去1分钟、5分钟、15分钟的平均负载
                等待运行的进程队列的长度
        t: 显示或不显示进程及CPU相关的信息
            1: 数字,分别显示各CPU的相关信息
                us: user space
                sy: system
                ni: 
                id: 
                wa: wait io
                hi: hardware interrupt
                si: soft interrupt
                st: 
        m: 显示或不显示物理内存和交换内存的相关信息

        q: 退出
        k: 终止指定进程
        s: 修改刷新时间间隔

        常用选项:
            -d #: 指定刷新时间间隔
            -b: 以批次的方式显示top的刷新
            -n #: 显示的批次

    htop: 
        u: 交互式选择显示指定用户的进程
        l: 显示光标所在进程所打开的文件列表
        s: 显示光标所在进程执行的系统调用
        a: 绑定进程到指定的CPU
        #:快速定位光标至PID为#的进程上

        F1:获取帮助

    vmstat: 
        procs:
            r: 运行队列的长度
            b: 被阻塞(等待IO完成)队列的长度

        memory: 
            swpd: 从物理内存交换至swap中的数据量
            free: 空间物理内存
            buffer:
            cache:

        swap:
            si: swap in, 数据进入swap中的数据速率,kb/s
            so: swap out,数据离开swap中的数据速率

        io:
            bi: block in, 从块设备读入的数据速率,kb/s
            bo: block out,保存至块设备的数据速率

        system:
            in: interrupt, 中断速率
            cs: context switch, 进程切换速率

        cpu:
            us, sy, id, wa, st

        -s: 显示内存统计数据

总结:
    ps, pstree, pgrep, pidof, top, htop, vmstat

进程管理:
top,
us%, sy%, wa%, ni%

    VSZ, RSS

进程调度:
    CPU: timeslice, process

    CPU:
        O(1), CFS

        优先级:
            实时优先级:1-99
            静态优先级:100-139
            动态优先级:

    CPU:
        进程切换:上下文切换
            保存现场,恢复现场

    scale up: 向上扩展
    scale out: 向外扩展
        集群

htop: a

静态优先级:100-139
            -20, 19

            用户空间的程序:0, 120

直接启动一个进程,并指定其Nice值:
    nice -n # COMMAND

调整已运行的进程的nice值:
    renice -n # -p PID


进程间通信:IPC
    同一主机:signal, shm, semerphor
    不同主机:socket, rpc

    信号:signal,借助于kill命令

    基于kill命令向其它的进程发信号:


    显示常用信号:
        # kill -l
        # man 7 signal

    每个信号都可以使用三种方式之一在Kill进行调用:
        数字代称: 1, 2, 9, 15
        信号完整名称:SIGHUP, SIGINT, SIGKILL, SIGTERM
        信号简称:HUP, INT, KILL, TERM

        1) SIGHUP:让程序重读配置文件需无须重新启动;
        2) SIGINT:interrupt,打断正在运行中的程序;
        9) SIGKILL:
        15) SIGTERM:

        kill [-SIGNAL] PID
            -9, -SIGKILL

        killall [-SIGNAL] COMMAND

Linux作业控制:
    job

    前台作业:通过终端启动,并在终止之前一直占据着终端
    后台作业:作业启动之后即运行于后台,释放前台

    交互式模式:手动启动的非守护进程类的程序,一般都运行于前台;

    如何将作业运行于后台:
        1、运行中的作业:
            Ctrl+z
                送往后台后,作业处于STOPPED状态
        2、尚未启动作业:
            COMMAND &

            此类由手动方式控制的作业,与终端相关作业会被终止;如果把作业送往后台,且与终端无关:
                # nohup COMMAND &

    作业:作业号
        # jobs

    作业控制命令:
        # fg [[%]JOBNUM]: 将指定的作业调回前台
        # bg [[%]JOBNUM]: 让送往后台的作业在后台继续运行
        # kill %JOBNUM: 终止指定的作业

进程查看:htop
    uptime, vmstat, iostat, netstat, ifstat, nfsstat

    dstat
        -c: 显示CPU统计数据
        -d: 显示disk统计数据
        -D DISK: 只显示指定disk的统计数据
        -g: 显示page的统计数据
        -i: 显示中断的统计数据
        -m: 显示内存的统计数据
        -l: 显示系统负载的统计数据
        -n: 显示网络接口相关
        -N INTERFACE: 仅显示指定的网络接口的数据
        -s: 显示交换内存
        -p: 进程队列
        --ipc: 显示ipc消息队列、信号量和共享内存的使用状况
        -y: 系统状态数据

        默认相当于使用“dstat -cdngy”,也相当于“dstat -a”

        此外,使用"dstat -f", 以完整格式显示所有信息,

        再者,使用"dstat -v",显示结果类似于vmstat命令

        网络连接状态统计:
            --tcp
            --udp
            --raw
            --unix

/proc/#/maps:
    进程内存映射表

    pmap命令:显示指定进程的物理内存空间映射表
    pmap PID

glances: 
    由epel源所提供

课外作业:nmap, netcat, tcpdump, nethogs, iftop

命令总结:nice, renice, jobs, bg, fg, nohup, kill, dstat, uptime, pmap, glances

bash编程之case语句

写一个脚本,使用格式:
    script.sh {start|stop|restart|status}

    1) start: 创建/var/lock/subsys/script.sh
    2) stop: 删除此文件
    3) restart: 先删除文件,再创建文件
    4) status: 如文件存在,显示running,否则,显示stopped

        #!/bin/bash
        #
        srv=`basename $0`

        lockFile="/var/lock/subsys/$srv"

        [ $# -lt 1 ] && echo "Usage: $srv {start|stop|restart|status}" && exit 4

        [ $UID -ne 0 ] && echo "Only root." && exit 5

        if [ "$1" == 'start' ]; then
           if [ -f $lockFile ]; then
                echo "$srv is running."
                exit 7
           else
                touch $lockFile
                [ $? -eq 0 ] && echo "Starting $srv OK."
           fi
        elif [ "$1" == 'stop' ]; then
            if [ -f $lockFile ]; then
                rm -f $lockFile
                [ $? -eq 0 ] && echo "Stopping $srv OK."
            else
                echo "$srv is stopped yes."
                exit 6
            fi
        elif [ "$1" == 'restart' ]; then
            if [ -f $lockFile ];then
                rm -f $lockFile
                [ $? -eq 0 ] && echo "Stopping $srv OK."
            else
                echo "$srv is stopped yet."
            fi
            touch $lockFile
            [ $? -eq 0 ] && echo "Starting $srv OK."
        elif [ "$1" == 'status' ];then
            if [ -f $lockFile ];then
                echo "$srv is running."
            else
                echo "$srv is stopped."
            fi
        else
            echo "Usage: $srv {start|stop|restart|status}" && exit 9
        fi



条件测试:
    [ expression ]
    [[ expression ]]
    test expression
    COMMAND: 不能使用命令引用,要引用的命令执行后状态返回值
    [ `COMMAND` -eq 0 ]

    expression:
        整数测试:-eq, -ne, -ge, -le, -gt, -lt
        字符串测试: ==, !=, >, <, =~, -z, -n
            注意:字串比较时,尽量使用引号;
        文件测试:-e, -f, -d, -L, -b, -c, -S, -p, -r, -w, -x, -s

    多分支的if语句:
        if 条件1; then
            分支1
        elif 条件2; then
            分支2
        ...
        else
            分支n
        fi


case语句:有多个测试条件时,case语句会使得语法结构更明晰

    case 变量引用 in
    PATTERN1)
        分支1
        ;;
    PATTERN2)
        分支2
        ;;
    ...
    *)
        分支n
        ;;
    esac

    PATTERN:类同于文件名通配机制,但支持使用|表示或者;
        a|b: a或者b
        *:匹配任意长度的任意字符
        ?: 匹配任意单个字符
        []: 指定范围内的任意单个字符

例如:用户键入字符后判断其所属的类别;

    #!/bin/bash
    #

    read -p "Plz enter a char: " char

    case $char in
    [0-9])
        echo "a digit"
        ;;
    [a-z])
        echo "a char"
        ;;
    *)
        echo "a special word"
        ;;
    esac


写一个脚本,使用格式:
    script.sh {start|stop|restart|status}

    1) start: 创建/var/lock/subsys/script.sh
    2) stop: 删除此文件
    3) restart: 先删除文件,再创建文件
    4) status: 如文件存在,显示running,否则,显示stopped

        #!/bin/bash
        #
        srv=`basename $0`

        lockFile="/var/lock/subsys/$srv"

        [ $# -lt 1 ] && echo "Usage: $srv {start|stop|restart|status}" && exit 4

        [ $UID -ne 0 ] && echo "Only root." && exit 5

        case $1 in
        start)
           if [ -f $lockFile ]; then
                echo "$srv is running."
            exit 7
           else
            touch $lockFile
            [ $? -eq 0 ] && echo "Starting $srv OK."
           fi
           ;;
        stop)
            if [ -f $lockFile ]; then
            rm -f $lockFile
            [ $? -eq 0 ] && echo "Stopping $srv OK."
            else
            echo "$srv is stopped yes."
            exit 6
            fi
            ;;
        restart)
            if [ -f $lockFile ];then
                rm -f $lockFile
            [ $? -eq 0 ] && echo "Stopping $srv OK."
            else
            echo "$srv is stopped yet."
            fi
            touch $lockFile
            [ $? -eq 0 ] && echo "Starting $srv OK."
            ;;
        status)
            if [ -f $lockFile ];then
            echo "$srv is running."
            else
            echo "$srv is stopped."
            fi
            ;;
        *)
            echo "Usage: $srv {start|stop|restart|status}" && exit 9
        esac

练习:写一个脚本,对/etc/目录及内部的所有文件打包压缩
1、显示一个菜单,让用选择使用的压缩工具:
    xz) xz compress tool
    gz) gzip compress tool
    bz2) bzip2 compress tool
2、根据用户选择的工具,对/etc执行相应的操作并保存至/backups目录,文件形如/backups/etc-日期时间.tar.压缩后缀

    #!/bin/bash
    #
    [ -d /backups ] || mkdir /backups

    cat << EOF
        xz) xz compress tool
        gz) gzip compress tool
        bz2) bzip2 compress tool
    EOF

    read -p "Plz choose an option: " choice

    case $choice in
    xz)
        tar -Jcf /backups/etc-`date +%F-%H-%M-%S`.tar.xz /etc/*
        ;;
    gz)
        tar -zcf /backups/etc-`date +%F-%H-%M-%S`.tar.gz /etc/*
        ;;
    bz2)
        tar -jcf /backups/etc-`date +%F-%H-%M-%S`.tar.bz2 /etc/*
        ;;
    *)
        echo "wrong option."
        exit 1
        ;;
    esac



练习:写一个脚本,使用形式如下所示
    showifinfo.sh [-i INTERFACE|-a] [-v]
    要求:
    1、-i或-a不可同时使用,-i用于指定特定网卡接口,-a用于指定所有接口;
        显示接口的ip地址
    2、使用-v,则表示显示详细信息
        显示接口的ip地址、子网掩码、广播地址;
    3、默认表示仅使用-a选项;

        #!/bin/bash
        #
        verbose=0
        allInterface=0
        ifflag=0
        interface=0

        while [ $# -ge 1 ]; do
            case $1 in
            -a)
            allInterface=1
                shift 1
            ;;
             -i)
            ifflag=1
            interface="$2"
            shift 2
            ;;
             -v)
            verbose=1
            shift
            ;;
             *)
            echo "wrong option"
            exit 2
            ;;
             esac
        done

        if [ $allInterface -eq 1 ]; then
            if [ $verbose -eq 1 ]; then
            ifconfig | grep "inet addr:"
            else
            ifconfig | grep "inet addr:" | awk '{print $2}' 
            fi
        fi

        if [ $ifflag -eq 1 ]; then
            if [ $verbose -eq 1 ]; then
            ifconfig $interface | grep "inet addr:"
            else
            ifconfig $interface | grep "inet addr:" | awk '{print $2}' 
            fi
        fi      

Linux内核及系统启动流程

kernel的功能:
    进程管理
    文件系统
    硬件驱动
    内存管理
    安全功能:SELinux
    网络子系统


    标准库:glibc

    调用:返回
        利用别的组件的功能,完成某特定事务
        返回值

内核设计流派:
    单内核体系:
        Linux
            支持模块化
            模块还可以动态装载或卸载

        Linux内核:核心 + 外围模块
            核心:/boot/vmlinux-VERSION-release
            模块:/lib/modules/VERSION-release
                .ko: kernel object
            ramdisk: /boot/initramfs-VERSION-release.img
                在内核启动过程中装载根文件系统时有用;

    微内核体系:
        Windows
        Solaris

Linux系统启动流程:X86(PC)

    POST:加电自检
        ROM+RAM
            ROM:CMOS (BIOS)
            RAM:
                    EFI()

        引导次序:按次序找引导设备,第一个有引导程序的设备即为启动PC server所用到的设备;
            1st boot: 
            2nd boot:
            3rd boot:

    MBR:Master Boot Record
        1st sector:512bytes
            446: bootloader
            64: partation table
            2: 5A

    bootloader: 选择要启动的内核(在当前磁盘的某或某些分区上)

        LILO: LInux LOader
            0-1023范围内的柱面构成的分区的内核文件
        GRUB: GRand Unified Bootloader
            CentOS 5,6 Grub 0.97
            CentOS 7, Grub2 1.96

    kernel: 
        自身初始化
            探测所有能识别的硬件
            装载驱动程序
            以只读方式装载根文件系统(rootfs)
            /sbin/init

        CentOS 5: SysV, init
        CentOS 6: upstart, init
        CentOS 7: systemd, init

        CentOS 5 SysV, init, /etc/inittab --> /etc/rc.d/rc.sysinit
        CentOS 6 Upstart, /etc/init/*.conf (/etc/inittab)--> /etc/rc.d/rc.sysinit
            chkconfig
        CentOS 7 Systemd, 
            /usr/lib/systemd/system/

    CentOS 5: init
        kernel ==> /sbin/init (/etc/inittab) 
            设定系统默认运行级别
                0-6: 7个级别
                    0:关机
                    1: single user mode, s, S, single
                    2: multi user mode, 不支持NFS功能
                    3:完全多用户模式,文本接口
                    4:未使用,预留级别
                    5:完全多用户械,图形接口
                    6: 重启

                切换级别:init #

            进一步初始化系统
                /etc/rc.d/rc.sysinit

            启动指定的默认级别的默认为启动的服务,停止指定的级别下默认为关闭的服务;
                /etc/rc.d/rc#.d
                    S##: 启动的服务
                    K##:停止的服务

                    ##:01-99,数字越小,越优先启动或关闭;

                脚本如果期望能够被chkconfig命令使用,要在脚本中添加如下行
                    # chkconfig: - 85 15
                        -:当此脚本由chkconfig控制时,默认哪些级别就是开启的,
                        85:启动优先级
                        15: 关闭优先级

                    # chkconfig --add SRV_SCRIPT
                    # chkconfig --del SRV_SCRIPT
                    # chkconfig SRV_SCRIPT {on|off}
                        默认为2345级别;
                        --level ######

                    /etc/rc.d/rc.local (/etc/rc.local): 是一个脚本,通常为系统启动完成的最后运行一个脚本;

                定义一些组合键的功能:通常是Ctrl+Alt+Delete

                初始化字符终端

                如果有需要,启动图形终端

        CentOS 5: /etc/inittab
            每一行定义一种action和对应的程序;
                id:runlevels:action:process
                例如
                si::sysinit:/etc/rc.d/rc.sysinit

                action: respwan, wait, initdefault
                l3:3:wait:/etc/rc.d/rc 3

        CentOS 6: /etc/inittab
            由/etc/init/*.conf 一类的配置文件定义init的初始化动作
                由upstart调用,程序为/sbin/init

/etc/rc.d/rc.sysinit: 系统初始化脚本
    设定主机名:读取/etc/sysconfig/network文件中的HOSTNAME参数,并以之设定主机名
    打印文本欢迎信息
    激活SELinux和udev
    挂载/etc/fstab文件中定义的其它文件系统
    激活swap
    检测根文件系统,并以读写方式重新挂载;
    设置系统时钟
    根据/etc/sysctl.conf设置内核参数
    激活LVM和RAID设备;
    加载额外设备的驱动程序;
    清理操作

初始化流程:POST --> (BIOS)boot sequence --> MBR(bootloader) --> kernel + ramdisk(initrd, initramfs) --> mount rootfs (ro) --> /sbin/init (CentOS 5: /etc/inittab, CentOS6 /etc/init/*.conf) 
    设定默认运行级别 --> 使用/etc/rc.d/rc.sysinit初始化系统 --> 分别启动并关闭指定服务 --> Ctrl+Alt+Delete组合键 --> 启动字符终端 --> 启动图形终端


GRUB: GRand Unified Bootloader
    grub程序由两段组成:
        stage1: MBR (0柱面 0磁道 1扇区)
        stage1_5: MBR随后的扇区
        stage2: 读取grub.conf配置文件,并实现引导功能的扩展

    grub的功能:
        1、提供菜单,并提供交互式接口
            e: 进入编辑模式
        2、选择要启动的内核或系统
            允许传递引导参数给内核
            选择界面可隐藏
        3、为编辑功能提供保护机制
            启用内核文件:
                选择运行指定的内核得先输入密码
            传递参数:
                使用e命令得先输入密码

    grub命令行接口:
        root:指定哪个分区为接下来要启动的系统或内核文件所在的分区
            root (DEVICE)
                所有硬盘都识别为hd
                不同的硬盘基于数字标识:如hd0, hd1等
                同一个硬盘上的不同分区,也使用数字标识,如hd0,0  hd1,5

                root (hd0,0)

            find (DEVICE)/path/to/file

            kernel: 指定要运行的内核文件
            initrd: 为要运行的内核指定其可用的ramdisk文件

            boot: 启动此前配置好的内核或系统

    grub.conf:
        参数:
            default=: 选择第几个title配置的内核或系统,各title从0开始编号
            timeout=#: 菜单显示的超时时长;
            splashimage=/path/to/some_image_file:指定菜单的背景图片;此图片只能为14bits色,xpm格式,gzip压缩;
            hiddenmenu: 隐藏菜单
            title TILTE STRING:显示于菜单中的标题
                root
                kernel
                initrd

    grub保护机制:
        1、生成密码:
            # grub-md5-crypt
        2、保护编辑功能,则需要title之外的添加
            password --md5 密码串
        3、保护使用某内核,则需要内核对应的title之下添加
            password --md5 密码串

    安装grub的方式:
        1、使用grub-install命令
            # grub-install [--root-directory=/path/to/somewhere] DEVICE

            --root-directory=/path/to/somewhere
                /path/to/somewhere:内核及initrd文件所在的分区的挂载点的父目录,且此挂载点必须叫boot
                    例如:/dev/sdb1: /mnt/boot
                    # grub-install --root-directory=/mnt /dev/sdb

回顾:启动流程
POST --> 引导次序(BIOS)--> BootLoader(MBR) --> kernel + ramdisk (临时根) --> 根切换 (rootfs) --> /sbin/init (配置文件)

配置文件:设置默认运行级别 --> 指定系统初始化脚本进行系统初始化 --> 启动服务(关闭服务)(/etc/rc.d/rc#.d, /etc/rc.d/init.d/) --> /etc/rc.d/rc.local -> 设置CtrlAltDel组合的功用 --> 启动终端(mingetty),并在终端附加登录程序(login) --> 如果级别为5, 则要启动 X server

login: root
password: mageedu

nsswitch: 检查用户帐是否存在,并且如果存在,还能将其解析为UID;
    库(API),而非服务
    /usr/lib64/libnss*
    /lib64/libnss*
pam: pluggable authentication module, 做用户认证
    库 (API)
    /lib64/security/*


ramdisk
    centos5: initrd
        ram disk: 块设备
    centos6: initramfs
        ram fs:

配置文件:
    c5: sysv init, /etc/inittab
    c6: upstart, /etc/inittab + /etc/init/*.conf
        chkconfig --add, --del, --list, --level
    c7: systemd, /usr/lib/systemd/

X-Window: Client --> Server
    X protocol
    twm
    Desktop: GNome, KDE, Xfce

GRUB: GRand Unified Bootloader
    stage1
    stage1_5
    stage2

    命令行接口:
    grub>

    配置文件:
    /boot/grub/grub.conf

    编辑模式:

Linux内核:单内核,模块化
    内核的某些功能:
        编译进内核本体  [*]
        编译成内核模块  [M]
        不选择使用       [ ]

    内核的组成部分:
        /boot/vmlinuz-VERSION
        /lib/modules/VERSION/
            *.ko: kernel object
            模块间有可能存在依赖关系;

    内核模块管理:
        lsmod: 显示内核已装载模块

        动态装卸载模块:
            卸载:modprobe -r MOD_NAME
            装载:modprobe MOD_NAME

            装载:insmod /path/to/module_file
            卸载:rmmod MOD_NAME

        查看某模块的详细信息:
            modinfo MOD_NAME

        检查并生成模块间依赖关系的命令:
            depmod

bash编程函数:

模块化,代码重用

代码块,名

语法:

function F_NAME {
    函数体
}

F_NAME() {
    函数体
}

可调用:使用函数名
    函数名出现的地方,会被自动替换为函数;

脚本:

函数的返回值:
    函数的执行结果返回值:代码的输出
        函数中的打印语句:echo, print
        函数中调用的系统命令执行后返回的结果
    执行状态返回值:
        函数体中最后一次执行的命令状态结果
        自定函数执行状态的返回值:return #

函数可以接受参数:
    在函数体中调用函数参数的方式同脚本中调用脚本参数的方式:位置参数
        $1, $2, ...
        $#, $*, $@


示例:服务脚本示例

    #!/bin/bash
    #
    # chkconfig: 2345 67 34
    #
    srvName=$(basename $0)

    lockFile=/var/lock/subsys/$srvName

    start() {
        if [ -f $lockFile ];then
        echo "$srvName is already running."
        return 1
        else
        touch $lockFile
        [ $? -eq 0 ] && echo "Starting $srvName OK."
        return 0
         fi
    }

    stop() {
        if [ -f $lockFile ];then
        rm -f $lockFile &> /dev/null
        [ $? -eq 0 ] && echo "Stop $srvName OK" && return 0 
        else
        echo "$srvName is not started."
        return 1
        fi
    }   

    status() {
        if [ -f $lockFile ]; then
        echo "$srvName is running."
        else
        echo "$srvName is stopped."
        fi
        return 0
    }

    usage() {
         echo "Usage: $srvName {start|stop|restart|status}"
         return 0
    }

    case $1 in
    start)
        start
        ;;
    stop)
        stop ;;
    restart)
        stop
        start ;;
    status)
        status ;;
    *)
        usage
        exit 1 ;;
    esac

练习:写一个脚本,完成如下功能(使用函数):
1、提示用户输入一个可执行命令;
2、获取这个命令所依赖的所有库文件(使用ldd命令);
3、复制命令至/mnt/sysroot/对应的目录中
解释:假设,如果复制的是cat命令,其可执行程序的路径是/bin/cat,那么就要将/bin/cat复制到/mnt/sysroot/bin/目录中,如果复制的是useradd命令,而useradd的可执行文件路径为/usr/sbin/useradd,那么就要将其复制到/mnt/sysroot/usr/sbin/目录中;
4、复制各库文件至/mnt/sysroot/对应的目录中;

!/bin/bash

target=/mnt/sysroot/

[ -d $target ] || mkdir $target

preCommand() {
if which $1 &> /dev/null; then
commandPath=which --skip-alias $1
return 0
else
echo "No such command."
return 1
fi
}

commandCopy() {
commandDir=dirname $1
[ -d ${target}${commandDir} ] || mkdir -p ${target}${commandDir}
[ -f ${target}${commandPath} ] || cp $1 ${target}${commandDir}
}

libCopy() {
for lib in ldd $1 | egrep -o "/[^[:space:]]+"; do
libDir=dirname $lib
[ -d ${target}${libDir} ] || mkdir -p ${target}${libDir}
[ -f ${target}${lib} ] || cp $lib ${target}${libDir}
done
}

read -p "Plz enter a command: " command

until [ "$command" == 'quit' ]; do

if preCommand $command &> /dev/null; then
commandCopy $commandPath
libCopy $commandPath
fi

read -p "Plz enter a command: " command
done

练习:
写一个脚本,判定192.168.0.0网络内有哪些主机在线,在线的用绿色显示;不在线的用红色显示;(使用函数)
写一个脚本,判定172.16.0.0网络内有哪些主机在线,在线的用绿色显示;不在线的用红色显示;(使用函数)

练习:写一个脚本,完成如下功能(使用函数):
1、脚本使用格式:
mkscript.sh [-D|--description "script description"] [-A|--author "script author"] /path/to/somefile
2、如果文件事先不存在,则创建;且前几行内容如下所示:

!/bin/bash

Description: script description

Author: script author

3、如果事先存在,但不空,且第一行不是“#!/bin/bash”,则提示错误并退出;如果第一行是“#!/bin/bash”,则使用vim打开脚本;把光标直接定位至最后一行
4、打开脚本后关闭时判断脚本是否有语法错误
如果有,提示输入y继续编辑,输入n放弃并退出;
如果没有,则给此文件以执行权限;

练习:提示用户输入一个用户名,判断用户是否登录了当前系统;
如果没有登录,则停止5秒钟之后,再次判断;直到用户登录系统,显示“用户来了”,而后退出;

练习:写一个脚本,
1、提示用户输入一个磁盘设备的设备文件,如果设备文件不存在,就提示用户重新输入,直到用户输入正确为止;
2、用户可以输入quit退出;

练习:扩展前一题
当用户给出正确的块设备后:
1、显示用户输入块设备,并提示用户,后续的操作会损坏设备上的所有文件,让用户选择是否继续
2、如果用户输入y,则继续后面的操作;
3、如果用户输入n,则显示用户选择了中止,并退出脚本;
4、输入任何其它字符,则让用户重新选择;

练习:扩展上一题
1、如果用户选择了y, 则抹除指定块设备上的所有分区;

练习:再扩展
1、在上面的磁盘创建两个主分区:
(1) 50M
(2) 512M
2、均格式化为ext4文件系统;
3、分别挂载至/mnt/boot和/mnt/sysroot

练习:继续扩展
1、在此设备上安装grub;
2、在/mnt/sysroot目录下创建根文件系统所需要各目录;

练习:扩展
1、移植多个应用程序,至少包含bash、ifconfig等;

回顾:
系统启动流程,内核模块加载及卸载的方法;bash函数的使用;

写一个脚本:让用户输入一个网络地址,探测此网络内的所有主机是否在线;
    192.168.1.1-254
    172.16.0.1-172.16.255.254
    10.0.0.1-10.255.255.254

内核参数的配置:

/proc, /sys

/proc: 内核映像
    许多参数(读写,只读)
        只读文件:输出统计信息
        读写文件:设定内核工作特性
            /proc/sys

            不允许使用文本编辑器打开进行编写,而只能使用重定向的方式或使用专用的工具

        vm, net, fs

        net.ipv4.ip_forward

    /proc: 虚拟成了文件系统
        net/ipv4/ip_forward

几个常用参数:
    kernel.hostname
    vm.drop_caches
    net.ipv4.icmp_echo_ignore_all
    net.ipv4.ip_forward

Linux: ip地址属于内核,而非网卡

修改内核参数的办法:
    echo "" > /proc/sys/

    sysctl -w VARAIABLE=VALUE

        配置文件:/etc/sysctl.conf

    sysctl -a: 显示sysctl可控制的所有内核参数;
    sysctl -p: 重读配置文件并生效之;

/sys: 

    Linux 2.4-: /dev所有设备都是事先预置;
    Linux 2.6+: /dev下所有设备文件能够按需创建
        kernel初始化时,根文件系统尚未挂载
        /sys: 硬件设备的相关信息
        用户空间的某应用程序就可根据/sys中信息来为每个设备按需创建设备文件

        udev: 用户空间的程序,用于创建所需要设备, udevadmin,
            hotplug

        udev创建设备文件是根据udev规则进行,规则文件在/etc/udev/rules.d/


ramdisk: /boot/initramfs-VERSION.img

    创建工具:mkinitrd
              dracut

    uname:
        -n, -r

    # dracut /boot/initramfs-$(uname -r).img  $(uname -r)
    # dracut /boot/initramfs-3.10.1.img   3.10.1

    cpio, gzip

    展开initramfs文件:
    # cp /boot/initramfs-RELEASE.img /tmp/initramfs.img.gz
    # gzip -d /tmp/initramfs.img.gz
    # mkdir /tmp/initramfs
    # cd /tmp/initramfs
    # cpio -id < /tmp/initramfs.img.gz

bash子进程:

exec COMMAND: 能启动command为一个进程,此进程会取代当前shell进程;

screen工具:

启动新屏幕:screen
退出新屏幕:exit, 意味着关闭
拆除新屏幕:Ctrl+a, d    意味着临时隐藏

screen -ls: 查看所有被隐藏的屏幕ID
screen -r SID: 连接至某隐藏的屏幕

lftp: ftp客户端工具
lftp HOST
-u USERNAME,PASSWORD
-p PORT

    -e 'CMD'

lftp: 子命令

    help: 获取帮助
    cd: 切换远程服务器上的文件系统目录
    lcd: 切换本地文件系统目录
    get FILE: 下载

    !COMMAND: 执行shell命令,而非ftp命令

    mget FILE1...: 下载多个文件,支持使用通配符

    mirror DIR: 镜像目录至本地 

    put FILE: 
    mput FILE1...:


lftpget类似于wget: 下载指定URL

kernel:
www.kernel.org

版本号:
    RHEL6: 
        6.0: 2.6.32
        6.1
        .
        6.5:2.6.32

    RHEL7:


    3.10: f1, f2

前提:查看本地硬件信息常用工具

    查看CPU信息:
        # cat /proc/cpuinfo

        # x86info

            # yum install x86info

        # lscpu

    查看PCI:
        # lspci
            -v

    查看USB:
        # lsusb

    查看块设备:
        # lsblk

编译:交叉编译
    cross-compiling

编译内核的步骤:(安装好开发环境,c6: Development Tools, Server Platform Development, ncurses-devel)
    第一步:配置内核
        make config
        make allyesconfig
        make allnoconfig

        make menuconfig
        make gconfig (依赖GNome桌面环境及GNome的图形开发环境,gtk2)
        make kconfig (依赖KDE桌面环境及KDE的图形开发环境,qt)

    第二步:编译
        make

    第三步:安装内核模块
        make modules_install

        安装位置:/lib/modules/VERSION/
            分析模块间依赖关系并成dep文件

    第四步:安装内核
        make install

            安装内核:/boot/vmlinuz-VERSION
            编辑grub.conf,添加一新的title,


获取源代码,展开指定目录下:
    # tar xf linux-3.10.10.tar.xz -C /usr/src


后续的编译,开始之前的清理操作
    # make clean
        清理编译的文件,但保留配置文件
    # make mrproper
        移除所有编译生成的文件、配置文件和备份文件
    # make distclean
        完全清理

1、将编译生成的文件保存至别处:
    # mkdir /path/to/somewhere
    # cd /path/to/somewhere
    # ./configure --ksource=/usr/src/linux

2、如何只编译内核的部分代码
    (1) 只编译某子目录中的相关代码
    # cd /usr/src/linux
    # make  path/to/dir/

    例如:
    # make SUBDIR=arch/
    # make drivers/net/

    (2) 只编译部分模块
    # make M=path/to/dir

    # make M=drivers/net/

    (3) 只编译一个模块
    # make path/to/dir/MOD_NAME.ko

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

    (4)将编译生成的文件保存至别处:
    # make O=/path/to/somewhere

3、交叉编译

    # make ARCH=arch

    获取某ARCH的可用的默认配置
    # make ARCH=arch help

    例如:
    # make ARCH=arm acs5k_defconfig

回顾:

内核管理:功能、系统启动流程、查看硬件信息、简单内核定制

系统启动流程:
    POST --> BootLoader(MBR) --> Kernel (ramdisk) --> rootfs (/sbin/init)

    内核模块:/lib/modules/VERSION/

    可做为启动设备:
        光驱、便携式移动设备、硬盘、网卡(系统引导,PXE)

    BootLoader: GRUB
        GRUB 0.97, GRUB Legacy
        GRUB 1.96, GRUB 2

    kernel (ramdisk): 
        安装程序: anaconda 

        PXE: DHCP, tftp(kernel+ramdisk)

    /sbin/init
        C5:
            /sbin/init (SysV,)
            echo $$
        C6: 
            /sbin/init (upstart), D-BUS
                /etc/rc.d/init.d/*
                service

            运行级别:0-6
                默认: 3, 5

                /etc/inittab

        C7:
            /sbin/init (systemd)
                systemctl 

Linux系统安装:

安装过程:
    POST --> Bootloader (kernel+ramdisk) --> anaconda

    BootLoader界面:
        GUI界面
        text界面
            boot:

    anaconda接口:
        text接口
        GUI接口

    安装过程分为两个阶段:

        安装前的配置阶段:  (既可交互式进行,亦可直接读取配置文件自动完成)
            键盘类型
            安装过程中的语言
            支持使用语言
            时区
            选择要使用磁盘设备
            分区、格式化配置
            选择要安装的包
            管理员密码
        安装阶段:
            在目标磁盘创建分区、执行分区格式化
            将选定的程序包安装至目标磁盘
            安装bootloader
        第一次启动配置:
            iptables
            selinux
            core kdump

    kickstart文件:文本文件

    建议单独分区:
        /
        /home
        /usr
        /var
        swap
    不能单独分区:
        /proc, /sys, /etc, /bin, /sbin, /lib, /media, /mnt, /dev

    /boot: 
        单独分区与否,取决于rootfs所在设备的类型

boot: 
    启动安装过程的引导参数

        CentOS 6:
            text: 文本安装界面
            repo=
                http://server/path/to/repo/
                ftp://username:password@server/path/to/repo
            网络配置:
                ip=
                netmask=
                gateway=
                dns=
                ifname=: 指定此地址配置到地的网络接口
            指定使用的kickstart文件及其位置
                ks=cdrom:/path/to/ksfile
                ks=http://server/path/to/ksfile
                ks=ftp://username:password@server/path/to/ksfile

                例如:http://172.16.0.1/centos6.x86_64.cfg
            如果额外加载驱动程序:
                dd

        CentOS 7:
            指定安装源:
                inst.repo=

            指定额外需要加载驱动:
                inst.dd=

            指定kickstart文件及其位置:
                inst.ks=

            指定使用TUI界面:
                inst.text
                inst.cmdline: 必须与kickstart文件一同使用

            网络功能选项:
                ip=method
                    可用method: dhcp, dhcp6, auto6
                ip=interface:method
                ip=IP::GATEWAY:NETMASK:HOSTNAME:INTERFACE:none
                nameserver=


kickstart文件:
    命令段
    软件包段
        %packages
            pack_name
            @group
            -pack_name: 不安装的包,但如果被依赖,也会被安装
    脚本段
        %pre
            安装前脚本
        %post
            安装后脚本

    图形配置接口:
        # yum install system-config-kickstart

    配置命令:
        # system-config-kickstart

    配置完成后的语法检查命令:
        # ksvalidator /path/to/ks_file


基于isolinux目录创建引导盘:
# mkisofs -R -J -T -v --no-emul-boot --boot-load-size 4 --boot-info-table -V "CentOS 6.5 x86_64 boot" -b isolinux/isolinux.bin -c isolinux/boot.cat -o /root/boot.iso myiso/

回顾:Linux, C6, C7
isolinux, anaconda, kickstart
system-config-kickstart, ksvalidator

批量部署:
    物理机:PXE
        负载均衡
    虚拟机:映像文件模板
        分布式文件系统

PXE + kickstart文件

DHCP,WEB,tftp

DHCP:

    DHCP:Dynamic Host Configuration Protocol
        ip/netmask
        gateway
        name server

    bootp

    C/S架构:Server, Client
        dhclient/dhcpd

        Client: DHCP DISCOVER
        Server: DHCP OFFER
        Client: DHCP REQUEST
        Server: DHCP ACK

        广播:

        租约:
            2hours

            DHCP REQUEST
            DHCP ACK

            1hour --> 2hours

            1hour --> 1.5hours --> 1.75hours --> 1.875hours

        DHCP DISCOVER

    DHCP Relay: 中继

安装:

# yum install dhcp

C6:
    服务脚本:/etc/rc.d/init.d/

    dhcpd, 67/udp
    dhclient, 68/udp

    /var/lib/dhcpd/dhcpd.leases

    service dhcpd configtest
        配置文件语法测试

保留地址:专用于某特定客户端的地址,不应该使用地址池中的地址;
    优先于地址池中的地址;

CentOS 7: 服务控制

    # systemctl is-enabled DAEMON.service
    # systemctl enable DAEMON.service
    # systemctl disable DAEMON.service

    # systemctl {start|stop|restart|status} DAEMON.service

总结:
dhcpd.conf
option domain-name
option domain-name-servers
option routers

    subnet NETWORK netmask MASK {
        range START_IP END_IP;

        host HOSTID {
            hardware ethernet 00:11:22:33:44:55;
            fixed-address IP;
        }
    }

tftp:
C/S
Server: 69/udp
listening:
accept():

            socket: 
                ip:port
                    172.16.100.7:69

    Client: 
        connetc()

        使用大于1023的一个其它进程未注册使用的随机端口

    session:
        ip:port ======> ip:port

守护进程:
独立守护进程:standalone
/etc/rc.d/init.d/*
xinetd: 超级守护进程
瞬时守护进程:
/etc/xinetd.d/*
配置启动:
(1) chkconfig SERVICE_NAME on
(2) 编辑配置文件,确保没有被禁用
disable = no

    修改后的生效需要重启超级守护进程:
    # service xinetd restart


DHCP:
    next-server
    pxelinux.0

如何配置PXE:
    1、配置dhcp服务
        subnet ... netmask ... {
            ...
            next-server TFTP-SERVER-IP;
            filename "pxelinux.0";
        }

    2、配置tftp server
        # yum install tftp-server
        # chkconfig tftp on
        # service xinetd restart
        # ss -unl | grep :69

    3、提供PXE的工作环境
        # yum install syslinux

        # cp /usr/share/syslinux/pxelinux.0  /var/lib/tftpboot/

    4、提供引导内核等文件

        挂载系统光盘,假设位置为/media/cdrom/

        # cp /media/cdrom/images/pxeboot/{vmlinuz,initrd.img}  /var/lib/tftpboot/
        # cp /media/cdrom/isolinux/{splash.jpg,vesamenu.c32,boot.msg}  /var/lib/tftpboot

        # mkdir /var/lib/tftpboot/pxelinux.cfg/
        # cp /media/cdrom/isolinux/isolinux.cfg  /var/lib/tftpboot/pxelinux.cfg/default

    5、提供安装源
        基于http服务实现

        # yum -y install httpd

        # mkdir -pv /var/www/html/centos/6/x84_64 

        # mount --bind /media/cdrom /var/www/html/centos/6/x84_64

    6、提供ks.cfg文件


作业:写成博客

回顾:系统安装过程
anaconda: 安装前配置、系统安装
引导参数:linux
ip, netmask, gateway, dns
ks=

kickstart文件:anaconda-ks.cfg
    命令段
    %packages
    @group
    [-]pkg_name
    %end

    脚本段:
        %pre:
            安装前脚本的执行环境为非完整的shell环境;

        %post:

dhcp服务:
    c/s:
        dhcpd: 67/udp
        dhclient: 68/udp

    守护进程:
        standalone
        xinetd
            transient

    CentOS 6:
        独立守护进程:
            chkconfig [--level ###] SERVICE on|off

        非独立守护进程
            1、chkconfig SERVICE on|off
            2、/etc/xinetd.d/SERVICE
                disable = {yes|no}

    CentOS 7:
        systemctl enable SERVICE.service

PXE: 
    tftp: 69/udp

    /etc/services文件
    /etc/protocols文件

    /var/lib/tftpboot/
        vmlinuz
        initrd.img
            安装源:images/pxelinux/
        vesamenu.c32
        splash.{jpg|png}
        boot.msg
            安装源:isolinux/
        pxelinux.0
            syslinux包
        pxelinux.cfg/
            default
                isolinux/isolinux.cfg

Linux故障排除:CentOS 6

紧急救援模式:rescue
    微小的Linux

1、grub损坏
    # chroot /mnt/sysimage
    # grub
    grub> root (DEVICE,PART)
    grub> setup (DEVICE)

    # grub-install /dev/DEVICE

2、bash损坏
    重装bash包

3、文件系统损坏
    进入紧急救援模式
    /etc/fstab,禁止开机自动挂载

4、驱动文件损坏
    grub: 
        e:
            kernel:
                emergency:
                    不会执行/etc/rc.d/rc.sysinit

总结:修复系统两种方式(紧急救援模式,grub下向内核传递参数(single, emergency))

脚本:写一个脚本,能够ping探测指定网络内的所有主机是否在线?

    #!/bin/bash
    #
    quitScript() {
        echo "Quit..."
    }    

    trap 'quitScript; exit 5' SIGINT

    cnetPing() {
        for i in {1..254}; do
        if ping -c 1 -W 1 $1.$i &> /dev/null; then
             echo "$1.$i is up."
        else
             echo "$1.$i is down."
        fi
         done
    }

    bnetPing() {
        for j in {0..255}; do
            cnetPing $1.$j 
        done
    }

    anetPing() {
        for m in {0..255}; do
            bnetPing $1.$m
        done
    }

    netType=`echo $1 | cut -d"." -f1`

    if [ $netType -ge 1 -a $netType -le 126 ]; then
        anetPing $netType
    elif [ $netType -ge 128 -a $netType -le 191 ]; then
        bnetPing $(echo $1 | cut -d'.' -f1,2)
    elif [ $netType -ge 192 -a $netType -le 223 ]; then
        cnetPing $(echo $1 | cut -d'.' -f1-3)
    else
        echo "Wrong"
        exit 2
    fi

信号捕捉:
trap 'COMMAND' SIGNALE
SIGINT

sed:

回顾:
    BRE:
        字符匹配:., [], [^]
        次数匹配: *, \?, \+, \{m,n\}
        锚定: ^, $, \<, \>
        分组引用: \(\), \1, \2, ...

    ERE:
        次数匹配:*, ?, +, {m,n}
        锚定:
        分组引用:(), \1, \2, ...
        或者:|

    grep: 文本过滤工具
    sed: stream editor,行编辑工具
    awk:文本报告生成器

sed [option]... '地址 编辑命令' FILE...

    地址:
        行范围:
            start_line[, end_line]
            /patten1/,/patten2/: 第一次被pattern1匹配到的行开始,到第一次被pattern2匹配到的行结束之间的所有行;
        特定行:
            /pattern/
        无地址:全文

    pattern space: 模式空间

    编辑命令:命令可在之前加!取反
        p:打印
        d: 删除
        i \text: 行上方,text即为插入的内容
        a \text: 行下方,
        r /path/from/some_file: 
        w /path/to/some_file: 把符合条件的行保存至指定的文件中
        =: 显示符合条件行的行号
        s///: s@@@
            g,i


    选项:
        -n: 静默模式,不显示模式空间中的内容
        -r: 支持使用扩展正则表达式
        -i: 修改原文件;
        -e: sed -e "" -e "" -e "", sed "{COM1;COM2;COM3}"

    1、替换/etc/inittab中的"id:3:initdefault"一行数字为5;
        sed -e 's/id:3:initdefault/id:5:initdefault/' 

    2、删除/etc/init.d/functions的空白行;
        /^[[:space:]]*$/d

    3、删除/boot/grub/grub.conf文件中行首的空白字符;
        s

    4、echo一个路径给sed,通过sed取出其目录名;例如echo "/etc/sysconfig/" | sed,返回/etc;
    # echo '/etc/sysconfig/' | sed 's@[^/]\{1,\}/\?$@@'

    高级命令:t, T, D, P, n, N, g, G, h, H

awk: 基本应用
可以实现对文件中每一行内容的每个字段分别进行格式化,而后进行显示

awk, --> nawk
gnu awk --> gawk 

基本语法:
    awk [option]... 'script' FILE...
    awk [option]... '/PATTERN/{action}' FILE...

    支持使用:变量(内置变量、自定义变量)、循环、条件、数组

    PATTERN:
        地址范围:
            start_line, end_line
            /pat1/,/pat2/
        特定行:
            /pattern/
            #
        表达式:比较
            >, >=, ==, <, <=, !=, ~
        BEGIN模式:在{action}开始之前执行一次
        END模式:在{action}结束之后执行一次;


    内置变量:
        NF:Number of Field
        FS: Field Seperator,输入分隔符;-F:
        OFS:输出时的字段分隔符

        awk分隔符常用的有四种:
            字段的:FS, OFS
            行的:

        引用变量的值,不需要以$开头,所有以$开头的变量,是用于引用字段的值;

    action:
        print "string"
        print $#
        print $1,$2,...


    练习:
    1、显示gid小于500的组;
    # gawk -F: '$3<500{print $1}' /etc/group

    2、显示默认shell为nologin的用户;
    # gawk -F: '$7~/nologin$/{print $1}' /etc/passwd

    3、显示eth0网卡配置文件的配置信息,只显示=号后的内容;
    # gawk -F= '{print $2}' /etc/sysconfig/network-scripts/ifcfg-eth0

    4、显示/etc/sysctl.conf文件定义的内核参数的参数名;
    # awk -F= '/^[^#]/{print $1}' /etc/sysctl.conf

    5、显示eth0网卡的ip地址;
    # ifconfig eth0 | awk -F: '/inet addr/{print $2}' | awk '{print $1}'
    # ifconfig eth0 | awk 'BEGIN{FS="[ :]+"}/inet addr/{print $4}'


    awk: 

回顾:sed, awk
sed语法:sed [option]... '地址 命令' FILE...
-r, -i, -e, -n, -f

awk语法:gawk [option]... '/pattern/{action}' FILE...
    -F

    模式:
        地址范围:
            起始行,结束行
        表达式:
            $n~/pattern/
        特定行:
        BEGIN
        END 

bash编程:

信号捕捉:trap 'COMMAND;COMMAND' 

循环控制:
    continue: 提前进入下一轮循环
        用于条件语句中,仅在某些个特殊场景提前进入;
    break [n]:跳出当前循环
        用于条件语句中,

    例如:查看用户登录

        #!/bin/bash
        #
        read -p "Plz enter a username: " userName

        while true; do
            if who | grep "\<$userName\>" &> /dev/null; then
                break
            fi
            echo "not here."
            sleep 5
        done

        echo "$userName is logged on."


        #!/bin/bash
        #
        read -p "Plz enter a username: " userName

        until who | grep "\<$userName\>" &> /dev/null; do
          sleep 5
          echo "not here"
        done

        echo "here"

写一个脚本:生成10个随机数,排序之;

数组:
    数组名+索引
        数组元素

    索引的表示方式:
        数字索引:a[index]
            a[0], a[1]

        bash 4.0的关联数组
            a[hello], a[hi]

        declare -a 
                -A

    支持稀疏格式:
    仅一维数组

数组的赋值:
    一次对一个元素赋值:
        a[0]=$RANDOM
        ...

    一次对全部元素赋值:
        a=(red blue yellow green)

    按索引进行赋值:
        a=([0]=green [3]=red [2]=blue [6]=yellow)

    命令替换:

    用户输入:
        read -a ARRAY


数组的访问:

    用索引访问:
        ARRAY[index]

数组的长度:
    ${#ARRAY[*]}
    ${#ARRAY[@]}

    练习:写一个脚本,生成10个随机数,保存至数组中;而后显示数组下标为偶数的元素;

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

从数组中挑选某元素:
    ${ARRAY[@]:offset:number}
        切片:
            offset: 偏移的元素个数
            number: 取出的元素的个数

    ${ARRAY[@]:offset}:取出偏移量后的所有元素

    ${ARRAY[@]}: 取出所有元素


数组复制:
    要使用${ARRAY[@]}

    $@: 每个参数是一个独立的串
    $*: 所有参数是一个串


向数组追加元素:

    示例:复制一个数组中下标为偶数的元素至一个新数组中
        #!/bin/bash
        declare -a mylogs
        logs=(/var/log/*.log)

        echo ${logs[@]}

        for i in `seq 0 ${#logs[@]}`; do
            if [ $[$i%2] -eq 0 ];then
               index=${#mylogs[@]}
               mylogs[$index]=${logs[$i]}
            fi
        done

        echo ${mylogs[@]}


从数组中删除元素:

    unset ARRAY[index]

练习1:生成10个随机数,升序排序

    #!/bin/bash
    for((i=0;i<10;i++))
    do
        rnd[$i]=$RANDOM
    done

    echo -e "total=${#rnd[@]}\n${rnd[@]}\nBegin to sort"

    for((i=9;i>=1;i--))
    do
        for((j=0;j<i;j++))
        do
            if [ ${rnd[$j]} -gt ${rnd[$[$j+1]]} ] ;then
                swapValue=${rnd[$j]}
                rnd[$j]=${rnd[$[$j+1]]}
                rnd[$[$j+1]]=$swapValue     
            fi
        done
    done

    echo ${rnd[@]}  

练习2:打印九九乘法表

    #!/bin/bash
    for((i=1;i<=9;i++))
    do 
        strLine=""
        for((j=1;i<=9;j++))
        do
            strLine=$strLine"$i*$j="$[$i*$j]"\t"
            [ $i -eq $j ] && echo -e $strLine && break
        done
    done

字符串操作:

字符串切片:
    ${string:offset:length}

取尾部的指定个数的字符:
    ${string: -length}

取子串:基于模式
    ${variable#*word}:在variable中存储字串上,自左而右,查找第一次出现word,删除字符开始至此word处的所有内容;
    ${variable##*word}:在variable中存储字串上,自左而右,查找最后一次出现word,删除字符开始至此word处的所有内容; 
        file='/var/log/messages'
            ${file#*/}: 返回的结果是var/log/messages
            ${file##*/}: 返回messages

    ${variable%word*}: 在variable中存储字串上,自右而左,查找第一次出现word,删除此word处至字串尾部的所有内容;
    ${variable%%world*}:在variable中存储字串上,自右而左,查找最后一次出现word,删除此word处至字串尾部的所有内容;
        file='/var/log/messages'
            ${file%*/}: 返回的结果是/var/log
            ${file%%*/}: 返回结果为空

        phonenumber='010-110-8'
            ${phonenumber%%-*}
            ${phonenumber##*-}

        url="http://www.magedu.com:80"

查找替换:
    ${variable/pattern/substi}: 替换第一次出现
    ${variable//pattern/substi}:替换所有的出现

    ${variable/#pattern/substi}:替换行首被pattern匹配到的内容
    ${variable/%pattern/substi}:    行尾

    pattern可以使用globbing中的元字符:
        *
        ?

查找删除:
    ${variable/pattern}
    ${variable//pattern}
    ${variable/#pattern}
    ${variable/%pattern}

大小写转换:
    小-->大:${variable^^}
    大-->小:${variable,,}

变量赋值操作:

    ${parameter:-word}
          Use  Default  Values.  If parameter is unset or null, the expansion of word is substituted.  Otherwise, the value of parameter is
          substituted.
    ${parameter:=word}
          Assign Default Values.  If parameter is unset or null, the expansion of word is assigned to parameter.  The value of parameter is
          then substituted.  Positional parameters and special parameters may not be assigned to in this way.
    ${parameter:?word}
          Display Error if Null or Unset.  If parameter is null or unset, the expansion of word (or a message to that effect if word is not
          present) is written to the standard error and the shell, if it is not interactive, exits.  Otherwise, the value of  parameter  is
          substituted.
    ${parameter:+word}
          Use Alternate Value.  If parameter is null or unset, nothing is substituted, otherwise the expansion of word is substituted.


    ${variable:-string}
        variable为空或未设定,那么返回string,否则,返回variable变量的值;

    ${variable:=string}
        variable为空或未设定,则返回string,且将string赋值给变量variable,否则,返回variable的值;


为脚本使用配置文件,并确保某变量有可用值的方式
    variable=${variable:-default vaule}

练习:读取/etc/sysconfig/network文件,利用其HOSTNAME变量的值设置主机名;


库:函数的组合,通常是一个文件

书:
《Linux命令行和shell编程宝典》
《abs-guide》

命令:
mktemp
# mktemp
--tmpdir=

        -d: 创建临时目录

install:
    复制文件
    创建目录

    增强型的复制命令:
        -o user
        -g group
        -m mode

        -d : 创建目录

练习:
1、使用install创建目录/tmp/test;
2、在/tmp/test目录创建多个以.txt和.doc结尾的文件;
3、将.txt结尾的文件的文件名后缀改为.TXT;.doc的改为.DOC (使用bash内置的字符串处理机制)

博客:总结bash脚本编程的所有语法知识点,要求语言通顺,案例详实;

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容

  • feisky云计算、虚拟化与Linux技术笔记posts - 1014, comments - 298, trac...
    不排版阅读 3,813评论 0 5
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,580评论 18 139
  • 1.Linux下如何用命令查看实时日志(完整命令) tail -f 路径.log查看前多少行 tai-200f 路...
    qianyewhy阅读 2,239评论 0 11
  • linux资料总章2.1 1.0写的不好抱歉 但是2.0已经改了很多 但是错误还是无法避免 以后资料会慢慢更新 大...
    数据革命阅读 12,127评论 2 34
  • 昨天夜里忽然刮起了大风,电闪雷鸣的下了一晚上的雨,于是睡的的也格外不安宁。雨点像是要冲破玻璃冲进我的心,风从门缝和...
    琼姐夫阅读 255评论 0 0