《鸟哥的Linux私房菜》第四版辅助文档

0、计算机概论

0.1、电脑:辅助人脑的好工具

0.1.2、一切设计的起点:CPU的架构

  1. 关于32位CPU和64位CPU的说明
  • 32位CPU的意思就是CPU每次解析数据是32bits,也就是4B,那么支持的地址就是4B长度的,也就是支持的最大内存是2^32(个地址)*1Byte=4GB。
  • 同理64位CPU每次解析数据是64位,也就是8B,那么支持的地址长度就是8B长度,如果按照字节进行编址的话,支持的最大内存就是2^64(个地址)*1Byte。
  1. Intel/AMD的x86架构中的重要指令(以下内容了解即可)
  • MMX(Multi Media eXtension,多媒体扩展指令集)指令集是Intel公司于1996年推出的一项多媒体指令增强技术。MMX指令集中包括有57条多媒体指令,通过这些指令可以一次处理多个数据,在处理结果超过实际处理能力的时候也能进行正常处理,这样在软件的配合下,就可以得到更高的性能。
  • SSE(Streaming SIMD Extensions,单指令多数据流扩展)指令集是Intel在Pentium III处理器中率先推出的。其实,早在PIII正式推出之前,Intel公司就曾经通过各种渠道公布过所谓的KNI(Katmai New Instruction)指令集,这个指令集也就是SSE指令集的前身,并一度被很多传媒称之为MMX指令集的下一个版本,即MMX2指令集。
  • SSE2(Streaming SIMD Extensions 2,Intel官方称为单指令多数据流技术扩展 2或单指令多数据流扩展指令集 2)指令集是Intel公司在SSE指令集的基础上发展起来的。相比于SSE,SSE2使用了144个新增指令,扩展了MMX技术和SSE技术,这些指令提高了广大应用程序的运行性能。随MMX技术引进的单指令多数据流整数指令从64位扩展到了128 位,使SIMD整数类型操作的有效执行率成倍提高。双倍精度浮点(实数)单指令多数据流指令允许以 单指令多数据流格式同时执行两个浮点(实数)操作,提供双倍精度操作支持有助于加速内容创建、财务、工程和科学应用。除SSE2指令之外,最初的SSE指令也得到增强,通过支持多种数据类型(例如,双字和四字)的算术运算,支持灵活并且动态范围更广的计算功能。

0.2、个人电脑架构与相关设备组件

0.2.1、执行脑袋运算与判断的CPU

  1. 什么是CPU架构?
  • 个人理解:CPU架构就是CPU和其他的单元部件是如何摆放的。

0.2.3、显卡

  1. 什么是GPU?
  • 图形处理器(英语:Graphics Processing Unit,缩写:GPU),又称显示核心、视觉处理器、显示芯片,是一种专门在个人电脑、工作站、游戏机和一些移动设备(如平板电脑、智能手机等)上做图像和图形相关运算工作的微处理器。
  • GPU使显卡减少了对CPU的依赖,并进行部分原本CPU的工作,尤其是在3D图形处理时GPU所采用的核心技术有硬件T&L(几何转换和光照处理)、立方环境材质贴图和顶点混合、纹理压缩和凹凸映射贴图、双重纹理四像素256位渲染引擎等,而硬件T&L技术可以说是GPU的标志。GPU的生产商主要有NVIDIA和ATI。
  • GPU存在于显卡中。

0.2.8、选购须知

  1. 关于速度瓶颈分析的例题
    由于内存使用的是DDR3-1600型号,所以数据位宽是64位,频率是1600MHz,故带宽为频率位宽=64bit1600MHz=12.8GB/s。
    由于磁盘列阵卡使用的是PCIe 2.0 x8型号,PCIe 2.0 x1的250MB/s,因为后面的x1表示一个通道,x8表示8个通道,故PCle 2.0 x8是PCIe 2.0 x1的8倍,所以带宽为4GB/s。
    由于安装了8块3TB理论速度可以达到200MB/s的硬盘,而且是可叠加访问速度的RAID 0 配置,因此速度在200MB/s~1.6GB/s之间。
    网络使用的是千兆网卡,即1000Mbit/s,也就是125MB/s,安装在PCIe 2.0 x1的接口上,PCIe 2.0 x1的带宽是500MB/s,但是千兆网络最多只能达到125MB/s,故网络接口的带宽是125MB/s。
    故综上所述,速度最慢的是网络接口的125MB/s,所以要让整机性能提升,需要解决网络问题。

0.6、本章习题

  • 第一题
    截止到2020.6,最快的超级计算机:
    名称:Supercomputer Fugaku - Supercomputer Fugaku, A64FX 48C 2.2GHz, Tofu interconnect D, Fujitsu RIKEN Center for Computational Science
    所在位置:日本
    使用的CPU型号与规格:富士通ARM处理器 A64FX 48C 2.2GHz
    总共使用CPU数量:7,299,072

  • 第二题:
    CPU:AMD Athlon II X2 240,外频:200Mhz,倍频:14X,主频为2.8GHz。
    内存:4GB 1600MHz DDR3 Non-ECC CL11 DIMM 1Rx8

  • 第三题:
    CPU:Inter Pentium G620 2.6GHz
    内存:4GBytes;DDR3
    显卡:PCI Express 3.0;2GBytes
    主板:ASUSTEK COMPUTER INC;Intel H61(南桥)。
    总结:如果是Windows操作系统可以使用鲁大师软件或者CPUID CPU-Z软件查询电脑硬件配置。如果是Linux操作系统可以使用cat /proc/cpuinfo或者lspci等命令查看各项组件型号。

  • 第四题:
    (1)DMI2 5GT/S;(2)三级缓存 8MB;(3)16条PCIe 通道。

  • 第五题:
    (1)SATA3(6Gbps,即6Gbit/s);(2)读:280MB/S(SATA2),550MB/S(SATA3);写:260MB/S(SATA2),520MB/S(SATA3);(3)IOPS的值为:6187(读),17740(写)。

1、Linux是什么与如何学习

1.6、本章习题

  • 第一题:
    截止到2020年6月22日,Linux内核最新稳定版是 5.7.5
    总结:要查询目前linux内核目前的最新版本可以直接登陆网站(https://www.kernel.org/)进行查询即可。如果要直接在Linux系统中查询内核版本,可以通过命令(uname -r)来查询。
  • 第二题:
    Linux·吉祥物名字叫做tuxedo
  • 第三题:
    1.5 Cupcake —> 2.6.27
    1.6 Donut —> 2.6.29
    2.0/1 Eclair —> 2.6.29
    2.2.x Froyo —> 2.6.32
    2.3.x Gingerbread —> 2.6.35
    3.x.x Honeycomb —> 2.6.36
    4.0.x Ice Cream San —> 3.0.1
    4.1.x Jelly Bean —> 3.0.31
    4.2.x Jelly Bean —> 3.4.0
    4.3 Jelly Bean —> 3.4.39
    4.4 Kit Kat —> 3.10
    5.x Lollipop —> 3.16.1
    6.0 Marshmallow —> 3.18.10
    7.0 Nougat —> 4.4.1
    7.1 Nougat —> 4.4.1 (To be updated)
    总结:详细的Android与Linux内核的对应关系参考:https://blog.csdn.net/ly890700/java/article/details/75040704
  • 第四题:
    如果没有禁用主板自带网卡,则禁用后再试。
    如果网卡驱动没有安装,则安装驱动之后再试。
    如果系统网卡需要资源已经被其它设备占用,则重新安装主板驱动,再装网卡
    如果有病毒无法正常安装设备驱动程序,先杀毒,再安装。
    如果网卡在pci 插槽里没有安插到位,重新插好,再试试。
  • 第五题:
    运算单元:用来执行当前指令所规定的算术运算和逻辑运算,具有定点和浮点运算功能。
    控制单元:指挥微处理器执行指令操作的功能。
    寄存器组:用来暂存操作数,中间结果和处理结果,它构成了微处理器内部的小型存贮空间,其容量大小影响到微处理器的效率。
    总线接口单元:提供微处理器与周围其它硬件的接口,有效地将微处理器的地址、数据和控制等信息通过总线和各相关部件接通。
    输入/输出接口单元。
  • 第六题:
    自己的回答:操作系统内核可以控制硬件完成相应的功能,而应用程序如果想要使用硬件的功能需要通过系统调用实现,系统调用可以理解为是API,由于Windows和Linux提供的API是不一样的,在Windows上运行的游戏,在编写的时候使用Windows系统提供的API,所以放在Linux系统上是无法运行的。
  • 第七题:
    Linux各个发行版差不太多,唯一的差别可能就是各个厂商所开发出来的管理工具,以及套件管理的模式不同。
  • 第八题:
    UNIX是Thompson和Ritchie合作写出来的。
    GNU计划是斯托曼先生发起的。
  • 第九题:
    GNU 工程 开始于一九八四年,旨在发展一个类似 Unix ,且为 自由软件 的完整操作系统:GNU 系统。(GNU 是由“GNU’s Not Unix”所递回定义出的首字母缩写语;它的发音为“guh-NEW”)。各种使用 Linux 作为内核的 GNU 操作系统正被广泛地使用著;虽然这些系统通常被称作为“Linux”,但是它们应该更精确地被称为 GNU/Linux 系统 。主要由FSF基金会支持。
  • 第十题:
    自己的回答:多用户就是,多个终端用户同时使用计算机,各个用户在使用计算机的时候感受不到其他用户的存在。多任务是指,CPU在一段时间间隔内执行多个任务。
    稍微标准一些的回答:多用户是可以在系统上创建多个用户,且多个用户可以同时使用系统资源;对于多任务,理论上一个CPU在一个时间内仅能进行一个程序,多任务,即计算机对于多个任务,会在不同的程序间切换,让用户感觉多个任务是在同步进行(现在的多核心计算机可以实现真正的多任务同时处理)。Linux是一个真实的、完整的多用户多任务操作系统,可以在Linux上建立多个用户,而多个用户可以在同一时间内登录同一个系统执行不同的任务而互不影响。
  • 第十一题:
    自己的回答:一个软件使用了GPL版权声明之后,就成了自由软件,自由软件的重点并不是指“免费”,而是指具有“自由度”的软件,用户可以自由的执行、复制、再发行、学习、修改与强化自由软件。
  • 第十二题:
    什么是POSIX:POSIX是可移植操作系统接口的缩写,重点在于规范内核与应用程序之间的接口,这是由美国电器与电子工程师学会(IEEE)所发布的一项标准。
    POSIX对于Linux的好处:因为POSIX标准主要是针对UNIX与一些软件运行时的标准规范,主要依据这些标准规范来设计的内核与软件,理论上可以搭配在一起执行。而Linux的开发就是依据这个POSIX的标准规范,UNIX上面的软件也是遵循POSIX标准来设计的,这样的话,让Linux很容易地能与UNIX兼容共享互有的软件。同时,因为Linux直接发不到了网络上,提供大家下载,所以在流通的速度上相当快,导致Linux的使用率大增,这些都是造成Linux大受欢迎的几个重要因素。
  • 第十三题:
    Linux的成功可以归结为以下几点:
    托瓦兹的个人能力:一开始,只有一个人的托瓦兹开发Linux的方法相当务实,他将Linux内核放在FTP上,用户下载之后如果发生了问题或有特殊的需求(需要某些硬件的驱动程序),会主动反馈给托瓦兹,托瓦兹会尽自己的能力解决问题。
    广大黑客志愿者加入:由于托瓦兹总是有些硬件无法取得,所以无法编写驱动程序,所以这时就有很多有相应硬件的志愿者主动站出来帮忙编写驱动程序,之后托瓦兹将这些驱动程序进行测试,没有问题就将其加入到内核中。
    内核功能详细分工发展:由于一个人测试内核功能太费力,有的人自愿担任副手帮助托瓦泽将其他志愿者开发的补丁程序或新功能程序进行测试,之后再由托瓦兹进行整合。这种分层工作的方式让Linux的开发更加的容易。# 0、计算机概论

0.1、电脑:辅助人脑的好工具

0.1.2、一切设计的起点:CPU的架构

  1. 关于32位CPU和64位CPU的说明
  • 32位CPU的意思就是CPU每次解析数据是32bits,也就是4B,那么支持的地址就是4B长度的,也就是支持的最大内存是2^32(个地址)*1Byte=4GB。
  • 同理64位CPU每次解析数据是64位,也就是8B,那么支持的地址长度就是8B长度,如果按照字节进行编址的话,支持的最大内存就是2^64(个地址)*1Byte。
  1. Intel/AMD的x86架构中的重要指令(以下内容了解即可)
  • MMX(Multi Media eXtension,多媒体扩展指令集)指令集是Intel公司于1996年推出的一项多媒体指令增强技术。MMX指令集中包括有57条多媒体指令,通过这些指令可以一次处理多个数据,在处理结果超过实际处理能力的时候也能进行正常处理,这样在软件的配合下,就可以得到更高的性能。
  • SSE(Streaming SIMD Extensions,单指令多数据流扩展)指令集是Intel在Pentium III处理器中率先推出的。其实,早在PIII正式推出之前,Intel公司就曾经通过各种渠道公布过所谓的KNI(Katmai New Instruction)指令集,这个指令集也就是SSE指令集的前身,并一度被很多传媒称之为MMX指令集的下一个版本,即MMX2指令集。
  • SSE2(Streaming SIMD Extensions 2,Intel官方称为单指令多数据流技术扩展 2或单指令多数据流扩展指令集 2)指令集是Intel公司在SSE指令集的基础上发展起来的。相比于SSE,SSE2使用了144个新增指令,扩展了MMX技术和SSE技术,这些指令提高了广大应用程序的运行性能。随MMX技术引进的单指令多数据流整数指令从64位扩展到了128 位,使SIMD整数类型操作的有效执行率成倍提高。双倍精度浮点(实数)单指令多数据流指令允许以 单指令多数据流格式同时执行两个浮点(实数)操作,提供双倍精度操作支持有助于加速内容创建、财务、工程和科学应用。除SSE2指令之外,最初的SSE指令也得到增强,通过支持多种数据类型(例如,双字和四字)的算术运算,支持灵活并且动态范围更广的计算功能。

0.2、个人电脑架构与相关设备组件

0.2.1、执行脑袋运算与判断的CPU

  1. 什么是CPU架构?
  • 个人理解:CPU架构就是CPU和其他的单元部件是如何摆放的。

0.2.3、显卡

  1. 什么是GPU?
  • 图形处理器(英语:Graphics Processing Unit,缩写:GPU),又称显示核心、视觉处理器、显示芯片,是一种专门在个人电脑、工作站、游戏机和一些移动设备(如平板电脑、智能手机等)上做图像和图形相关运算工作的微处理器。
  • GPU使显卡减少了对CPU的依赖,并进行部分原本CPU的工作,尤其是在3D图形处理时GPU所采用的核心技术有硬件T&L(几何转换和光照处理)、立方环境材质贴图和顶点混合、纹理压缩和凹凸映射贴图、双重纹理四像素256位渲染引擎等,而硬件T&L技术可以说是GPU的标志。GPU的生产商主要有NVIDIA和ATI。
  • GPU存在于显卡中。

0.2.8、选购须知

  1. 关于速度瓶颈分析的例题
    由于内存使用的是DDR3-1600型号,所以数据位宽是64位,频率是1600MHz,故带宽为频率位宽=64bit1600MHz=12.8GB/s。
    由于磁盘列阵卡使用的是PCIe 2.0 x8型号,PCIe 2.0 x1的250MB/s,因为后面的x1表示一个通道,x8表示8个通道,故PCle 2.0 x8是PCIe 2.0 x1的8倍,所以带宽为4GB/s。
    由于安装了8块3TB理论速度可以达到200MB/s的硬盘,而且是可叠加访问速度的RAID 0 配置,因此速度在200MB/s~1.6GB/s之间。
    网络使用的是千兆网卡,即1000Mbit/s,也就是125MB/s,安装在PCIe 2.0 x1的接口上,PCIe 2.0 x1的带宽是500MB/s,但是千兆网络最多只能达到125MB/s,故网络接口的带宽是125MB/s。
    故综上所述,速度最慢的是网络接口的125MB/s,所以要让整机性能提升,需要解决网络问题。

0.6、本章习题

  • 第一题
    截止到2020.6,最快的超级计算机:
    名称:Supercomputer Fugaku - Supercomputer Fugaku, A64FX 48C 2.2GHz, Tofu interconnect D, Fujitsu RIKEN Center for Computational Science
    所在位置:日本
    使用的CPU型号与规格:富士通ARM处理器 A64FX 48C 2.2GHz
    总共使用CPU数量:7,299,072
  • 第二题:
    CPU:AMD Athlon II X2 240,外频:200Mhz,倍频:14X,主频为2.8GHz。
    内存:4GB 1600MHz DDR3 Non-ECC CL11 DIMM 1Rx8。
    显卡接口:PCIe 2。
    主板:品牌是微星,北桥型号显示不清楚,南桥没找到,BIOS芯片位置没找到,有无集成的网卡和声卡也不知道。
    硬盘:连接接口是SATA3.4,硬盘容量500GB,7200转,16MB的缓存。
    总结:查询硬件资料的时候可以直接在百度上面查,也可以直接在对应硬件的官网查,前提是知道硬件的型号。
  • 第三题:
    CPU:Inter Pentium G620 2.6GHz
    内存:4GBytes;DDR3
    显卡:PCI Express 3.0;2GBytes
    主板:ASUSTEK COMPUTER INC;Intel H61(南桥)。
    总结:如果是Windows操作系统可以使用鲁大师软件或者CPUID CPU-Z软件查询电脑硬件配置。如果是Linux操作系统可以使用cat /proc/cpuinfo或者lspci等命令查看各项组件型号。
  • 第四题:
    (1)DMI2 5GT/S;(2)三级缓存 8MB;(3)16条PCIe 通道。
  • 第五题:
    (1)SATA3(6Gbps,即6Gbit/s);(2)读:280MB/S(SATA2),550MB/S(SATA3);写:260MB/S(SATA2),520MB/S(SATA3);(3)IOPS的值为:6187(读),17740(写)。

1、Linux是什么与如何学习

1.6、本章习题

  • 第一题:
    截止到2020年6月22日,Linux内核最新稳定版是 5.7.5
    总结:要查询目前linux内核目前的最新版本可以直接登陆网站(https://www.kernel.org/)进行查询即可。如果要直接在Linux系统中查询内核版本,可以通过命令(uname -r)来查询。
  • 第二题:
    Linux·吉祥物名字叫做tuxedo
  • 第三题:
    1.5 Cupcake —> 2.6.27
    1.6 Donut —> 2.6.29
    2.0/1 Eclair —> 2.6.29
    2.2.x Froyo —> 2.6.32
    2.3.x Gingerbread —> 2.6.35
    3.x.x Honeycomb —> 2.6.36
    4.0.x Ice Cream San —> 3.0.1
    4.1.x Jelly Bean —> 3.0.31
    4.2.x Jelly Bean —> 3.4.0
    4.3 Jelly Bean —> 3.4.39
    4.4 Kit Kat —> 3.10
    5.x Lollipop —> 3.16.1
    6.0 Marshmallow —> 3.18.10
    7.0 Nougat —> 4.4.1
    7.1 Nougat —> 4.4.1 (To be updated)
    总结:详细的Android与Linux内核的对应关系参考:https://blog.csdn.net/ly890700/java/article/details/75040704
  • 第四题:
    如果没有禁用主板自带网卡,则禁用后再试。
    如果网卡驱动没有安装,则安装驱动之后再试。
    如果系统网卡需要资源已经被其它设备占用,则重新安装主板驱动,再装网卡
    如果有病毒无法正常安装设备驱动程序,先杀毒,再安装。
    如果网卡在pci 插槽里没有安插到位,重新插好,再试试。
  • 第五题:
    运算单元:用来执行当前指令所规定的算术运算和逻辑运算,具有定点和浮点运算功能。
    控制单元:指挥微处理器执行指令操作的功能。
    寄存器组:用来暂存操作数,中间结果和处理结果,它构成了微处理器内部的小型存贮空间,其容量大小影响到微处理器的效率。
    总线接口单元:提供微处理器与周围其它硬件的接口,有效地将微处理器的地址、数据和控制等信息通过总线和各相关部件接通。
    输入/输出接口单元。
  • 第六题:
    自己的回答:操作系统内核可以控制硬件完成相应的功能,而应用程序如果想要使用硬件的功能需要通过系统调用实现,系统调用可以理解为是API,由于Windows和Linux提供的API是不一样的,在Windows上运行的游戏,在编写的时候使用Windows系统提供的API,所以放在Linux系统上是无法运行的。
  • 第七题:
    Linux各个发行版差不太多,唯一的差别可能就是各个厂商所开发出来的管理工具,以及套件管理的模式不同。
  • 第八题:
    UNIX是Thompson和Ritchie合作写出来的。
    GNU计划是斯托曼先生发起的。
  • 第九题:
    GNU 工程 开始于一九八四年,旨在发展一个类似 Unix ,且为 自由软件 的完整操作系统:GNU 系统。(GNU 是由“GNU’s Not Unix”所递回定义出的首字母缩写语;它的发音为“guh-NEW”)。各种使用 Linux 作为内核的 GNU 操作系统正被广泛地使用著;虽然这些系统通常被称作为“Linux”,但是它们应该更精确地被称为 GNU/Linux 系统 。主要由FSF基金会支持。
  • 第十题:
    自己的回答:多用户就是,多个终端用户同时使用计算机,各个用户在使用计算机的时候感受不到其他用户的存在。多任务是指,CPU在一段时间间隔内执行多个任务。
    稍微标准一些的回答:多用户是可以在系统上创建多个用户,且多个用户可以同时使用系统资源;对于多任务,理论上一个CPU在一个时间内仅能进行一个程序,多任务,即计算机对于多个任务,会在不同的程序间切换,让用户感觉多个任务是在同步进行(现在的多核心计算机可以实现真正的多任务同时处理)。Linux是一个真实的、完整的多用户多任务操作系统,可以在Linux上建立多个用户,而多个用户可以在同一时间内登录同一个系统执行不同的任务而互不影响。
  • 第十一题:
    自己的回答:一个软件使用了GPL版权声明之后,就成了自由软件,自由软件的重点并不是指“免费”,而是指具有“自由度”的软件,用户可以自由的执行、复制、再发行、学习、修改与强化自由软件。
  • 第十二题:
    什么是POSIX:POSIX是可移植操作系统接口的缩写,重点在于规范内核与应用程序之间的接口,这是由美国电器与电子工程师学会(IEEE)所发布的一项标准。
    POSIX对于Linux的好处:因为POSIX标准主要是针对UNIX与一些软件运行时的标准规范,主要依据这些标准规范来设计的内核与软件,理论上可以搭配在一起执行。而Linux的开发就是依据这个POSIX的标准规范,UNIX上面的软件也是遵循POSIX标准来设计的,这样的话,让Linux很容易地能与UNIX兼容共享互有的软件。同时,因为Linux直接发不到了网络上,提供大家下载,所以在流通的速度上相当快,导致Linux的使用率大增,这些都是造成Linux大受欢迎的几个重要因素。
  • 第十三题:
    Linux的成功可以归结为以下几点:
    托瓦兹的个人能力:一开始,只有一个人的托瓦兹开发Linux的方法相当务实,他将Linux内核放在FTP上,用户下载之后如果发生了问题或有特殊的需求(需要某些硬件的驱动程序),会主动反馈给托瓦兹,托瓦兹会尽自己的能力解决问题。
    广大黑客志愿者加入:由于托瓦兹总是有些硬件无法取得,所以无法编写驱动程序,所以这时就有很多有相应硬件的志愿者主动站出来帮忙编写驱动程序,之后托瓦兹将这些驱动程序进行测试,没有问题就将其加入到内核中。
    内核功能详细分工发展:由于一个人测试内核功能太费力,有的人自愿担任副手帮助托瓦泽将其他志愿者开发的补丁程序或新功能程序进行测试,之后再由托瓦兹进行整合。这种分层工作的方式让Linux的开发更加的容易。

2、主机规划与磁盘分区

2.5、本章习题

  • 第一题:
    电脑的功率:106W
    每小时用电量:106 / 1000 = 0.106度
    每天使用时间:8小时左右
    2020年电费:0.5469元/度
    一年的使用费用:大约0.106 * 8 * 0.5469 * 365 = 169.276元
    总结
    可以通过鲁大师直接查询电脑的功率,如下图:
    在这里插入图片描述
    用功率(单位:瓦)除以1000就可以得到每小时耗电量是多少度。
  • 第二题:
    我的回答:一台计算机并不是CPU足够快整体速度就快,如果内存容量比较小的,并且需要处理的任务比较多的话,会出现频繁的换入换出现象,这种频繁的换入换出会影响计算机整体的性能。
    其他答案:在性能方面并非只考虑CPU的能力而已,速度的快慢与整体系统的最慢的那个设备有关。CPU再快,其他硬件无法配合CPU的高速处理能力,也无法发挥CPU的最佳性能,计算机整体性能就会卡在最慢的硬件的瓶颈上。
  • 第三题:
    我的回答:Linux对于硬件的要求需要根据个人的用途和需求来确定。并不一定要在非常好的硬件设备上才能安装Linux,如果个人的需求比较的简单,甚至在一些过时的硬件上也可以运行Linux。
    其他答案:Linux对于硬件的要求因计算机的用途而定,且Linux对于硬件的最低要求较其它系统都低。所以配置不一定要高,因地制宜即可。
  • 第四题:
    我的答案:首先需要根据个人的需求和用途选择合适的Linux发行版。之后看个人的用途在硬件方面的需求,不同的需求对硬件的配置要求是不一样的。最后最重要的就是进行硬盘的分区,同样也是要根据用途来进行分,分区方式不唯一,以个人对于Linux的用途来定。
    其他答案:规划主机的定位与角色。主机是否开放网络服务,是否需要大量运算,是否需要很大的硬盘容量来服务客户端的使用,套间选择安装等都是要考虑的内容。
  • 第五题:
    SATA 硬盘在Linux中的设备文件名:/dev/sd[a-p]
    CD - ROM在Linux中的设备文件名:/dev/cdrom
    打印机在Linux中的设备文件名:/dev/usb/lp[0-15]
  • 第六题:
    常见的硬盘和主板的接口是SATA和IDE。不过目前IDE已经被淘汰了。

3、安装CentOS 7.x

4、首次登陆与在线求助

4.1、首次登陆系统

4.2、命令行模式下命令的执行

4.2.1、开始执行命令

  1. 关于输入命令后输出的结果是乱码的问题
    在Centos中通过locale来设置程序运行的不同语言环境,locale由ANSI C提供支持。locale的命名规则为<语言><地区>.<字符集编码>,如zh_CN.UTF-8,zh代表中文,CN代表大陆地区,UTF-8表示字符集。在locale环境中,有一组变量,代表国际化环境中的不同设置。
    LC_COLLATE
    定义该环境的排序和比较规则
    LC_CTYPE
    用于字符分类和字符串处理,控制所有字符的处理方式,包括字符编码,字符是单字节还是多字节,如何打印等。是最重要的一个环境变量。
    LC_MONETARY
    货币格式
    LC_NUMERIC
    非货币的数字显示格式
    LC_TIME
    时间和日期格式
    LC_MESSAGES
    提示信息的语言。另外还有一个LANGUAGE参数,它与LC_MESSAGES相似,但如果该参数一旦设置,则LC_MESSAGES参数就会失效。LANGUAGE参数可同时设置多种语言信息,如LANGUANE=”zh_CN.GB18030:zh_CN.GB2312:zh_CN”。
    LANG
    LC
    *的默认值,是最低级别的设置,如果LC_*没有设置,则使用该值。类似于 LC_ALL。
    LC_ALL
    它是一个宏,如果该值设置了,则该值会覆盖所有LC_*的设置值。注意,LANG的值不受该宏影响。
    实际操作如下:
    在这里插入图片描述输入locale之后可以看到各种信息使用的字符集。
    在这里插入图片描述如上图可以直接通过命令行输入“LANG=…”的方式直接更改字符集。
    在这里插入图片描述如果LANG没有值的话,LC_*会采用默认值POSIX。
    在这里插入图片描述如果对LC_ALL设置了值的话,所有的LC_*会和LC_*的值保持一致,但是LANG的值并不会因为LC_ALL的改变而改变。
    在这里插入图片描述不能直接通过命令行输入某个LC_*来改变其值。
    总结:所有的LC_*的值会和LANG保持一致,如果LANG没有值那么所有的LC_*会采用默认值,如果LC_ALL有值的话,所有的LC_*会合LC_ALL一样,但是改变LC_ALL并不会改变LANG的值。另外还有一点需要注意,纯命令行模式(ctrl + alt + F2~6可以切换)下,如果采用中文字符,命令输出中文信息的时候会出现乱码,因此需要改成英文字符集。还有一点要注意,命令更改字符集之后,如果重启之后会回到系统一开始的默认值。如果要让系统默认的字符集是XXX的话,可以修改系统配置文件/etc/locale.conf的内容(可以使用nano编辑器来进行修改)。

4.7、本章习题

1、第一题:

  • 物理终端:直接连接在主机上的显示器、键盘鼠标统称。在实际机架式服务器部署中,一般是多台服务器共享一套终端,简称KVM(Keyboard键盘,video显示器,mouse鼠标)
  • 虚拟终端(tty):附加在物理终端之上,用软件方式虚拟实现,CentOS默认启用6个虚拟终端,可以通过快捷键来切换,切换方式:Ctrl-Alt-F[1–6], 对应的文件是/dev/tty#。可以同过tty命令来查看当前的虚拟终端号。tty是teletypewriter的简称。
  • 伪终端(pty):两种应用场景,第一在图形界面下打开的命令行接口,第二基于ssh协议或telnet协议等远程打开的命令行界面,是运维工程师用的最多的一种连接服务器的方式。pts(pseudo-terminal slave)是pty的实现方法。

2、第二题:

  • 我的回答:Linux默认有6个终端接口可以使用,可以使用组合键Ctrl + Alt + F1~6进行切换。

3、第三题:

  • 我的回答:在Linux系统中/VBird和/vbird不是同一个文件。因为Linux系统的文件命名是区分大小写的。

4、第四题:

  • 我的回答:如果是选项不是很清楚可以通过命令(date --help)进行查询。如果不知道这个命令是干什么的,可以通过命令(man date)和命令(info date)进行查询。

5、第五题:

  • 我的回答:可以通过命令(shutdown -h 1:30)来关机。

6、第六题:

  • 我的回答:如果X Windows突然挂了,可以通过命令(startx)重启X Windows。
  • 其他答案:[Ctrl]+[Alt]+[Backspace]。

7、第七题:

  • 我的回答:可以通过日历命令(cal 2 5 2010)查看,是周日。

8、第八题:

  • 我的回答:经过命令(man date)查询,如果要将日期显示成XXXX/XX/XX-XX:XX的格式,可以通过命令(date +%Y/%m/%d-%H:%M)。

9、第九题:

  • 可以通过Ctrl + Alt + F2~6进入。

10、第十题:

  • 我的回答:Tab按键可以进行命令名或者文件名的补齐,具体操作是双击两下Tab键。
  • 其他答案:在命令行模式下[Tab]按键具有“命令补全”与“文件补齐”的功能。[Tab]接在一串命令的第一个命令的后面为“命令补全”,接在一串命令的第二个命令以后时则为“文件补齐”。

11、第十一题:

  • 我的回答:如果要强制结束一个正在运行的程序,可以通过组合键Ctrl + C。

12、第十二题:

  • 我的回答:通过命令(man -f passwd)可以知道有三个关于passwd的说明。可以通过info来代替man指令。
  • 其他回答:利用man -f passwd来查询。在Linux上可以用info passwd命令来替代man的在线查询passwd的功能。

13、第十三题:

  • 我的回答:man page中命令或文件后面的数字如果是数字1则代表的是一般用户可以打开的文件,如果是数字5说明是配置文件或者某文件格式,如果是数字8表示的是管理员使用的命令。
  • -其他回答:代表意义为:1)用户在shell环境中可以操作的命令或可执行文件;5)配置文件或者是某些文件的格式8);系统管理员能够使用的管理命令。

14、第十四题:

  • 我的回答:man page显示的内容通常存放在/usr/share/man目录中。

15、第十五题:

  • 我的回答:foo1是命令的名称,-foo2是命令的选项,foo3和foo4可能是foo2的参数。
  • 其他回答:foo1一定是指令, -foo2则是foo1这个指令的选择项目参数, foo3与foo4则不一定,可能是foo1的参数设定值,也可能是额外加入的parameters。

16、第十六题:

  • 我的回答:出现乱码的原因是字符集不匹配。可以通过设置LANG或者LC_ALL来进行修改输出的字符集。
  • 其他回答:乱码是由语系导致。可以在终端输入echo &LANG命令查看当前使用的语言,再输入LANG=en_CN.UTF-8修改语言(临时修改)即可。

17、第十七题:

  • 我的回答:说明当前目录下某有vbird这个目录或者文件。

18、第十八题:

  • 我的回答:命令行模式输入bz双击Tab键。

19、第十九题:

  • 我的回答:通过查询man page可以知道bzip2命令是进行文件压缩的命令。
  • 其他回答:使用man bzip2命令查看可以知道是用来压缩与解压缩文件用的。

20、第二十题:

  • 我的回答:$是一般用户模式,#是管理员模式。一般是 $模式。

21、第二十一题:

  • 我的回答:图形用户界面可以使用。reboot指令在默认情况下会调用systemctl这个重要的管理命令。
  • 其他回答:理论上reboot仅能让root运行。不过,如果dmtsai是在主机前面以图形接口登陆时,则dmtsai还是可以透过图形接口功能来关机。

5、Linux的文件权限与目录配置

5.2、Linux文件权限概念

5.2.2、如何修改文件属性与权限

1、关于如何创建新的用户以及将用户添加到某个用户组的操作

  • 可以通过命令(adduser 用户名)来创建一个新用户,比如下图,创建一个用户test4。
    在这里插入图片描述通过在root权限下执行命令(groups 用户名)可以知道一个用户所属的组有哪些,如下图所示,冒号左边的字符表示用户,右边的表示用户所属的用户组。刚创建的用户test4所属的用户组是test4。
    在这里插入图片描述如果要查看所有的组,可以在root权限之下通过命令(nano /etc/group)或者命令(cat /etc/group)来查看所有的用户组的基本信息,如下图所示。可以看到里面的内容他类似于X1 : X2 : X3 : X4,通过命令(man group)可知,X1表示用户组,X2表示加密过的组密码,X3表示组编号,X4表示属于这个组的成员有哪些。不过有一点儿很奇怪,新创建的test4本该属于test4组,但是下图中的test4组中的组成员并没有显示出来,但是使用命令(groups test4)却可以正常显示。
    没有截全图除了命令(adduser 用户名)之外还可以通过命令(useradd -d /home/用户名 用户名)的方式来进行用户的创建,用户文件是存放在家目录下,如下图所示。
    在这里插入图片描述但是通过命令(useradd -d /home/用户名 用户名)的方式来进行用户的创建和adduser一样,/etc/group文件中也不会显示test5用户组中有用户test5。如下图所示。
    在这里插入图片描述如果要修改某一个用户的登陆密码,可以在root权限下通过执行命令(passwd 用户名)即可更改某个用户的密码,如下图所示。
    在这里插入图片描述
    如果要将一个用户添加到一个用户组中可以通过命令(usermod -a -G 用户组名 用户名),效果如下图所示。
    在这里插入图片描述如果要创建一个新的用户组,可以通过命令(groupadd 用户组名)来进行创建。效果如下面两张图图所示。
    在这里插入图片描述
    在这里插入图片描述

5.5、本章练习

1、第一题:

  • 我的回答:如果是ASCII码,一个文件大约可以达到255个字符的长度。如果是占两个字符的汉字大约可以容纳128个汉字。
  • 其他解答:由于使用Ext2/Ext3文件系统,单一档名可达 255字符,完整文件名 (包含路径)可达 4096 个字符。

2、第二题:

  • 我的回答:用户可以读取修改该文件,且该文件可以被用户执行。用户组可以读取修改该文件,且该文件可以被用户组执行。其他组可以读取修改该文件,且该文件可以被其他组执行。

3、第三题:

  • 我的回答:可以通过命令(chmod 754 文件名)或者命令(chmod u=rwx,g=rx,o=r 文件名)来进行修改。

4、第四题:

  • 我的回答:可以通过命令(chgrp 用户组名 文件名)可以更改文件所属的用户组。还可以通过命令(chown 用户名:用户组名 文件名)同时修改文件所属的用户名和用户组名。

5、第五题:

  • 我的回答:/etc/目录下存放的是一些系统主要的配置文件。/boot存放一些启动会使用的文件包括Linux内核文件、启动选项、启动所需的配置文件等。/usr/bin存放单人维护模式下还能够被使用的命令。/bin是/usr/bin的链接文件。/usr/sbin存放一些非系统正常运行所需要的系统命令。/sbin是/usr/sbin的链接文件。/dev存放所有的设备文件和接口文件。/var/log是非常重要的日志文件。/run存放的是系统启动后所产生的各项信息。
  • 其他回答:/etc/:系统主要的配置文件几乎都放置在这个目录内,例如人员的账号密码文件、各种服务的起始文件等;/etc/init.d:所有服务的默认启动脚本都是放在这个目录中;/boot:主要放置在开机会使用到的文件,包括Linux内核文件以及开机菜单与开机所需配置文件等;/usr/bin:绝大部分的用户可使用命令都在这里,与/bin不同的是这些命令与开机过程无关;/bin:主要放置在开机时,以及进入单用户维护模式后还能够被操作的命令;/usr/sbin:非系统正常运行所需要的系统命令,最常见的就是某些网络服务器软件的服务命令;/sbin:主要放置开机过程中所需要的命令,里面包括了开机、修复、还原系统所需要的命令,只有系统管理员能使用;/dev:在Linux系统上,任何设备与接口设备都是以文件的形式存在与这个目录当中;/var/log:主要放置登录文件,记录登录信息。

6、第六题:

  • 我的回答:“.“开头的文件代表隐含文件。可以通过命令(ls -al)来显示隐含文件的文件名和相关的属性。

6、Linux文件与目录管理

6.1、目录与路径

6.1.3、关于执行文件路径的变量:$PATH

1、如何取出shell中的变量的值

  • 如果是通过echo命令显示到终端可以通过"$"符号来取出PATH中的值,具体的命令是:echo $PATH。
  • 如果是在双引号中进行字符串的拼接可以使用"${}"来取值,最后生成的字符串是” ${PATH}sdjflsdjfiosjdiofjsidf“。

6.2、文件与目录管理

6.2.2、复制、删除与移动:cp、rm、mv

1、关于软硬链接的说明

  • 软链接其实就是一种链接类型的文件,当打开一个链接类型的文件的时候,会根据链接文件的路径转移到所指向的文件。
  • 想要明白硬链接的原理首先就要知道每个文件有一个inode节点,这个inode节点记录了文件内容,权限等信息,所以打开一个文件实际上是打开这个文件指向的inode里面的内容,每个inode会有一个计数器,记录这个inode被多少文件使用,也就是所谓的硬链接个数,硬链接和软链接的区别就在于,软链接是通过记录某个文件的路径,然后对这个文件指向的inode进行操作,而硬链接文件则是直接指向某个文件指向的inode,此inode被链接的个数加一。

6.8、本章习题

1、第一题:

  • 我的回答:绝对路径是从根目录开始的完整路径,相对路径是从当前目录开始的路径。
  • 其他回答:对于Linux,绝对路径的写法为由 /开始写,相对路径则不由 /开始写。此外,相对路径为相对于目前工作目录的路径。

2、第二题:

  • 我的回答:可以通过mv指令的妙用进行更改,具体的命令为:mv /home/test /home/test2。
  • 其他回答:mv /home/test /home/test2 。

3、第三题:

  • 我的回答:在查询一个即将被执行的命令的时候,会查找PATH中的目录,如果在PATH中的目录中找到了对应的命令那么就会将这个命令执行,否则会提示没有这个命令。
  • 其他回答:这个是用来指定运行档运行的时候,命令搜寻的目录路径。

4、第四题:

  • 我的回答:umask可以用来设置一个新目录或者新文件被创建时的默认权限。
  • 其他回答:umask用来指定目前用户在新建文件或目录时候的权限默认值,因此它可以增减一些权限,因此,适当的定义 umask有助於系统的安全,因为他可以用来创建默认的目录或文件的权限。

5、第五题:

  • 我的回答:如果umask是033的话,那么创建一个新文件的权限是-rwxr–r--,创建一个目录的权限是drwxr–r--,如果umask是044,那么创建一个新文件的权限是-rwx-w–w-,创建一个新目录的权限是drwx-wx-wx。错误回答。
  • 其他回答:在 umask为 033时,则默认是拿掉 group与 other的 w(2)x(1)权限,因此权限就成为“文件 -rw-r–r–;目录 drwxr–r-- ”而当 umask 044时,则拿掉 r的属性,因此就成为“文件 -rw–w–w-,目录 drwx-wx-wx”。

6、第六题:

  • 我的回答:若s这个标志出现在所属用户身份的x栏上,且所属用户拥有x权限那么将这种情况的权限称作是SUID权限。
  • 其他回答:SUID是一种文件特殊权限,SUID有这样的限制于功能:SUID权限仅对二进制程序有效;执行者对于该程序需要具有x的可执行权限;本权限仅在执行改程序的过程中有效;执行者将具有该程序所有者的权限。

7、第七题:

  • 我的回答:可以通过ll /usr/bin/passwd来查询传统的权限和文件的类型,lsattr 命令可以查看文件的隐藏属性。

8、第八题:

  • 我的回答:可以通过命令find / -perm /4000 -exec ls -l {} ;。
  • 其他回答:find / -perm /4000 -print。

9、第九题:

  • 我的回答:find /etc/ -size +50k -size -60k -exec ls -l {} ;。
  • 其他回答:find /etc -size +50k -a -size -60k -exec ls -l {} ;。

10、第十题:

  • 我的回答:不会。
  • 其他回答:find /etc -size +50k -a ! -user root -exec ls -ld {} ;。

11、第十一题:

  • 我的回答:find /etc -size +1500k -exec ls -l {} ; ; find /etc/ -size -1c -exec ls -l {} ;。
  • 其他回答:find /etc -size +1500k -o -size 0。亲测是错误的。

7.1.7、挂载点的意义

1、关于为什么目录【/】、【/boot】和【/home】inode相同问题的说明。

  • 我的机器上这三个目录的inode结点如下图所示。
    在这里插入图片描述
    可以发现这三个目录的inode都是96,inode号码相同有以下两种情况。
  • 第一种:由于一个inode对应一个文件,如果一个文件系统中有两个文件指向同一个inode,那么这两个文件是一幕一样的文件且拥有相同的inode号码。
  • 第二种:如果两个分别属于不同的文件系统,那么两个不同的文件是可能拥有相同inode号码的。
  • 从以上两点看来这三个目录的inode号码相同,属于第二种情况,因为在安装centos的时候,这三个文件是分了三个不同的分区进行挂载的,分别属于三个不同的文件系统,我的机器上面inode号码96是顶层目录的inode号码,所以这三个目录都是挂载目录,也就是说这三个目录都是顶层目录,所以拥有相同的inode号码。

7.4.1、启动挂载/etc/fstab及/etc/mtab

1、如何设置启动挂载?

  • 当我们使用命令(mount)来对某个格式化的分区(创建了文件系统的分区)进行挂载,如果系统进行重起,我们会发现之前已经挂载的格式化分区并没有挂载目录。原因就在于我们没有在启动配置文件/etc/fstab中配置该格式化分区的一些信息,所以在系统启动的时候找不到该格式化分区的挂载信息,这才导致该分区明明之前已经被挂载但重起之后却是没有挂载的状态。
  • 为了解决这个问题需要对启动配置文件(/etc/fstab)进行信息修改。
    如下图所示。
    在这里插入图片描述
    对于输入的信息格式一定要正确,错误的格式会导致系统无法正确启动。正确的格式应该是:格式化分区的UUID 挂载目录 文件系统类型 文件系统参数 能否被dump命令作用(一般是0) 是否以fsck检验扇区(一般是0),中间用空格分割就行。
    最后通过命令(mount -a)将/etc/fstab文件中的挂载信息重新加载一边就可以看到各个格式化的分区已经被挂载完成了。如下图所示。
    在这里插入图片描述

这样子设置之后系统就会根据启动配置文件/etc/fstab中的信息将挂载信息写入到真正记录文件系统挂载的/etc/mtab和/etc/mounts这两个文件中。这样就算是重起也不会消失了。

7.8、本章习题

1、第一题

  • 我的回答:文件系统损坏了。
  • 其他回答:如果某个 filesystem里面,由于操作不当,可能会造成 Superblock数据的损毁,或者是 inode的架构损毁,或者是 block area的记录遗失等等,这些问题当中,其实硬盘还是好好的,不过,在硬盘上面的文件系统则已经无法再使用。一般来说,我们的 Linux很少会造成 filesystem的损毁,所以,发生问题时,很可能整个硬盘都损毁了。但是,如果您的主机常常不正常断电,那么,很可能硬盘是没问题的,但是,文件系统则有可能损毁。此时,重建文件系统 (reinstall)即可,不需要换掉硬盘。

2、第二题

  • 我的回答:不会被修改,因为file1和file2都是硬链接的形式,删除了file1,对file2的指向并没有什么影响,此时重新建立一个file1也会指向与file2不同的inode,所以不会对file2产生任何影响。
  • 其他回答:当我删除 file1之后, file2 则为一个正规文件,并不会与他人共同分享同一个 inode与 block ,因此,当我重新创建一个档名为 file1时,他所利用的 inode 与 block都是由我们的 filesystem 主动去搜寻 meta data,找到空的 inode 与 block来创建的, 与原本的 file1并没有任何关联性。所以,新建的 file1 并不会影响 file2。

9.6、本章习题

1、第一题

  • 我的回答:34G,15l。

2、第二题

  • 我的回答:gg,G。

3、第三题

  • 我的回答:0,$。

4、第四题

  • 我的回答:r是进入替换模式。

5、第五题

  • 我的回答:输入:w 文件名即可。

6、第六题

  • 我的回答:aior都可以进入编辑模式。

7、第七题

  • 我的回答:Esc。

8、第八题

  • 我的回答:hjkl可以用来移动光标。

9、第九题

  • 我的回答:dd,ndd(n为数字),x相当于是del,X相当于是Backspace。

10、第十题

  • 我的回答:yy,nyy(n为数字),p是在光标所在处的下一行进行粘贴,P是在上一行进行粘贴。

11、第十一题

  • 我的回答:/string。

12、第十二题

  • 我的回答::1,$s/word1/word2/gc。

13、第十三题

  • 我的回答::r 文件名。

14、第十四题

  • 我的回答:w,q,wq,wq!。

15、第十五题

  • 我的回答:q!。

16、第十六题

  • 我的回答::! ls -a。

10.2.3、环境变量的功能

1、关于环境变量和普通变量的区别

  • 变量可分为俩类:环境变量(全局变量),和普通变量(局部变量)。
  • 环境变量也称为全局变量,可以在创建他们的Shell及其派生出来的任意子进程Shell中使用,环境变量又可以分为自定义环境变量和bash内置的环境变量,环境变量可以在命令行中设置和创建,用户退出命令行时这些变量值就会丢失,想要永久保存环境变量,可在用户家目录下的. bash_profile或. bashrc(非用户登录模式特有,如:SSH)文件中,或在/etc/profile文件中定义,这样每次用户登录时这些变量都将被初始化。
  • 普通变量也可称为局部变量,只能在创建它们的Shell函数或Shell脚本中使用,普通变量一般由开发者在开发脚本程序时创建。

10.2.5、变量的有效范围

1、关于环境变量和自定义变量的补充说明

  • 首先要注意的点就是,环境变量和自定义变量这两个概念几乎是出现在父子进程对于变量的使用方面,父进程的自定义变量,子进程是无法引用的,如果父进程将自定义变量通过export命令变成环境变量之后就可以被子进程引用了。
  • 以上情况需要从原理进行说明,每启动一个shell,os会为其分配一块内存区域给这个shell使用,该shell如果自定义了变量,那么这个变量是不会被写入到os分配给这个shell的内存区域中的,只有将这个变量变成环境变量才可以被写入到分配的内存中。如果这个shell加载了另一个shell(即启动了子进程),子进程会将分配给父进程内存中的环境变量加载到子进程中的os分配给他的内存区域中。这也就是为什么子进程可以引用环境变量而不能引用父进程的自定义变量的原因。
  • 既然环境变量的概念是针对父子进程之间,那么不同的用户环境变量也不是互通的,因为两者构不成父子进程的关系,并且os会为两个用户都打开一个shell,分配不同的内存空间,两个用户创建的环境变量会放在不同的区域,所以不同的用户环境变量并不互通。
  • 如果要让不同的用户使用相同的环境变量,需要通过存放系统环境变量的配置文件进行相关的配置才能够让不同的用户之间的环境变量互通。

10.5.1、什么是数据重定向

1、数据重定向中关于‘1>&2’和’2>&1’的说明

  • 1>&2:表示将标准输出传递给2输出通道(即,标准错误输出),其中&2表示2输出通道(也就是标准错误输出)。如果此处错写成 1>2, 就表示把1输出重定向到文件2中。
  • 2>&1:表示将错误返回值传递给1输出通道,同样&1表示1输出通道。
  • 举例如下图。
    在这里插入图片描述

10.8、本章习题

1、情景模拟题,关于图形界面注销用户无法执行.bash_logout文件中命令的说明

  • shell登录时会调用login这个登录程序,注销时应该也会调用注销程序。shell会在调用注销程序时执行~/.bash_logout中的命令。而gnoma的登录和注销则是直接调用login和注销程序,不会调用.bash_logout文件中的内容,顾名思义,bash_logout应该指的是退出bash时执行的程序,在终端(ctrl + alt F2)中注销是可以执行该文件的。图形界面目前还没有什么好办法让.bash_logout文件执行。

2、第一题

  • 我的回答:linux中可以找到的shell有sh、bash、csh、tcsh等。记录shells的文件是/etc/shells。linux默认的shells是bash。

3、第二题

  • 我的回答:可以通过快捷键ctrl + u。

4、第三题

  • 我的回答:可以修改。修改变量PS1的值即可。默认的内容是([\u@\h \W]$)。
  • 其他回答:命令提示符可以通过环境变量PS1来修改,改环境变量的内容即可,默认的提示符内容是[\u@\h\W]$。

5、第四题

  • 我的回答:echo $HOME或者echo ${HOME}。

6、第五题

  • 我的回答:set命令显示目前用户的所有变量的值。env只显示环境变量。

7、第六题

  • 我的回答:不能。变量名开头不能是数字。

8、第七题

  • 我的回答:是B。

9、第八题

  • 我的回答:通过命令unset可以取消变量的值。通过命令unalias可以取消命令别名。

10、第九题

  • 我的回答:直接命令行输入:name=‘It’s my name?’。

11、第十题

  • 我的回答:一个是login shell的读取,读取的文件有/etc/profile,~/.bash_profile。另一个是non-login shell读取,读取的文件有~/.bashrc。

12、第十一题

  • 我的回答:man page的路径配置文件是/etc/man_db.conf。

13、第十二题

  • 我的回答:单引号内的字符都是一般字符,双引号内保留了特殊字符,飘号内部为可以先执行的命令。

14、第十三题

  • 我的回答:将特殊字符或通配符变成一般字符(比如空格、换行、$)。

15、第十四题

  • 我的回答:";"用来连接两个不相关的命令。&&用来连接两个相关的命令,如果第一个命令出错,第二个命令不执行,只有第一个命令执行成功才能执行第二个命令。||用来连接两个相关的命令,如果第一个命令执行失败才会执行第二个命令,第一个命令执行成功就不会再执行第二个命令了。

16、第十五题

  • 我的回答:last | cut -d ’ ’ -f 1。
  • 其他回答:last | cut -d ’ ’ -f1 | sort | uniq。

17、第十六题

  • 我的回答:foo1、foo2、foo3是命令,foo4是文件。意思就是如果foo1命令执行成功,就将foo2命令执行的结果写入foo4文件中,foo1执行失败了,就将foo3执行的结果写入foo4文件中。
  • 其他回答:foo1、foo2、foo3都是命令,foo4是文件。整串命令的意义是当foo1正确执行时则执行foo2,否则不执行,然后foo2若没有正确执行则执行foo3,并将结果作为stdin输出到foo4中。

18、第十七题

  • 我的回答:不知道咋做。
  • 其他回答:ls -l /bin/a*。

19、第十八题

  • 我的回答:不知道咋做。
  • 其他回答:ll /bin ???。

20、第十九题

  • 我的回答: ll /bin [^a-d]*。

21、第二十题

  • 我的回答:忘记了。
  • 其他回答:/etc/issue。

22、第二十一题

  • 我的回答:忘记了。
  • 其他回答:/etc/motd。

11.6、本章习题

1、第一题

  • 我的回答:grep ‘[XYZ]’ $(find /etc 2> /dev/null) 2> /dev/null。
  • 其他回答:grep [XYZ] /etc/*。我觉得这样不对,只能找/etc的第一层目录,不能往第二层目录之后找。

2、第二题

  • 我的回答:cat /etc/kdump.conf | egrep -v ‘^#|^$’ | grep ‘^[[:alpha:]]’ | awk ‘{print "column: " NR}’。
  • 其他回答:cat /etc/kdump.conf | egrep -v ‘^#|^$’ | grep ‘^[[:alpha:]]’ | wc -l。

12.2、简单的shell脚本练习

1、交互式脚本,变量内容由用户决定

  • 我的写法。

    #!/bin/bash                                                                                                                                  
    # Program:
    #       User inputs his first name and last name. Program shows his full name.
    # History:
    # 2020/08/08        VBird       First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    read -p 'Please input your first name: ' firstname
    read -p 'Please input your last name: ' lastname
    echo -e "\nYour full name is ${firstname} ${lastname}"
    exit 0
    
    
    [948cshell@localhost bin]$ sh showname.sh 
    Please input your first name: Tao
    Please input your last name: Xincan
    
    Your full name is Tao Xincan
    
    

2、随日期变化,利用date创建文件

  • 我的写法
    #!/bin/bash                                                                                                                                           
    # Program:
    #       Program create three files, which named by user's input and date command.
    # History:
    # 2020/08/08        VBird       First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    read -p 'What is your filename: ' filename
    touch "${filename}_$(date +%F | sed 's/-//g')"
    touch "${filename}_$(date -d "-1 day" +%F | sed 's/-//g')"
    touch "${filename}_$(date -d "-2 day" +%F | sed 's/-//g')"
    exit 0
    
    
    [948cshell@localhost bin]$ sh my_create_3_filename.sh 
    What is your filename: testfile
    [948cshell@localhost bin]$ ll
    总用量 16
    -rw-rw-r--. 1 948cshell 948cshell 1121 8月   9 16:04 create_3_filename.sh
    -rwxrw-r--. 1 948cshell 948cshell  208 8月   9 15:58 hello.sh
    -rw-rw-r--. 1 948cshell 948cshell  461 8月   9 16:04 my_create_3_filename.sh
    -rwxrw-r--. 1 948cshell 948cshell  405 8月   9 16:02 showname.sh
    -rw-rw-r--. 1 948cshell 948cshell    0 8月   9 16:04 testfile_20200807
    -rw-rw-r--. 1 948cshell 948cshell    0 8月   9 16:04 testfile_20200808
    -rw-rw-r--. 1 948cshell 948cshell    0 8月   9 16:04 testfile_20200809
    
  • 鸟哥给的写法。
    #!/bin/bash                                                                                                                                           
    # Program:
    #       Program create three files, which named by user's input and date command.
    # History:
    # 2020/08/09    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
     
    # 1、让使用者输入文件名称,并取得fileuser这个变量
    echo -e "I will use 'touch' command to create 3 files." # 纯粹的显示信息
    read -p "Please input your filename: " fileuser # 提示使用者输入
     
    # 2、为了避免使用者随意按Enter,利用变量功能分析文件名是否有设置?
    # 开始判断是否有配置文件名,该语句的意思是如果fileuser为空白就将
    # filename这个字符串赋值给filename变量。
    filename=${fileuser:-"filename"}
     
    # 3、开始利用date命令来取得所需要的文件名
    date1=$(date --date='2 days ago' +%Y%m%d) # 前两天的日期
    date2=$(date --date='1 days ago' +%Y%m%d) # 前一天的日期
    date3=$(date +%Y%m%d) # 今天的日期
    file1=${filename}${date1}
    file2=${filename}${date2}
    file3=${filename}${date3}
     
    #3、将文件名建立起来
    touch "${file1}"
    touch "${file2}"
    touch "${file3}"
    
    
    当输入空白文件名的情况如下。
    [948cshell@localhost bin]$ sh create_3_filename.sh 
    I will use 'touch' command to create 3 files.
    Please input your filename: 
    [948cshell@localhost bin]$ ll
    总用量 16
    -rw-rw-r--. 1 948cshell 948cshell 1121 8月   9 16:04 create_3_filename.sh
    -rw-rw-r--. 1 948cshell 948cshell    0 8月   9 16:07 filename20200807
    -rw-rw-r--. 1 948cshell 948cshell    0 8月   9 16:07 filename20200808
    -rw-rw-r--. 1 948cshell 948cshell    0 8月   9 16:07 filename20200809
    -rwxrw-r--. 1 948cshell 948cshell  208 8月   9 15:58 hello.sh
    -rw-rw-r--. 1 948cshell 948cshell  461 8月   9 16:04 my_create_3_filename.sh
    -rwxrw-r--. 1 948cshell 948cshell  405 8月   9 16:02 showname.sh
    
    当输入非空白文件名的情况如下。
    [948cshell@localhost bin]$ sh create_3_filename.sh 
    I will use 'touch' command to create 3 files.
    Please input your filename: testfile
    [948cshell@localhost bin]$ ll
    总用量 16
    -rw-rw-r--. 1 948cshell 948cshell 1121 8月   9 16:08 create_3_filename.sh
    -rwxrw-r--. 1 948cshell 948cshell  208 8月   9 15:58 hello.sh
    -rw-rw-r--. 1 948cshell 948cshell  461 8月   9 16:04 my_create_3_filename.sh
    -rwxrw-r--. 1 948cshell 948cshell  405 8月   9 16:02 showname.sh
    -rw-rw-r--. 1 948cshell 948cshell    0 8月   9 16:09 testfile20200807
    -rw-rw-r--. 1 948cshell 948cshell    0 8月   9 16:09 testfile20200808
    -rw-rw-r--. 1 948cshell 948cshell    0 8月   9 16:09 testfile20200809
    

3、数值运算,简单的加减乘除

  • 我的写法:
    !/bin/bash                                                                                                                                           
    # Program:
    #       User inputs 2 integer numbers ; program will cross these two numbers.
    # History:
    # 2020/08/08    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    echo -e "You should input 2 numbers, I will multiplying them! \n"
    declare -i firstnum
    declare -i secondnum
    read -p "Please input the first number: " firstnum
    read -p "Please input the second number: " secondnum
    declare -i sum=${firstnum}*${secondnum}
    echo $sum
    exit 0
    
    
    [948cshell@localhost bin]$ sh my_multiplying.sh 
    You should input 2 numbers, I will multiplying them! 
    
    Please input the first number: 2
    Please input the second number: 3
    6
    
  • 鸟哥的写法:
    #!/bin/bash                                                                                                                                           
    # Program:
    #       User inputs 2 integer numbers ; program will cross these two numbers.
    # History:
    # 202/0/08/09    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    echo -e "You SHOULD input 2 numbers, I will multiply them! \n"
    read -p "first number: " firstnu
    read -p "second number: " secnu
    # 可以通过【result=$((计算式))】计算整数运算的值,并把结果赋值给result变量。
    # 以下代码也可以写成【declare -i total=${firstnu}*${secnu}】,只是这种写法中
    # 表达式之间不能使用空格,第一种表达式之间是可以使用空格的。
    total=$((${firstnu}*${secnu}))
    echo -e "\n The result of ${firstnu} x ${secnu} is ==> ${total}"
    exit 0
    
    
    [948cshell@localhost bin]$ sh multiplying.sh 
    You SHOULD input 2 numbers, I will multiply them! 
    
    first number: 2
    second number: 3
    
    The result of 2 x 3 is ==> 6
    

4、数值运算,通过bc计算Pi

  • 鸟哥的写法:
    #!/bin/bash                                                                                                                                           
    # Program:
    #       User input a scale number to calculate pi number
    # History:
    # 2020/08/10    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    echo -e "This program will calculate pi value. \n"
    echo -e "You should input a float number to calculate pi value. \n"
    read -p "The scale number (10~10000) ? " checking
    # 如果checking输入的是空白,就将10赋值给num变量
    num=${checking:-"10"}
    echo -e "Starting calculate pi value. Be patient."
    # time命令后面跟命令,用来计算后面所跟的命令执行所花的时间。
    # echo命令经常和bc命令通过管道来进行配合,bc命令会将echo
    # 命令的引号中的语句按照分号进行分割,依次执行。bc命令中的-l
    # 选项是调用标准函数库的意思,4*a(1)是其中的一个函数,会返回
    # pi的值。
    time echo "scale=${num} ; 4*a(1)" | bc -lq 
    exit 0
    
    
    [948cshell@localhost bin]$ sh cal_pi.sh 
    This program will calculate pi value. 
    
    You should input a float number to calculate pi value. 
    
    The scale number (10~10000) ? 
    Starting calculate pi value. Be patient.
    3.1415926532
    
    real	0m0.005s
    user	0m0.003s
    sys	0m0.003s
    

12.2.2、脚本执行方法的差异,即source、sh script、./script的差异

1、关于使用source命令运行shell脚本的时候,脚本最后【exit 0】语句的说明。

  • 如果使用source命令运行shell脚本的时候,由于是在父进程的bash中运行,如果脚本最后含有语句【exit 0】,在执行完毕后会直接退出命令行模式。所以在用source执行脚本的时候最好别加上语句【exit 0】。
  • 如果是使用除了source命令以外的方式执行脚本,由于会在子进程的 bash中执行,所以就算有exit 0也不会直接退出父进程,故脚本中可以写入语句【exit 0】。

12.3.1、利用test命令的测试功能

1、关于test命令的脚本范例

  • 我的写法:
    #!/bin/bash                                                                                                                                           
    # Program:
    #       User input a filename, program will check the following:
    #       1、exist?
    #       2、file / directory
    #       3、file permission
    # History:
    # 2020/08/10    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    read -p "Please input a filename: " filename
    # 下面的语句本来是想判断文件存在则继续执行下面的语句,不存在则退出,可是由于
    # 没有学习脚本中的if语句,所以不太会写。于是就写了下面这个错误的版本。
    test -e "${filename}" && echo "exist" || echo "Not exist" && exit 0
    test -f "${filename}" && echo "This is a file" || echo "This is a directory"
    test -r "${filename}" && perm="${perm} readable"
    test -w "${filename}" && perm="${perm} writable"
    test -x "${filename}" && perm="${perm} executable"
    echo "User's permission are $perm"
    
  • 鸟哥的写法:
    #!/bin/bash                                                                                                                                           
    # Program:
    #       User input a filename, program will check the following:
    #       1、exist?
    #       2、file / directory
    #       3、file permission
    # History:
    # 2020/08/10    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    # 1、让输入者输入文件名,并且判断使用者是否真的有输入字符
    echo -e "Please input a filename, I will check the filename's type and permission. \n\n"
    read -p "Input a filename: " filename
    test -z ${filename} && echo "You MUST input a filename." && exit 0
     
    # 2、判断文件是否存在?若不存在则显示信息并结束脚本
    test ! -e ${filename} && echo "The filename '${filename}' DO NOT exist" && exit 0
     
    # 3、开始判断文件类型与属性
    test -f ${filename} && filetype="regular file"
    test -d ${filename} && filetype="directory"
    test -r ${filename} && perm="readable"
    test -f ${filename} && perm="${perm} writable"
    test -f ${filename} && filetype="${perm} executable"
    # 4、开始输出信息
    echo "The filename: ${filename} is a ${filetype}"
    echo "And the permissions for you are : ${perm}"
    

12.3.2、利用判断符号[]

1、关于中括号作为判断符号的范例。

  • 我的写法
    #!/bin/bash                                                                                                                                           
    # Program:
    #       This program shows the user's choice
    # History:
    # 2020/08/10    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    read -p "Please input your choice : " choice
    [ "${choice}" == "Y" -o "${choice}" == "y" ] && echo "OK, continue"
    [ "${choice}" == "N" -o "${choice}" == "n" ] && echo "Oh, interrupt"
    [ "${choice}" != "Y" -a "${choice}" != "y" -a "${choice}" != "N" -a "${choice}" != "n" ] && echo "I don't know what your choice is"
    
    
    [948cshell@localhost bin]$ sh ans_yn.sh 
    Please input your choice : y
    OK, continue
    [948cshell@localhost bin]$ sh ans_yn.sh 
    Please input your choice : Y
    OK, continue
    [948cshell@localhost bin]$ sh ans_yn.sh 
    Please input your choice : n
    Oh, interrupt
    [948cshell@localhost bin]$ sh ans_yn.sh 
    Please input your choice : N
    Oh, interrupt
    [948cshell@localhost bin]$ sh ans_yn.sh 
    Please input your choice : d
    I don't know what your choice is
    
  • 鸟哥的写法:
    #!/bin/bash                                                                                                                                           
    # Program:
    #       This program shows the user's choice
    # History:
    # 2020/08/10    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    read -p "Please input (Y/N) :" yn
    [ "${yn}" == "Y" -o "${yn}" == "y" ] && echo "OK, continue" && exit 0
    [ "${yn}" == "N" -o "${yn}" == "n" ] && echo "Oh, interrupt" && exit 0
    echo "I don't know what your choice is" && exit 0
    
    
    [948cshell@localhost bin]$ sh ans_yn.sh 
    Please input (Y/N) :y
    OK, continue
    [948cshell@localhost bin]$ sh ans_yn.sh 
    Please input (Y/N) :Y
    OK, continue
    [948cshell@localhost bin]$ sh ans_yn.sh 
    Please input (Y/N) :n
    Oh, interrupt
    [948cshell@localhost bin]$ sh ans_yn.sh 
    Please input (Y/N) :N
    Oh, interrupt
    [948cshell@localhost bin]$ sh ans_yn.sh 
    Please input (Y/N) :d
    I don't know what your choice is
    
  • 使用单层、简单条件判断式进行改写:
    #!/bin/bash                                                                                                                                           
    # Program:
    #       This program shows the user's choice
    # History:
    # 2020/08/10    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    read -p "Please input (Y/N) :" yn
    if [ "${yn}" == "Y" ] || [ "${yn}" == "y" ]; then
        echo "OK, continue"
        exit 0
    fi
     
    if [ "${yn}" == "N" ] || [ "${yn}" == "n" ]; then
        echo "Oh, interrupt"
        exit 0
    fi
    echo "I don't know what your choice is" && exit 0
    
  • 使用多重复杂判断式进行改写:
    #!/bin/bash                                                                                                                                           
    # Program:
    #       This program shows the user's choice
    # History:
    # 2020/08/10    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    read -p "Please input (Y/N) :" yn
    if [ "${yn}" == "Y" ] || [ "${yn}" == "y" ]; then
        echo "OK, continue"
        exit 0
    elif [ "${yn}" == "N" ] || [ "${yn}" == "n" ]; then
        echo "Oh, interrupt"
        exit 0
    else
        echo "I don't know what your choice is" && exit 0
    fi
    

12.3.3、shell脚本的默认变量,即$1、$2……

1、关于脚本中的默认变量的使用范例。

  • 我的写法:
    #!/bin/bash                                                                     
    # Program:
    #       Program shows the script name, parameters...
    # History:
    # 2020/08/11    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    echo "程序的文件名是:${0}"
    echo "程序中共有几个参数:${#}"
    [ "${#}" -lt "2" ] && echo "The number of parameter is less than 2. Stop here. " && exit 0
    echo "传入的参数有:${*}"
    echo "第一个参数是:${1}"
    echo "第二个参数是:${2}"
    
    
    [948cshell@localhost ~]$ sh my_how_paras.sh a b c
    程序的文件名是:my_how_paras.sh
    程序中共有几个参数:3
    传入的参数有:a b c
    第一个参数是:a
    第二个参数是:b
    [948cshell@localhost ~]$ sh my_how_paras.sh 
    程序的文件名是:my_how_paras.sh
    程序中共有几个参数:0
    The number of parameter is less than 2. Stop here. 
    
  • 鸟哥的写法:
    #!/bin/bash                                                                                                                                           
    # Program:
    #       Program shows the script name, parameters...
    # History:
    # 2020/08/11    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    echo "The script name is    ==> ${0}"
    echo "Total parameter number is ==> $#"
    [ "$#" -lt 2 ] && echo "The number of parameter is less than 2. Stop here." && exit 0
    echo "Your whole parameter is  ==> '$@'"
    echo "The 1st parameter     ==> ${1}"
    echo "The 2nd parameter     ==> ${2}"
    
    
    [948cshell@localhost bin]$ sh how_paras.sh a b c
    The script name is    ==> how_paras.sh
    Total parameter number is ==> 3
    Your whole parameter is  ==> 'a b c'
    The 1st parameter     ==> a
    The 2nd parameter     ==> b
    [948cshell@localhost bin]$ sh how_paras.sh a 
    The script name is    ==> how_paras.sh
    Total parameter number is ==> 1
    The number of parameter is less than 2. Stop here.
    

2、关于shift向右偏移变量号码的范例说明

  • 鸟哥的范例
    #!/bin/bash                                                                                                                                           
    # Program:
    #       Program shows the effect of shift function.
    # History:
    # 2020/08/10    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    echo "Total parameter number is     ==> $#"
    echo "Your whole parameter is       ==> '$@'"
    # 进行一次参数的向左偏移
    shift
    echo "Total parameter number is     ==> $#"
    echo "Your whole parameter is       ==> '$@'"
    # 进行三次参数的向左偏移
    shift 3
    echo "Total parameter number is     ==> $#"
    echo "Your whole parameter is       ==> '$@'"
    
    
    [948cshell@localhost bin]$ sh shift_paras.sh one two three four five six
    Total parameter number is     ==> 6
    Your whole parameter is       ==> 'one two three four five six'
    Total parameter number is     ==> 5
    Your whole parameter is       ==> 'two three four five six'
    Total parameter number is     ==> 2
    Your whole parameter is       ==> 'five six'
    

12.4.1、利用if…then

1、多重、复杂条件判断式的范例。

  • 我的写法:
    #!/bin/bash                                                                                                                                           
    # Program:
    #       This program shows the user's choice
    # History:
    # 2020/08/10    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    if [ "${1}" == "hello" ]; then
        echo "Hello, how are you?"
    elif [ -z "${1}" ]; then
        echo "必须输入参数"
    else
        echo "请输入正确的参数hello"
    fi
    
    
    [948cshell@localhost bin]$ sh my_hello-2.sh 
    必须输入参数
    [948cshell@localhost bin]$ sh my_hello-2.sh l
    请输入正确的参数hello
    [948cshell@localhost bin]$ sh my_hello-2.sh hello
    Hello, how are you?
    
  • 鸟哥的写法:
    #!/bin/bash                                                                                                                                           
    # Program:
    #       This program shows the user's choice
    # History:
    # 2020/08/10    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    if [ "${1}" == "hello" ]; then
        echo "Hello, how are you ?"
    elif [ "${1}" == "" ]; then
        echo "You MUST input parameters, ex> {${0} someword }"
    else
        echo "The only parameters is 'hello', ex> {${0} hello}"
    fi
    
    
    [948cshell@localhost bin]$ sh hello-2.sh 
    You MUST input parameters, ex> {hello-2.sh someword }
    [948cshell@localhost bin]$ sh hello-2.sh d
    The only parameters is 'hello', ex> {hello-2.sh hello}
    [948cshell@localhost bin]$ sh hello-2.sh hello
    Hello, how are you ?
    
  • 使用case…esac改写:
    #!/bin/bash
    # Program:
    #       This program shows the user's choice
    # History:
    # 2020/08/10    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    case ${1} in
        "hello")
            echo "Hello, how are you ?"
            ;;
        "")
            echo "You MUST input parameters, ex> {${0} someword}"
            ;;
        *) # 其实相当于通配符,0~无穷多个任意字符之意。
            echo "Usage ${0} {hello}"
            ;;
    esac
    
    
    [948cshell@localhost bin]$ sh case_hello-2.sh 
    You MUST input parameters, ex> {case_hello-2.sh someword}
    [948cshell@localhost bin]$ sh case_hello-2.sh sdf
    Usage case_hello-2.sh {hello}
    [948cshell@localhost bin]$ sh case_hello-2.sh hello
    Hello, how are you ?
    

2、多重、复杂条件判断式的较复杂的范例。

  • 我的写法:
    #!/bin/bash                                                                                                                                           
    # Program:
    #       You input your demobilization date, I calculate how many days before you demobilize.
    # History:
    # 2020/08/10    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    read -p "请输入您的退伍日期(YYYYMMDD):" retired
    # 目前的时间,用秒数来表示。
    current_date="$(date +%s)"
    # 退役的时间,用秒钟表示。
    retired_date="$(date --date="${retired}" +%s)"
    # 判断是否退役。
    if [ "${current_date}" -ge "${retired_date}" ]; then
        echo "您已经可以退役了。"
    else
        interval=$((${retired_date}-${current_date}))
        echo "距离您退役还有$((${interval}/86400))天。"
    fi
    
    
    [948cshell@localhost bin]$ sh my_cal_retired.sh 
    请输入您的退伍日期(YYYYMMDD):20200101
    您已经可以退役了。
    [948cshell@localhost bin]$ sh my_cal_retired.sh 
    请输入您的退伍日期(YYYYMMDD):20201212
    距离您退役还有122天。
    
  • 鸟哥的写法:
#!/bin/bash                                                                                                                                                                              
# Program:
#       You input your demobilization date, I calculate how many days before you demobilize.
# History:
# 2020/08/10    VBird   First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# 1、告知使用者这个程序的用途,并且告知应该如何输入日期格式
echo "This program will try to calculate: "
echo "How many days before your demobilization date ..."
read -p "Please input your demobilization date (YYYYMMDD ex>20200812): " date2
#2、测试一下,这个输入的内容是否正确?利用正则表达式
date_d=$(echo ${date2} | grep '[0-9]\{8\}')
if [ "${date_d}" == "" ]; then
    echo "You input the wrong date format..."
    exit 1
fi
#3、开始计算日期
# 退伍日期秒书
declare -i date_dem=$(date --date="${date2}" +%s)
# 现在日期秒数
declare -i date_now=$(date +%s)
# 剩余秒数统计
declare -i date_total_s=$((${date_dem}-${date_now}))
# 转为日数
declare -i date_d=$((${date_total_s}/60/60/24))
# 判断是否退伍
if [ "${date_d}" -lt "0" ]; then
    echo "You had been demobilization before : $((-1*${date_d})) days ago."
else
    declare -i date_h=$(($((${date_total_s}-${date_d}*60*60*24))/60/60))
    echo "You will demobilize after ${date_d} days and ${date_h} hours."
fi


[948cshell@localhost bin]$ sh cal_retired.sh 
This program will try to calculate: 
How many days before your demobilization date ...
Please input your demobilization date (YYYYMMDD ex>20200812): 20201212
You will demobilize after 121 days and 12 hours.
[948cshell@localhost bin]$ sh cal_retired.sh 
This program will try to calculate: 
How many days before your demobilization date ...
Please input your demobilization date (YYYYMMDD ex>20200812): 2020-12-12
You input the wrong date format...
[948cshell@localhost bin]$ sh cal_retired.sh 
This program will try to calculate: 
How many days before your demobilization date ...
Please input your demobilization date (YYYYMMDD ex>20200812): 20200101
You had been demobilization before : 224 days ago.

以上代码中的正则表达式做输入数据的容错需要学习。

12.4.2、利用case…esac判断

1、case…esac语句的范例。

  • 鸟哥的写法:
    #!/bin/bash                                                                                                                                                                              
    # Program:
    #       This script only accepts the flowing parameter: one, two or three.
    # History:
    # 2020/08/08    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    echo "This program will print your selection !"
    # read -p "Input your choice: " choice $ 暂时取消,可以替换
    # case ${choice} in # 暂时取消,可以替换
    case ${1} in
        "one")
            echo "Your choice is ONE"
            ;;
        "two")
            echo "Your choice is TWO"
            ;;
        "three")
            echo "Your choice is THREE"
            ;;
        *)  
            echo "Usage ${0} {one|two|three}"
            ;;
    esac
    
    
    [948cshell@localhost bin]$ sh show123.sh 
    This program will print your selection !
    Usage show123.sh {one|two|three}
    [948cshell@localhost bin]$ sh show123.sh one
    This program will print your selection !
    Your choice is ONE
    [948cshell@localhost bin]$ sh show123.sh two
    This program will print your selection !
    Your choice is TWO
    [948cshell@localhost bin]$ sh show123.sh three
    This program will print your selection !
    Your choice is THREE
    [948cshell@localhost bin]$ sh show123.sh four
    This program will print your selection !
    Usage show123.sh {one|two|three}
    
    #!/bin/bash
    # Program:
    #       This script only accepts the flowing parameter: one, two or three.
    # History:
    # 2020/08/08    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    echo "This program will print your selection !"
    read -p "Input your choice: " choice
    case ${choice} in
    # case ${1} in # 暂时取消
        "one")
            echo "Your choice is ONE"
            ;;
        "two")
            echo "Your choice is TWO"
            ;;
        "three")
            echo "Your choice is THREE"
            ;;
        *)
            echo "Usage ${0} {one|two|three}"
            ;;
    esac
    
    
    [948cshell@localhost bin]$ sh show123.sh 
    This program will print your selection !
    Input your choice: one
    Your choice is ONE
    [948cshell@localhost bin]$ sh show123.sh 
    This program will print your selection !
    Input your choice: 
    Usage show123.sh {one|two|three}
    [948cshell@localhost bin]$ sh show123.sh 
    This program will print your selection !
    Input your choice: two
    Your choice is TWO
    [948cshell@localhost bin]$ sh show123.sh 
    This program will print your selection !
    Input your choice: three
    Your choice is THREE
    

12.4.3、利用function功能

1、关于脚本中函数的范例

  • 使用函数改写上面的脚本
    #!/bin/bash
    # Program:
    #       Use function to repeat information.
    # History:
    # 2020/08/12    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    function printit() {
        # echo命令加上-n选项可以不换行,让接下来的命令的输出在同一行进行显示
        echo -n "Your choice is "
    }
    
    echo "This program will print your selection !"
    case ${1} in
        "one")
            printit ; echo ${1} | tr [a-z] [A-Z]
            ;;
        "two")
            printit; echo ${1} | tr [a-z] [A-Z]
            ;;
        "three")
            printit; echo ${1} | tr [a-z] [A-Z]
            ;;
        *)
            echo "Usage ${0} {one|two|three}"
            ;;
    esac
    
    
    
    [948cshell@localhost bin]$ sh show123-2.sh 
    This program will print your selection !
    Usage show123-2.sh {one|two|three}
    [948cshell@localhost bin]$ sh show123-2.sh ONE
    This program will print your selection !
    Usage show123-2.sh {one|two|three}
    [948cshell@localhost bin]$ sh show123-2.sh one
    This program will print your selection !
    Your choice is ONE
    [948cshell@localhost bin]$ sh show123-2.sh two
    This program will print your selection !
    Your choice is TWO
    

2、关于函数中的$0、$1…变量的使用范例。

  • 鸟哥的写法
#!/bin/bash
# Program:
#       Use function to repeat information.
# History:
# 2020/08/12    VBird   First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
function printit() {
    echo "Your choice is ${1}"
}

echo "This program will print your selection !"
case ${1} in
    "one")
        printit 1
        ;;
    "two")
        printit 2
        ;;
    "three")
        printit 3
        ;;
    *)
        echo "Usage ${0} {one|two|three}"
        ;;
esac


[948cshell@localhost bin]$ sh show123-3.sh 
This program will print your selection !
Usage show123-3.sh {one|two|three}
[948cshell@localhost bin]$ sh show123-3.sh one
This program will print your selection !
Your choice is 1
[948cshell@localhost bin]$ sh show123-3.sh two
This program will print your selection !
Your choice is 2
[948cshell@localhost bin]$ sh show123-3.sh three
This program will print your selection !
Your choice is 3

上面代码中函数printit中的${1}和主函数中调用printit函数后面跟的第一个参数有关,${2}和主函数中调用printit函数后面跟的第二个参数有关,以此类推。函数中的${0}和函数名有关。

12.5.1、while do down、until do done,即不定循环

1、while不定循环与until不定循环的使用范例。

  • 我的while写法
    #!/bin/bash
    # Program:
    #       Repeat question until user input corrent answer.
    # History:
    # 2020/08/12    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    read -p "Please input yes/YES to stop this program: " flag
    while [ "${flag}" != "yes" -a "${flag}" != "YES" ]
    do
        read -p "Please input yes/YES to stop this program: " flag
    done
    
    
    
    [948cshell@localhost bin]$ sh my_yes_to_stop.sh 
    Please input yes/YES to stop this program: Yes
    Please input yes/YES to stop this program: yes
    [948cshell@localhost bin]$ sh my_yes_to_stop.sh 
    Please input yes/YES to stop this program: YEs
    Please input yes/YES to stop this program: YES
    
  • 鸟哥的while写法。
    #!/bin/bash
    # Program:
    #       Repeat question until user input corrent answer.
    # History:
    # 2020/08/12    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    while [ "${yn}" != "yes" -a "${yn}" != "YES" ]
    do
        read -p "Please input yes/YES to stop this program: " yn
    done
    echo "OK! you input the correct answer."
    
    
    
    [948cshell@localhost bin]$ sh yes_to_stop.sh 
    Please input yes/YES to stop this program: NO
    Please input yes/YES to stop this program: no
    Please input yes/YES to stop this program: Yes
    Please input yes/YES to stop this program: YES
    OK! you input the correct answer.
    [948cshell@localhost bin]$ sh yes_to_stop.sh 
    Please input yes/YES to stop this program: yes
    OK! you input the correct answer.
    
  • 我的until写法。
    #!/bin/bash
    # Program:
    #       Repeat question until user input corrent answer.
    # History:
    # 2020/08/12    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    until [ "${yn}" == "yes" -o "${yn}" == "YES" ]
    do
        read -p "Please input yes/YES to stop this program: " yn
    done
    
    
    [948cshell@localhost bin]$ sh my_yes_to_stop-2.sh 
    Please input yes/YES to stop this program: no
    Please input yes/YES to stop this program: yes
    [948cshell@localhost bin]$ sh my_yes_to_stop-2.sh 
    Please input yes/YES to stop this program: NO
    Please input yes/YES to stop this program: YES
    
  • 鸟哥的until写法。
    #!/bin/bash
    # Program:
    #       Repeat question until user input corrent answer.
    # History:
    # 2020/08/12    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    until [ "${yn}" == "yes" -o "${yn}" == "YES" ]
    do
        read -p "Please input yes/YES to stop this program: " yn
    done
    echo "OK! you input the correct answer."
    
    
    [948cshell@localhost bin]$ sh yes_to_stop-2.sh 
    Please input yes/YES to stop this program: NO
    Please input yes/YES to stop this program: YES
    OK! you input the correct answer.
    [948cshell@localhost bin]$ sh yes_to_stop-2.sh 
    Please input yes/YES to stop this program: no
    Please input yes/YES to stop this program: yes
    OK! you input the correct answer.
    

12.5.2、for…do…done,即固定循环

1、for…do…done循环的使用范例。

  • 简单的遍历用空格分割的几个字符串
    #!/bin/bash
    # Program:
    #       Using for ... loop to print 3 animals
    # History:
    # 2020/08/12    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    # for循环中的in后面跟的条件可以用空格进行分割,变量animal会依次取各个条件的值。
    for animal in dog cat elephant
    do
        echo "There are ${animal}s..."
    done
    
    
    [948cshell@localhost bin]$ sh show_animal.sh 
    There are dogs...
    There are cats...
    There are elephants...
    
  • 利用cut识别/etc/passwd中的帐号名称并使用id命令来检查用户的标示符
    #!/bin/bash
    # Program:
    #       Usr id, finger command to check system account's information.
    # History:
    # 2020/08/12    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    users=$(cut -d ':' -f1 /etc/passwd)
    # for循环中的in后面跟的条件可以放到一个用换行分割的变量中,username变量会依次等于每一行的值
    for username in ${users}
    do
        id ${username}
    done
    
    
    [948cshell@localhost bin]$ sh userid.sh 
    uid=0(root) gid=0(root)=0(root)
    uid=1(bin) gid=1(bin)=1(bin)
    uid=2(daemon) gid=2(daemon)=2(daemon)
    uid=3(adm) gid=4(adm)=4(adm)
    uid=4(lp) gid=7(lp)=7(lp)
    uid=5(sync) gid=0(root)=0(root)
    uid=6(shutdown) gid=0(root)=0(root)
    uid=7(halt) gid=0(root)=0(root)
    uid=8(mail) gid=12(mail)=12(mail)
    uid=11(operator) gid=0(root)=0(root)
    uid=12(games) gid=100(users)=100(users)
    uid=14(ftp) gid=50(ftp)=50(ftp)
    uid=99(nobody) gid=99(nobody)=99(nobody)
    uid=192(systemd-network) gid=192(systemd-network)=192(systemd-network)
    uid=81(dbus) gid=81(dbus)=81(dbus)
    uid=999(polkitd) gid=998(polkitd)=998(polkitd)
    uid=998(libstoragemgmt) gid=996(libstoragemgmt)=996(libstoragemgmt)
    uid=997(colord) gid=995(colord)=995(colord)
    uid=32(rpc) gid=32(rpc)=32(rpc)
    uid=996(saslauth) gid=76(saslauth)=76(saslauth)
    uid=173(abrt) gid=173(abrt)=173(abrt)
    uid=172(rtkit) gid=172(rtkit)=172(rtkit)
    uid=75(radvd) gid=75(radvd)=75(radvd)
    uid=995(chrony) gid=992(chrony)=992(chrony)
    uid=994(gluster) gid=991(gluster)=991(gluster)
    uid=107(qemu) gid=107(qemu)=107(qemu),36(kvm)
    uid=993(unbound) gid=990(unbound)=990(unbound)
    uid=59(tss) gid=59(tss)=59(tss)
    uid=113(usbmuxd) gid=113(usbmuxd)=113(usbmuxd)
    uid=992(geoclue) gid=988(geoclue)=988(geoclue)
    uid=991(setroubleshoot) gid=987(setroubleshoot)=987(setroubleshoot)
    uid=171(pulse) gid=171(pulse)=171(pulse)
    uid=990(saned) gid=984(saned)=984(saned)
    uid=42(gdm) gid=42(gdm)=42(gdm)
    uid=29(rpcuser) gid=29(rpcuser)=29(rpcuser)
    uid=65534(nfsnobody) gid=65534(nfsnobody)=65534(nfsnobody)
    uid=989(gnome-initial-setup) gid=983(gnome-initial-setup)=983(gnome-initial-setup)
    uid=74(sshd) gid=74(sshd)=74(sshd)
    uid=70(avahi) gid=70(avahi)=70(avahi)
    uid=89(postfix) gid=89(postfix)=89(postfix),12(mail)
    uid=38(ntp) gid=38(ntp)=38(ntp)
    uid=72(tcpdump) gid=72(tcpdump)=72(tcpdump)
    uid=1000(948cshell) gid=1000(948cshell)=1000(948cshell),10(wheel)
    uid=1001(test1) gid=1001(test1)=1001(test1),1000(948cshell)
    
  • 用户输入某个目录名,输出这个目录内所有文件的权限。
    #!/bin/bash
    # Program:
    #       User input dir name , I find the permission of files
    # History:
    # 2020/08/12    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    # 1、先看看这个目录是否存在
    read -p "Please input a directory: " dir
    if [ "${dir}" == "" -o ! -d "${dir}" ]; then
        echo "The ${dir} is NOT exist in your system."
        exit 1
    fi
    
    # 2、开始测试文件
    filelist=$(ls ${dir})
    for filename in ${filelist}
    do
        perm=""
        test -r "${dir}/${filename}" && perm="${perm} readable"
        test -w "${dir}/${filename}" && perm="${perm} writable"
        test -x "${dir}/${filename}" && perm="${perm} executable"
        echo "The file ${dir}/${filename}'s permission is ${perm}"
    done
    
    
    [948cshell@localhost bin]$ sh dir_perm.sh 
    Please input a directory: /home/948cshell/bin
    The file /home/948cshell/bin/ans_yn.sh's permission is  readable writable
    The file /home/948cshell/bin/cal_1_100.sh's permission is  readable writable
    The file /home/948cshell/bin/cal_pi.sh's permission is  readable writable
    The file /home/948cshell/bin/cal_retired.sh's permission is  readable writable
    The file /home/948cshell/bin/case_hello-2.sh's permission is  readable writable
    The file /home/948cshell/bin/create_3_filename.sh's permission is  readable writable
    The file /home/948cshell/bin/dir_perm.sh's permission is  readable writable
    The file /home/948cshell/bin/file_perm.sh's permission is  readable writable
    The file /home/948cshell/bin/hello-2.sh's permission is  readable writable
    The file /home/948cshell/bin/hello.sh's permission is  readable writable executable
    The file /home/948cshell/bin/how_paras.sh's permission is  readable writable
    The file /home/948cshell/bin/ifelif_ans_yn.sh's permission is  readable writable
    The file /home/948cshell/bin/ifthen_ans_yn.sh's permission is  readable writable
    The file /home/948cshell/bin/multiplying.sh's permission is  readable writable
    The file /home/948cshell/bin/my_ans_yn.sh's permission is  readable writable
    The file /home/948cshell/bin/my_cal_retired.sh's permission is  readable writable
    The file /home/948cshell/bin/my_create_3_filename.sh's permission is  readable writable
    The file /home/948cshell/bin/my_file_perm.sh's permission is  readable writable
    The file /home/948cshell/bin/my_hello-2.sh's permission is  readable writable
    The file /home/948cshell/bin/my_how_paras.sh's permission is  readable writable
    The file /home/948cshell/bin/my_multiplying.sh's permission is  readable writable
    The file /home/948cshell/bin/my_yes_to_stop-2.sh's permission is  readable writable
    The file /home/948cshell/bin/my_yes_to_stop.sh's permission is  readable writable
    The file /home/948cshell/bin/shift_paras.sh's permission is  readable writable
    The file /home/948cshell/bin/show123-2.sh's permission is  readable writable
    The file /home/948cshell/bin/show123-3.sh's permission is  readable writable
    The file /home/948cshell/bin/show123.sh's permission is  readable writable
    The file /home/948cshell/bin/show_animal.sh's permission is  readable writable
    The file /home/948cshell/bin/showname.sh's permission is  readable writable executable
    The file /home/948cshell/bin/userid.sh's permission is  readable writable
    The file /home/948cshell/bin/yes_to_stop-2.sh's permission is  readable writable
    The file /home/948cshell/bin/yes_to_stop.sh's permission is  readable writable
    

12.5.3、for…do…done的数值处理

1、for…do…done的数值处理的使用范例

  • 计算1+2…+…的值。
    #!/bin/bash
    # Program:
    #       Try do calculate 1+2+...+${your_input}
    # History:
    # 2020/08/12    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    read -p "Please input a number, I will count for 1+2+...+your input: " nu
    s=0;
    for ((i=1; i<=${nu}; i++))
    do
        s=$((${s}+${i}))
    done
    echo "The result of '1+2...+${nu}' is ==> ${s}"
    
    
    [948cshell@localhost bin]$ sh cal_1_100-2.sh 
    Please input a number, I will count for 1+2+...+your input: 9
    The result of '1+2...+9' is ==> 45
    [948cshell@localhost bin]$ sh cal_1_100-2.sh 
    Please input a number, I will count for 1+2+...+your input: 100
    The result of '1+2...+100' is ==> 5050
    

12.5.4、搭配随机数与数组的实验

1、随机数与数组在脚本中的使用范例。

  • 用数组存每一种便当的名称,通过随机数随机输出一种便当。
    #!/bin/bash
    # Program:
    #       Try do tell you what you may eat.
    # History:
    # 2020/08/12    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    # 写下所有的店家
    eat[1]="卖当当汉堡"
    eat[2]="肯爷爷炸鸡"
    eat[3]="彩虹日式便当"
    eat[4]="越油越好吃大雅"
    eat[5]="想不出吃啥学餐"
    eat[6]="太师父便当"
    eat[7]="池上便当"
    eat[8]="怀念火车便当"
    eat[9]="一起吃泡面"
    # 保存有几个可用的便当
    eatnum=9
    check=$(( ${RANDOM} * ${eatnum} /32767 + 1 ))
    echo "your may eat ${eat[${check}]}"
    
    
    [948cshell@localhost bin]$ sh what_to_eat.sh 
    your may eat 一起吃泡面
    [948cshell@localhost bin]$ sh what_to_eat.sh 
    your may eat 肯爷爷炸鸡
    [948cshell@localhost bin]$ sh what_to_eat.sh 
    your may eat 一起吃泡面
    [948cshell@localhost bin]$ sh what_to_eat.sh 
    your may eat 怀念火车便当
    [948cshell@localhost bin]$ sh what_to_eat.sh 
    your may eat 彩虹日式便当
    [948cshell@localhost bin]$ sh what_to_eat.sh 
    your may eat 池上便当
    [948cshell@localhost bin]$ sh what_to_eat.sh 
    your may eat 太师父便当
    [948cshell@localhost bin]$ sh what_to_eat.sh 
    your may eat 彩虹日式便当
    [948cshell@localhost bin]$ sh what_to_eat.sh 
    your may eat 一起吃泡面
    
  • 用数组存每一种便当的名称,通过随机数随机输出三种不重复的便当
    #!/bin/bash
    # Program:
    #       Try do tell you what you may eat.
    # History:
    # 2020/08/12    VBird   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    # 写下所有的店家
    eat[1]="卖当当汉堡"
    eat[2]="肯爷爷炸鸡"
    eat[3]="彩虹日式便当"
    eat[4]="越油越好吃大雅"
    eat[5]="想不出吃啥学餐"
    eat[6]="太师父便当"
    eat[7]="池上便当"
    eat[8]="怀念火车便当"
    eat[9]="一起吃泡面"
    eatnum=9
    eated=0
    # 初始化,一开始所有的便当都没有被选。
    for (( i=1; i<=${eatnum}; i++ ))
    do
        haspick[${i}]=0
    done
    while [ "${eated}" -lt "3" ]
    do
        check=$(( ${RANDOM} * ${eatnum} /32767 + 1 ))
        # 检查是否便当已经被选了,如果被选了,mycheck赋值为1。
        mycheck=0
        for (( i=1; i<=${eatnum}; i++ ))
        do
            if [ "${haspick[${check}]}" == "1" ]; then
                mycheck=1
            fi
        done
        # 判断是否有已经被选择的便当,如果没有,就是一次成功的选择。
        if [ "${mycheck}" != "1" ]; then
            haspick[${check}]=1
            eated=$(( ${eated} + 1 ))
            echo "your may eat ${eat[${check}]}"
        fi
    done
    
    
    [948cshell@localhost bin]$ sh what_to_eat-2.sh 
    your may eat 怀念火车便当
    your may eat 卖当当汉堡
    your may eat 太师父便当
    [948cshell@localhost bin]$ sh what_to_eat-2.sh 
    your may eat 池上便当
    your may eat 肯爷爷炸鸡
    your may eat 越油越好吃大雅
    [948cshell@localhost bin]$ sh what_to_eat-2.sh 
    your may eat 池上便当
    your may eat 卖当当汉堡
    your may eat 彩虹日式便当
    

12.8、本章习题

1、第一题

#!/bin/bash
# Program:
#       Print username who are using CentOS and current directory.
# History:
# 2020/08/13    948cshell   First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo "您目前的身份是:$(whoami)"
echo "您目前所在的目录是:$(pwd)"


[948cshell@localhost bin]$ sh print_whoami_pwd.sh
您目前的身份是:948cshell
您目前所在的目录是:/home/948cshell/bin

2、第二题

#!/bin/bash
# Program:
#       Print the remained time to my next birthday.
# History:
# 2020/08/12    VBird   First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
current_year="$(date +%Y)"
next_year="$(( ${current_year} + 1 ))"
current_time="$(date +%s)"
current_year_birthday="$(date --date="${current_year}0320" +%s)"
next_year_birthday="$(date --date="${next_year}0320" +%s)"
if [ "${current_time}" -gt "${current_year_birthday}" ]; then
    remained=$(( ${next_year_birthday} - ${current_time} ))
else
    remained=$(( ${current_year_birthday} - ${current_time} ))
fi
echo "距离生日还有$(( ${remained} /60/60/24 ))天"


[948cshell@localhost bin]$ sh how_long_can_I_have_my_next_birthday.sh 
距离生日还有218天

3、第三题

#!/bin/bash
# Program:
#       user input a number n, sh will calculate the result of 1+2...+n.
# History:
# 2020/08/10    VBird   First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
read -p "Please input a number n : " n
declare -i sum=0
for ((i=1; i<=${n}; i++ ))
do
    sum=$(( ${sum} + ${i} ))
done
echo "The result of 1+2...+${n} is : ${sum}."


[948cshell@localhost bin]$ sh cal_1_to_n.sh 
Please input a number n : 100
The result of 1+2...+100 is : 5050.
[948cshell@localhost bin]$ sh cal_1_to_n.sh 
Please input a number n : 10
The result of 1+2...+10 is : 55.

4、第四题

#!/bin/bash
# Program:
#       deal with directory /root/test/logical
# History:
# 2020/08/12    VBird   First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
tested_directory='/root/test'
tested_file='logical'
if [ -e "${tested_directory}/${tested_file}" ]; then
    if [ -f "${tested_directory}/${tested_file}" ]; then
        rm -i "${tested_directory}/${tested_file}"
        mkdir -p "${tested_directory}/${tested_file}"
    else
        rm -ir "${tested_directory}/${tested_file}"
    fi
else
    if [ ! -e "${tested_directory}" ]; then
        mkdir -p "${tested_directory}"
    fi
    cd "${tested_directory}"
    touch "${tested_file}"
fi

5、第五题

#!/bin/bash
# Program:
#       Print account in this system.
# History:
# 2020/08/12    VBird   First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
row_num=1
for account in $(cut -d ':' -f1 /etc/passwd)
do
    echo "This ${row_num} account is \"${account}\""
    row_num=$(( ${row_num} + 1 ))
done


[948cshell@localhost bin]$ sh print_account.sh 
This 1 account is "root"
This 2 account is "bin"
This 3 account is "daemon"
This 4 account is "adm"
This 5 account is "lp"
This 6 account is "sync"
This 7 account is "shutdown"
This 8 account is "halt"
This 9 account is "mail"
This 10 account is "operator"
This 11 account is "games"
This 12 account is "ftp"
This 13 account is "nobody"
This 14 account is "systemd-network"
This 15 account is "dbus"
This 16 account is "polkitd"
This 17 account is "libstoragemgmt"
This 18 account is "colord"
This 19 account is "rpc"
This 20 account is "saslauth"
This 21 account is "abrt"
This 22 account is "rtkit"
This 23 account is "radvd"
This 24 account is "chrony"
This 25 account is "gluster"
This 26 account is "qemu"
This 27 account is "unbound"
This 28 account is "tss"
This 29 account is "usbmuxd"
This 30 account is "geoclue"
This 31 account is "setroubleshoot"
This 32 account is "pulse"
This 33 account is "saned"
This 34 account is "gdm"
This 35 account is "rpcuser"
This 36 account is "nfsnobody"
This 37 account is "gnome-initial-setup"
This 38 account is "sshd"
This 39 account is "avahi"
This 40 account is "postfix"
This 41 account is "ntp"
This 42 account is "tcpdump"
This 43 account is "948cshell"
This 44 account is "test1"

13.2.1、新增与删除用户:useradd、相关配置文件、passwd、usermod、userdel

1、关于/etc/login.defs文件的内容。

MAIL_DIR	/var/spool/mail
PASS_MAX_DAYS	99999
PASS_MIN_DAYS	0
PASS_MIN_LEN	5
PASS_WARN_AGE	7
UID_MIN                  1000
UID_MAX                 60000
SYS_UID_MIN               201
SYS_UID_MAX               999
GID_MIN                  1000
GID_MAX                 60000
SYS_GID_MIN               201
SYS_GID_MAX               999
CREATE_HOME	yes
UMASK           077
USERGROUPS_ENAB yes
ENCRYPT_METHOD SHA512

13.4.2、sudo

1、关于当用户的sudo权限重复设置时的问题以及对用户能够使用sudo执行的命令限制的设置问题的说明。

  • 将用户pro1通过visudo添加到sudoer中,并设置了对于pro1用户能够以root身份执行命令的一些限制之后,登陆pro1用户进行这些命令限制的测试,惊人的发现用户pro1还是可以执行这些被限制不能使用的命令,最后检查了语法,发现没有问题。偶然的输出了一下pro1所属的用户组,不知道什么时候将pro1添加进了wheel用户组,根据visudo中对于这个用户组的设置来说,属于这个wheel用户组的用户可以以任何用户的身份执行任何命令,由于网上也没有说清楚sudo的权限在执行的时候的原理,所以千万不要给同一个用户重复设置sudo权限,尤其是设置两个完全不同的权限,不然非常的麻烦。
  • 在对用户进行sudo可以执行的命令进行设置的时候,是从后开始向前进行匹配的,所以对于同一个命令限制的设置要满足某种规律,举例来说,如果我要让一般的用户可以使用sudo通过root身份来进行密码的修改,而又不能修改root的密码,因此这是就需要对这个用户在使用passwd命令上进行一些限制。命令【passwd root】应该被禁止,命令【passwd】也应该被禁止,因为sudo是以root的身份执行命令【passwd】,所以也会修改root的密码,但是【passwd 用户名】就不应该被禁,那么我需要通过visudo命令进入文件【/etc/sudoers】给这个用户进行命令设置(【/usr/bin/passwd [A-Za-z]*】,【!/usr/bin/passwd】,【!/usr/bin/passwd root】),由于是从后往前进行检测,所以前面的命令的执行范围应该要包括后面的命令的执行范围,这一点相当的关键。如果将上述三种命令设置按照下图进行排列:
    在这里插入图片描述
    切换到对应的用户,尝试执行被设置的命令,如下图所示。
    在这里插入图片描述
    上图中发现可以更改除了root之外的密码,这是符合要求的。接下来测试看能不能修改root密码。如下图。
    在这里插入图片描述
    从上图中可以发现,命令【passwd】也不能修改root密码,这是我们想要的,可是命令【passwd root】却可以修改root密码,这显然不对,错因就在于命令【passwd [A-Za-z]*】是包含命令【passwd root】的,也就是说执行命令【passwd root】的时候会先检测到【/usr/bin/passwd [A-Za-z]*】,发现符合要求于是便把命令【passwd root】错当作是可以执行的命令了。
    同理如果按照下面的组合。
    在这里插入图片描述
    切换用户进行如下测试。
    在这里插入图片描述
    上图中命令【passwd】和命令【passwd root】都不能正常运行,这是我们想要的。错误发生在下途中的测试。
    在这里插入图片描述
    其他用户的密码也不能被修改,这显然不是我们期望的结果。错因在于命令【passwd】从字符串的组成上要包含【passwd [A-Za-z]*】,后者是必须passwd后面跟上其他的字符串,而前者则是passwd后面可以什么都不跟。因此正确的顺序如下图。
    在这里插入图片描述
    之后切换用户测试。
    在这里插入图片描述
    从上图中发现全部正确。
    因此可以总结,用visudo命令在设置用户sudo权限时,针对同一个命令的多种限制,系统会从后向前进行命令限制字符串的匹配,如果匹配到了满足的命令限制条件就会执行而不会继续向后匹配,也就是说前面的命令限制条件的字符串必须是后面命令限制条件字符串的前缀,或者是前面命令限制条件的字符串集必须包含后面命令限制条件字符串集,从上面的例子来说,命令【passwd】是命令【passwd [A-Za-z]*】的前缀,命令【passwd [A-Za-z]*】的字符串字符集包括命令【passwd root】,这个规律也不一定对,还是要依情况而定。

13.5.4、常用模块简介

1、什么是ssh?

  • ssh= secure shell
    可以让远程主机通过网络访问sshd服务,开始一个安全shell,并对其进行操控。

13.7.2、大量创建帐号模板,适用passwd --stdin选项

1、批量增加用户的脚本模板

  • 该模板需要在root用户中才能进行
    #!/bin/bash
    # Program:
    #       This shell script will creates amount of Linux login accounts for you.
    #       1、check the "accountadd.txt" file exist? You must create that file manually.
    #          one account name one line in the "accountadd.txt" file.
    #       2、user openssl to create users password.
    #       3、user must change his password in his first login.
    # History:
    # 2020/08/16    948cshell   First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin
    export PATH
    
    # 0、userinput
    # if your account need secondary group, add here.
    usergroup=""
    # "openssl" or "account" is needed.
    pwmech="openssl"
    # if "yes" then I will modify home dir permission to 711
    homeperm="no"
    
    # 1、check the accountadd.txt file
    # "create" is useradd and "delete" is userdel.
    action="${1}"
    if [ ! -f "accountadd.txt" ]; then
        echo "There is no accountadd.txt file, stop here."
        exit 1
    fi
    # 如果有额外的用户组需要加入,创建一个GID小于500的系统工作组
    [ "${usergroup}" != "" ] && groupadd -r ${usergroup}
    usernames=$(cat accountadd.txt)
    for username in ${usernames}
    do
        case ${action} in
            "create")
                [ "${usergroup}" ] && usegrp=" -G ${usergroup}" || usegrp=""
                # 新建帐号
                useradd ${usegrp} ${username}
                # 随机生成一个6位的密码或者将用户名当作密码
                [ "${pwmech}" == "openssl" ] && usepw=$(openssl rand -base64 6) || usepw=${username}
                # 给每个用户设置密码
    	    echo "${usepw}" | passwd --stdin ${username}
                # 设置用户一登陆就要修改密码
                chage -d 0 ${username}
                [ "${homeperm}" == "yes" ] && chmod 711 /home/${username}
                echo "username=${username}, password=${usepw}" >> outputpw.txt
                ;;
            "delete")
                echo "deleting ${username}"
                userdel -r ${username}
                ;;
        esac
    done
    
  • 如果要创建用户。
    先编辑一下accountadd.txt文件。例子如下图。
    在这里插入图片描述
    之后终端以root身份运行脚本。例子如下。
    在这里插入图片描述
    即可成功运行。
  • 如果想删除用户。
    终端以root身份运行脚本。例子如下。
    在这里插入图片描述
    即可成功删除。

13.9、本章习题

1、第一题

  • 我的回答:root的UID和GID都是0,如果要让test这个一般用户拥有root权限,可以将他的UID和GID改成0。
  • 其他回答:root的UID与GID都是0,UID只有0和非0两种,0代表系统管理员。所以要让test这个账号具有root的权限,只要把test的UID和GID都改为0即可。

2、第二题

  • 我的回答:可以通过命令【passwd -l 用户名】给这个不乖的用户帐号上锁。
  • 其他回答:有几种办法。一是将/etc/passwd的shell字段写成/sbin/nologin,即可以让该账号暂时无法登录主机;二是将/etc/shadow内的口令字段添加一个*号在最前面;三是将/etc/shadow的第八个字段关于账号取消日期的改成小于当前日期的数字

3、第三题

  • 我的回答:UID在/etc/passwd文件中,GID在/etc/group文件中,用户密码在/etc/shadow文件中,用户组密码在/etc/gshadow中。
  • 其他回答:在/etc/login.defs还有/etc/default/useradd里面。

4、第四题

  • 我的回答:需要配置一个/etc目录下的目录,因为创建一个家目录的时候会将这个目录中的文件拷贝一份过去。
  • 其他回答:使用useradd的时候系统会自动以/etc/skel为默认home目录,所以在这个目录里新建一个名称为www的子目录即可。

5、第五题

  • 我的回答:系统帐号没有家目录。
  • 其他回答:从UID来说,UID为1~499的就是系统账号,往后为一般用户账号。系统账号拥有的权限一般比一般用户账号大,系统账号可以调用某些系统资源。

6、第六题

  • 我的回答:不知道。
  • 其他回答:不同的Linux distributions对于user的group创建机制不同,主要有两种。一种是Public group schemes:用户将会直接得到一个系统指定的群组,一般来说是users;另一种是Private group schemes:系统会创建一个与账号相同的群组。CentOS就属于后者。

7、第七题

  • 我的回答:使用命令【useradd -g alexgroup -G uses -s /bin/csh -c “Alex Tsai” alex】。
  • 其他回答:groupadd alexgroup
    useradd -c “Alex Tsai” -g alexgroup -G users -m alex
    先创建群组再创建使用者

8、第八题

  • 我的回答:输入命令【useradd -d /account 用户名】。
  • 其他回答:修改变量。编辑/etc/default/useradd,将HOME=/home改成HOME=/account即可(个人觉得不对)。

9、第九题

  • 我的回答:输入命令【usermod -G vbird1 vbird2 vbird3 dmtsai】。
  • 其他回答:usermod -a -G vbird1,vbird2,vbird3 dmtsai。

14.2.1、什么是RAID

1、关于磁盘阵列等级RAID 5的说明。

  • RAID 5 是一种存储性能、数据安全和存储成本兼顾的存储解决方案。 RAID 5可以理解为是RAID 0和RAID 1的折中方案。RAID 5可以为系统提供数据安全保障,但保障程度要比Mirror低而磁盘空间利用率要比Mirror高。RAID 5具有和RAID 0相近似的数据读取速度,只是多了一个奇偶校验信息,写入数据的速度比对单个磁盘进行写入操作稍慢。同时由于多个数据对应一个奇偶校验信息,RAID 5的磁盘空间利用率要比RAID 1高,存储成本相对较低,是运用较多的一种解决方案。
  • RAID 5不对数据进行备份,而是把数据和与其相对应的奇偶校验信息存储到组成RAID5的各个磁盘上,并且奇偶校验信息和相对应的数据分别存储于不同的磁盘上。当RAID5的一个磁盘数据损坏后,利用剩下的数据和相应的奇偶校验信息去恢复被损坏的数据。
  • RAID5把数据和相对应的奇偶校验信息存储到组成RAID5的各个磁盘上,并且奇偶校验信息和相对应的数据分别存储于不同的磁盘上,其中任意N-1块磁盘上都存储完整的数据,也就是说有相当于一块磁盘容量的空间用于存储奇偶校验信息。因此当RAID5的一个磁盘发生损坏后,不会影响数据的完整性,从而保证了数据安全。当损坏的磁盘被替换后,RAID还会自动利用剩下奇偶校验信息去重建此磁盘上的数据,来保持RAID5的高可靠性。做raid 5阵列所有磁盘容量必须一样大,当容量不同时,会以最小的容量为准。 最好硬盘转速一样,否则会影响性能,而且可用空间=磁盘数n-1,Raid 5 没有独立的奇偶校验盘,所有校验信息分散放在所有磁盘上, 只占用一个磁盘的容量。
  • 总之RAID 5磁盘阵列只允许同一时间坏一个磁盘,如果又有一块磁盘坏了,那么之前坏的那块磁盘上的数据对应的奇偶校验值可能也会丢失,这将造成RAID 5磁盘阵列的整体损坏。

14.2.3、软件磁盘阵列的设置

1、创建一个RAID 5级别的软件磁盘阵列并格式化与挂载使用案例。
案例的RAID 5级别的软件磁盘阵列的环境为:利用4个分区组成RAID 5。每个分区大小是1G,需确定每个分区一样大较佳。将1个分区设置为热备份磁盘。chunk设置为256KB这么大即可。这个热备份磁盘的大小与其他RAID所需分区一样大。将RAID 5设备挂载到目录【/srv/raid】下。

  • 第一步:创建5个分区。如果是GPT格式的分区表,使用gdisk命令进行分区。分完之后如下图所示。
    在这里插入图片描述
    在这里插入图片描述
  • 第二步使用mdadm命令创建RAID。如下图所示。
    在这里插入图片描述
    上图中的最后大括号内的14~18是分区编号,从第一步的图中可以看出。关于mdadm的参数参考【导学e479】。到此磁盘阵列的创建已经成功了。
    列出刚刚创建的软件磁盘阵列的详细信息,如下图。
    在这里插入图片描述

还可以通过查看内存中的文件【/proc/mdstat】文件来显示正在运行的软件磁盘阵列信息。如下图。
在这里插入图片描述
上图中的第二行分区后面有【(S)】的表示这是用来备份的。第三行的【[4/4]】表示此磁盘阵列需要4个设备,其中有4个设备正常运行,后面的【[UUUU]】中的U表示正常运行的意思,如果是不正常运行则会是【_】。
第三步,格式化软件磁盘阵列并使用。如下图。
在这里插入图片描述
关于上图中的命令【mkfs.xfs】的使用参考【导学a240】。到此完成了软件磁盘阵列的挂载使用。

  • 模拟RAID出错,之后进行恢复:案例,承接上面的磁盘阵列的创建。
    第一步:设置磁盘为错误。
    先复制一些数据到软件磁盘阵列挂载的的目录中。如下图所示。
    在这里插入图片描述
    可以看到上图中的目录已经存入了数据。
    假设分区【/dev/sdb14】出错了,将分区【/dev/sdb14】设置为出错状态模拟出现了错误。如下图所示。
    在这里插入图片描述
    上图中可以看到【Failed Devices】变成了1,然后从最后一行可以看出原来是热备份的分区,现在顶替了坏掉的分区14,状态是【spare rebuilding】。热备份磁盘重建完毕后会出现下图。
    在这里插入图片描述

上图中的热备份已经变为了活跃状态。
第二步:将出错的磁盘删除并加入新磁盘。
先从软件磁盘阵列中删除坏掉的磁盘或分区。如下图。
在这里插入图片描述
由于操作目标是分区,所以不需要关机更换磁盘。如果是磁盘坏掉了,在移除出磁盘阵列之后,需要更换磁盘。
将新的磁盘加入到磁盘阵列中,设备名一般还是和之前移出的设备名相同。如下图所示。
在这里插入图片描述
将新的完好的分区或磁盘作为备份,如上图最后一行所示。

  • 设置软件磁盘阵列开机自启并挂载:案例,承接上面案例。
    第一步:获得磁盘阵列的UUID。如下图。
    在这里插入图片描述
    第二步:配置文件【/etc/mdadm.conf】。如下图。
    在这里插入图片描述
    第三步:配置文件【/etc/fstab】。如下图。
    在这里插入图片描述
    通过vim配置文件【/etc/fstab】中的内容,在最后一行加上如下图内容。
    在这里插入图片描述
    在这里插入图片描述
    从上图中可以看出顺利挂载了。

14.2.6、关闭软件RAID

1、如何关闭RAID?(承接14.2.3的磁盘阵列)
第一步:先卸载,并且将文件【/etc/fstab】中的对应的信息删除。如下图所示。
在这里插入图片描述
第二步:覆盖掉RAID的metadata以及XFS的超级块,之后在关闭【/dev/md0】,这里覆盖使用命令【dd】。如下图。
在这里插入图片描述
通过查看文件【/proc/mdstat】可以发现,已经将磁盘阵列删除了。如下图。
在这里插入图片描述
第四部:将文件【/etc/mdadm.conf】中的对应信息删除即可。

14.3.2、LVM实践流程

1、如何创建一个LV并挂载使用?
通过LVM创建LV并格式化挂载使用:例子,建立一个名为vbirdvg的卷组,在这个卷组中划出一个名为vbirdlv的分区,并将其挂载到目录【/srv/lvm】。
第一步:disk阶段,即实际的磁盘。
使用命令gdisk随便划分5个分区,将他们的分区编码设置为8e00,即Linux LVM。如下图,分区14到17所示。
在这里插入图片描述
第二步:PV阶段,将分区变成物理卷。
使用到的命令有如下:
pvcreate:将物理分区建立为物理卷(PV)。
pvscan:查找目前系统里面任何具有物理卷(PV)的磁盘。
pvdisplay:显示出目前系统上面的PV状态。
pvremove:将PV属性移除,让该分区不具有PV属性。
具体操作如下。
先扫描看系统中有没有PV。如下图。
在这里插入图片描述
从上图中可以发现有一个PV存在,这是系统安装时候创建的。
将第一步划分的物理分区(分区14到17)建立成为PV。如下图。
在这里插入图片描述
上图中利用大括号,一口气创建了4个PV。再进行一次PV的扫描,如下图。
在这里插入图片描述
上图中检索到了刚刚创建的4个分区。
可以查看更加详细的PV的状态信息。下面以分区【/dev/sdb14】举例。
在这里插入图片描述
Allocatable字段表示是否被分配,NO表示没有被分配,PE Size表示一个PE的大小,Total PE表示PV共分了多少个PE出来,Free PE表示未被LV用掉的PE数量,Allocated PE表示尚可分配出去的PE数量。这些有关PE的字段的信息会在将该PV分配给VG时进行更新。
第三步:VG阶段,创建VG大磁盘
使用到的命令如下:
vgcreate:主要建立VG的命令。
vgscan:查找系统上面是否有VG存在。
vgdisplay:显示目前系统上面的VG状态。
vgextend:在VG内增加额外的PV。
vgreduce:在VG内删除PV。
vgchange:设置VG是否启动。
vgremove:删除一个VG。
具体操作如下。
创建一个VG。如下图。
在这里插入图片描述
上图中命令【vgcreate】的选项【-s】后面跟一个数字用来指定PE的大小(单位是m,g,t),倒数第二个参数是自定义的VG名称(vbirdvg),最后一个参数是用到的PV名称。
查看系统中的有多少VG。
在这里插入图片描述
从上图中查看到了刚刚创建的vbirdvg。之后在扫描以下系统中所有的PV,如下图。
在这里插入图片描述
可以发现上图中的PV14到PV16都属于名称为vbirdvg的卷组(VG),这是在创建卷组vbirdvg时指定的。
查看vbirdvg卷组的详细信息。
在这里插入图片描述
从上图中可以看出,字段PE Size的大小时16M,这是创建时指定的,Total PE表示总的PE数目,Free PE表示商可配置给LV的PE数量,由于目前还没有建立LV,所以PE可自由使用。PE是在建立卷组后自动创建的。
可以查看以下分配给卷组的物理卷的详细信息,如下图。
在这里插入图片描述
刚创建PV的时候字段Total PE等都是0,由于没有分配给卷组,当分配给卷组后就会有PE的数目了。
可以对一个创建好的卷组进行容量的扩充。如下图。
在这里插入图片描述
上图中的命令vgextend后面一个参数是卷组,最后面一个参数是被加入的PV。
第三步:LV阶段,对大磁盘VG进行分区(LV)
使用的命令如下:
lvcreate:建立LV。
lvscan:查询系统上面的LV。
lvdisplay:显示系统上面的LV状态。
lvextend:在LV里面增加容量。
lvreduce:在LV里面减少容量。
lvremove:删除一个LV。
lvresize:对LV进行容量大小的调整。
具体操作如下。
在一个已经创建好的卷组中创键一个LV分区。如下图。
在这里插入图片描述
上图中命令lvcreate的选项-L后面跟数字用来指定划分的LV分区的大小,该倒数第二个选项是要创建的LV分区的名称,最后一个参数是被划分的已经创建的卷组。
查看系统中所有的LV分区。如下图。
在这里插入图片描述
可以看到刚刚创建的LV分区vbirdlv处于活跃状态。
查看LV分区vbirdlv的详细信息。如下图。
在这里插入图片描述
上图中可以看出这个LV分区的大小时2G。
第四步:文件系统阶段,将LV分区格式化并挂载。
进行xfs文件系统的格式化。如下图。
在这里插入图片描述
将其进行挂载。如下图。
在这里插入图片描述
测试是否可以使用。如下图。
在这里插入图片描述
从上图可以看出,的确可以使用。

14.3.3、放大LV容量

1、放大LV容量的范例
放大文件系统容量:比如给上个案例的目录【/srv/lvm】增加500MB的容量。
第一步:查看卷组【vbirdvg】有多少容量。如下图。
在这里插入图片描述
从上图可以看出卷组的容量足够500M,可以直接放大LV分区的大小。
第二步:放大LV,利用命令lvresize来增加。如下图。
在这里插入图片描述
从上图可以看出原来vbirdlv分区是2G,放大后变成了2.5G了。虽然LV分区放大到了2.5G,可是可以发现文件系统并没有增加容量。如下图,依然还是2G大小。
在这里插入图片描述
第三步:增加文件系统的容量。
先查看以下文件系统的信息。如下图。
在这里插入图片描述
增加文件系统的大小,使用命令【xfs_growfs】命令。如下图。
在这里插入图片描述
发现容量变成了2.5G了。

  • 磁盘容量存储池(LVM thin Volume)使用范例。
    范例内容:将上面例子中创建出来的卷组vbirdvg的剩余容量取出1GB来做出一个名为vbirdtpool的thin pool LV设备,这就是所谓的磁盘容量存储池,由vbirdvg内的vbirdtpool产生一个名为vbirdthin1的10GB LV设备,将此设备格式化未xfs文件系统,并且挂载于目录【/srv/thin】。
    第一步:使用命令lvcreate建立一个vbirdtpool的thin pool设备。
    在这里插入图片描述
    上图中命令lvcreate的选项-T表示创建一个磁盘容量存储池,该选项后面跟的参数格式为【卷组名/待创建的磁盘容量存储池名称】。
    显示一下磁盘容量存储池的详细信息。如下图。
    在这里插入图片描述
    从上图中可以看到还有Allocated的选项,这是存储池的标志。或者可以更加直观的看一下,如下图。
    在这里插入图片描述第二步:建立vbirdthin1这个有10GB的设备,必须使用–thin(即-T选项)与vbirdtpool链接。如下图。
    在这里插入图片描述
    从上图中可以看出明明没有10G以上的容量,可是却能够通过thin pool进行创建。上图中的lvcreate命令的-V选项用来指定虚拟容量,经常和和-T选项连用,-n选项是指定创建的设备的文件名。
    第三步:建立文件系统。如下图。
    在这里插入图片描述
    可以看到虽然真实容量只有1G,可是文件系统信息显示却有10G。
    第四步:测试容量的使用情况。如下图。
    在这里插入图片描述
    从上图中可以看出设备vbirdthin1只使用了0.23%的容量(应该是5%左右才对,不知道为什么会这样),而存储池用了39.81%(应该是50%左右才对),毕竟只有1G。如果往存储池增加容量,可以看到下图的情况。
    在这里插入图片描述
    从上图中可以看出存储池的容量使用率变成25%左右了,而在存储池基础上创建的设备还是5%左右。

14.3.4、使用LVM thin Volume让LVM动态自动调整磁盘使用率

1、磁盘容量存储池的范例
建立LV快照区给上面例子中的逻辑卷vbirdlv作备份。
第一步:查看卷组vbirdvg还剩下多少容量。如下图。
在这里插入图片描述
从上图中可以看出只剩下25PE了。
第二步:利用lvcreate建立逻辑卷vbirdlv的快照区,命名为vbirdsnap1,且给予25个PE。如下图。
在这里插入图片描述
上图中的lvcreate命令的-s选项表示创建的是一个快照文件的意思,-l选项后面跟一个数字,表示使用多少个PE的意思,-n选项用来指定创建的快照的名称,最后一个参数是创建快照的目标文件。查看一下快照的详细信息,如下图。
在这里插入图片描述
上图中的LV Size表示原始文件的大小,在这里的例子中指的是vbirdlv的大小,COW-table size是快照可以记录的最大容量,Allocated to snapshot是目前已经被用掉的容量。将快照文件进行挂载,查看文件系统的信息。如下图。
在这里插入图片描述
从上图中的可以看出被快照的文件与快照文件是一样的,这里有个细节就是在挂载快照文件的时候由于快照文件与被快照的文件拥有相同的uuid所以在使用挂载命令mount的时侯要忽略相同uuid的影响。

14.3.5、LVM的LV磁盘快照

1、创建LV快照并进行数据恢复范例
使用快照功能恢复系统的例子,拿上面案例的逻辑卷vbirdlv和它的快照vbirdsnap1举例。
第一步:将逻辑卷vbirdlv做一点修改。注意修改的容量不要超过快照文件的大小。
在这里插入图片描述
经过修改之后可以发现这两个文件已经是不一样的了。检测一下快照文件,如下图所示。
在这里插入图片描述
从上图中可以发现快照已经使用了37%左右的容量。
第二步:利用快照将原来的文件系统进行备份,使用命令xfsdump。如下图。
在这里插入图片描述
从上图中可以看出成功根据快照创建了vbirdlv的备份文件【/home/lvm.dump】文件。
第三步:删除快照vbirdsnap1,因为备份文件已经建立了,之后恢复逻辑卷vbirdlv对应的文件。
删除快照。如下图。
在这里插入图片描述
之后将逻辑卷vbirdlv重新格式化。如下图。
在这里插入图片描述
将vbirdlv设备重新挂载,并进行数据的恢复。如下图。
在这里插入图片描述
可以看到,已经恢复成功了。
补充一点:在进行数据的测试时,可以将快照区作为测试用的文件,原系统作为备份数据,这样子就算搞砸了,直接将快照删了,在根据原系统建一个新的快照就行,非常的方便。

14.3.6、LVM相关命令集合与LVM的关闭

1、删除LVM的范例
删除系统中的某LVM:以删除上面建立的LV、VG和PV为例。
删除LVM的流程如下:
先卸载系统上面的LVM文件系统(包括快照和所有的LV)。
使用lvremove删除LV。
使用vgchange -a n VGname让该卷组不具有Active标志。
使用vgremove删除VG。
使用pvremove删除PV。
最后使用gdisk或者fdisk将分区的System ID改回来。
具体操作如下图。
在这里插入图片描述
删除存储池,存储上的设备,逻辑卷的顺序是:存储池、存储上的设备、逻辑卷(快照之前已经删了,如果还有快照也要删除)。
接下来将分区的System ID改回来就行了。如下图。
在这里插入图片描述

14.5、本章习题

1、第一题

  • 我的回答:首先需要在文件【/etc/fstab】中给某个文件系统添加usrquota的支持,在脚本循环创建用户的循环体中增加命令【xfs_quota】对于用户的限制语句即可。
  • 其他回答:先将/home制作好quota的环境然后再do…done内的最后一行,新增一行内容为setquota -u $username 40000 50000 0 0 /home

2、第二题

  • 我的回答:RAID1,RAID5,RAID6。
  • 其他回答:RAID-1,RAID-5,RAID-6。

3、第三题:

  • 我的回答:有快照功能。可以用来做备份。
  • 其他回答:snopshot快照功能可以进行数据备份。

4、第四题:

  • 我的回答:关于硬件磁盘阵列,我不知道。
  • 其他回答:/dev/sda。

15.6、本章习题

1、第一题

  • 我的回答:使用数据重定向把标准输出和标准错误输出导入到黑洞文件【/dev/null】。
  • 其他回答:按信件重要与否选择导入文件或丢弃。这样写:*/3 * * * * root /usr/local/ping.sh > /dev/null 2>&1。

2、第二题

  • 我的回答:at 00:00 2016-02-14。由于此时的时间已经过了2016年,所以我没法写命令。
  • 其他回答:at 1am 2016-02-14。

3、第三题

  • 我的回答:在周一到周五15时的每分钟都执行脚本【/usr/local/bin/backup.sh】,相当的麻烦。
  • 其他回答:在每星期的 1~5 ,下午 3 点的每分钟,共进行 60 次 /usr/local/bin/tea_time.sh 这个文件。 要特别注意的是,每个星期 1~5 的 3 点都会进行 60 次!很麻烦。

4、第四题

  • 我的回答:周天的0时25分执行备份脚本backup.sh。

5、第五题

  • 我的回答:没什么任务。

6、第六题

  • 我的回答:在文件【/etc/crontab】中添加一行内容【00 03 * * 6 root find / -perm 6000 > /tmp/uidgid.files】。

16.7、本章习题

1、第一题

  • 我的回答:程序就是代码段的集合。进程是动态的程序,运行中的程序。
  • 其他回答:程序 (program) 是系统上面可以被运行的文件,由于Linux的完整文件路径 (由 / 写起) 仅能有一个, 所以 program 的档名具有单一性。当程序被运行后,就会启动成进程 (process), 一个 program 可以被不同的使用者或者相同的使用者重复的运行成为多个进程, 且该程序所造成的进程还因为不同的使用者,而有不同的权限,且每个 process 几乎都是独立的。

2、第二题

  • 我的回答:忘了。
  • 其他回答:查询/etc/crontab可以用man 5 crontab,查询crontab可以用man crontab或info crontab。

3、第三题

  • 我的回答:使用命令【ps aux | grep ‘crond’】可以查询PID,使用命令【top】可以查询它的PRI值。
  • 其他回答:ps aux | grep crond。

4、第四题

  • 我的回答:由于PRI是由内核动态指定,所以可以通过修改NI来修改优先级。
  • 其他回答:先以 ps aux 找到 crond 的 PID 后,再以renice -n number PID来调整。

5、第五题

  • 我的回答:一般用户不能调整别的用户的NI值,也不能将一个NI值调小。
  • 其他回答:不可以。因为一般身份使用者仅能调整属于自己的 PID 程序,并且,只能将 nice 值调高,不能调低,所以调整为10之后,就不能降回5。

6、第六题

  • 我的回答:可以查看开机时的信息就可以知道网卡有没有被启动。
  • 其他回答:用dmesg来观察。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值