Docs
Ubuntu
ssh远程登录无法兼容新版本openssl 安全协议
Ubuntu22.04的sudoers被修改后无法使用
Ubuntu18.04安装vmware-tools解决无法复制粘贴和自由移动文件的问题
Windows
运维手册
-
+
首页
运维手册
目录 第1章 Linux快速入门 2 第2章 Linux发展及系统安装 12 第3章 CentOS系统管理 39 第4章 Linux必备命令 71 第5章 Linux用户及权限管理 96 第6章 Linux软件包企业实战 113 第7章 Linux磁盘管理 150 第8章 Linux文件服务器企业实战 171 第9章 Apache WEB服务器企业实战 189 第10章 MYSQL服务器企业实战 209 第11章 LAMP架构企业实战 243 基于程序读写分离(效率很高,实施难度大,开发改代码) 287 第12章 CentOS7实战Kickstart批量 系统部署 294 %post 305 第13章 Zabbix分布式监控企业实战 306 第14章 Nginx WEB服务器企业实战 369 第15章 大数据备份企业实战 409 第16章 Shell企业编程基础 422 第17章 Shell编程高级企业实战 459 第18章 黑客攻防Linux服务器企业实战 526 第19章 企业邮件入门简介 538 第20章 自动化运维发展前景 627 第21章 Puppet自动运维企业实战 632 Puppet master端批量执行通知客户端来同步配置,命令如下: 679 第22章 企业级Docker虚拟化平台实战 679 CentOS7\.x系列Docker批量管理脚本代码如下: 755 维 学习手册 # Linux快速入门 Linux是一套免费使用和自由传播的[类UNIX](http://baike.baidu.com/item/%E7%B1%BBUnix" \t "_blank)[操作系统](http://baike.baidu.com/item/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/192" \t "_blank),是一个基于[POSIX](http://baike.baidu.com/item/POSIX" \t "_blank)移植操作系统接口(Portable Operating System Interface of UNIX,POSIX)和[UNIX](http://baike.baidu.com/item/UNIX" \t "_blank)的多用户、[多任务](http://baike.baidu.com/item/%E5%A4%9A%E4%BB%BB%E5%8A%A1" \t "_blank)、支持[多线程](http://baike.baidu.com/item/%E5%A4%9A%E7%BA%BF%E7%A8%8B" \t "_blank)和多[CPU](http://baike.baidu.com/item/CPU" \t "_blank)的操作系统。 目前被广泛使用于企业服务器、WEB网站平台、大数据、虚拟化、Android、超级计算机等领域,未来Linux将应用各行各业,例如云计算、物联网、人工智能等。 本章向读者介绍Linux发展简介、Linux发行版特点、32位及64位CPU特性及Linux内核命名规则。 ## 为什么要学习Linux 我们为什么要学习Linux?我们目前的处境是什么?我们想达到什么样的目标?在谈到这三个问题时,相信每个人都有自己的答案,我们来自不同的家庭,各种经历也都不一样,但最终的目标都是希望通过学习技术,提升自己的专业技术。真正做一个对社会有贡献的人。 想想我们刚步入学堂的那一刻起,心里就狠狠下决心,以后不管做什么,都要有一番出息,可是20年、30年过去了,我们收获了什么,得到了什么,到底是在追求什么?方向又在哪里呢? 在生活中各种挫折、感情、生活以及很多零碎的事情,让我们很难静下心来学习,当我们某天突然惊醒,年少已不在。所以今天就下定决心,现在就要学习,去行动,去改变。 人生最可怕的是在自以为舒适的地方待得太久,等到外界改变来的时候,已经晚了,我们不能像温水煮青蛙一样,待在温水里,没有觉察到周围事物的变化,最终被社会所淘汰,如图1\-1所示。 ![IMG_256](/media/202411/20241125143328440480.jpeg) 图1\-1 温水煮青蛙 ## Linux操作系统简介 Linux操作系统是基于UNIX以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统,Linux能运行各种工具软件、应用程序及网络协议,它支持安装在32位和64位CPU硬件上。 通常的讲,Linux这个词本身只表示Linux内核,但是人们已经习惯用Linux来形容整个基于Linux内核的操作系统,并且是一种使用GNU通用公共许可证(GNU General Public License,GPL)工程各种工具和数据库的操作系统。 GNU是“GNU is Not Unix”,UNIX是一种广泛使用的商业操作系统,由于GNU将要实现以UNIX系统的接口标准,因此GNU计划可以分别开发不同的操作系统部件,并且采用了部分当时已经可自由使用的软件。 为了保证GNU软件可以自由地“使用、复制、修改和发布”,所有的GNU软件都在一份禁止其他人添加任何限制的情况下授权所有权利给任何人的协议条款里,我们把这个条款称之为GNU通用公共许可证(GNU General Public License,GPL)。 1991年的10月5日,Linux创始人Linus Torvalds在comp.os.minix[新闻组](http://baike.baidu.com/view/834.htm" \t "_blank)上发布消息,正式向外宣布Linux内核的诞生,1994年3月Linux 1\.0发布,代码量17万行,当时是完全按照自由免费的协议发布,随后正式采用GPL协议,目前GPL协议版本包括:GPLv1、GPLv2、GPLv3以及未来的GPLv4、GPLv5等。 ## Linux操作系统优点 随着IT产业的不断发展,Linux操作系统应用领域越来越广泛,尤其是近年来Linux在服务器领域飞速的发展,主要得益于Linux操作系统具备的如下优点: * 开源、免费; * 系统迭代更新; * 系统性能稳定; * 安全性高; * 多任务,多用户; * 耗资源少; * 内核小; * 应用领域广泛; * 使用及入门容易。 ## Linux操作系统发行版 学习Linux操作系统,需要选择不同的发行版本,Linux操作系统是一个大类别,Linux操作系统主流发行版本包括:Red Hat Linux、CentOS、Ubuntu、SUSE Linux、Fedora Linux等,具体发行版本区别如下: 1. Red Hat Linux Red Hat Linux是最早的Linux发行版本之一,同时也是最著名的Linux版本,Red Hat Linux已经创造了自己的品牌,也是读者经常听到的“红帽操作系统”。Red Hat 1994年创立,目前公司全世界有3000多人,一直致力于开放的源代码体系,向用户提供一套完整的服务,这使得它特别适合在公共网络中使用。这个版本的Linux也使用最新的内核,还拥有大多数人都需要使用的主体软件包。 Red Hat Linux发行版操作系统的安装过程非常简单,图形安装过程提供简易设置服务器的全部信息,磁盘分区过程可以自动完成,还可以通过图形界面(Graphical User Interface,GUI)完成安装,即使对于Linux新手来说这些都非常简单。后期如果想批量安装Red Hat Linux系统,可以通过批量的工具来实现快速安装。 1. CentOS 社区企业版操作系统(Community Enterprise Operating System,CentOS)是Linux发行版之一,它是来自于Red Hat Enterprise Linux依照开放源代码所编译而成。由于出自同样的源代码,因此有些要求高度稳定性的服务器以CentOS替代商业版的Red Hat Enterprise Linux使用。 CentOS于Red Hat Linux不同之处在于CentOS并不包含封闭的源代码软件,可以开源免费使用,得到运维人员、企业、程序员的青睐,CentOS发行版操作系统是目前企业使用最多的系统之一,2016年12月12日,CentOS7基于 Red Hat Enterprise Linux 的 CentOS Linux 7 (1611\) 系统正式对外发布。 1. Ubuntu Ubuntu是一个以桌面应用为主的Linux操作系统,其名称来自非洲南部祖鲁语或豪萨语的“ubuntu”一词(译为吾帮托或乌班图),意思是“人性”、“我的存在是因为大家的存在”,是非洲传统的一种价值观。 Ubuntu基于Debian发行版和GNOME桌面环境, Ubuntu发行版操作系统的目标在于为一般用户提供一个最新的、同时稳定的以开放自由软件构建而成的操作系统,目前Ubuntu具有庞大的社区力量,用户可以方便地从社区获得帮助。 1. SUSE Linux SUSE(发音 /ˈsuːsə/),SUSE Linux 出自德国,SuSE Linux AG公司发行维护的Linux发行版,是属于此公司的注册商标2003年11月4日,Novell表示将会对SUSE提出收购。收购的工作于2004年1月完成。 Novell也向大家保证SUSE的开发工作仍会继续下去,Novell更把公司内全线电脑的系统换成SUSE LINUX,并同时表示将会把SUSE特有而优秀的系统管理程序 \- YaST2以GPL授权释出。 1. Fedora Linux Fedora是一个知名的Linux发行版,是一款由全球社区爱好者构建的面向日常应用的快速、稳定、强大的操作系统。它允许任何人自由地使用、修改和重发布,无论现在还是将来。它由一个强大的社群开发,这个社群的成员以自己的不懈努力,提供并维护自由、开放源码的软件和开放的标准。 Fedora 约每六个月会发布新版本,美国当地时间2015年11月3日,北京时间2015年11月4日,Fedora Project 宣布 Fedora 23 正式对外发布,2022年6月发布Fedora 26版本。 ## 32位与64位操作系统的区别 学习Linux操作系统之前,需要理解计算机基本的常识,计算机内部对数据的传输和储存都是使用二进制,二进制是计算技术中广泛采用的一种[数制](http://baike.baidu.com/item/%E6%95%B0%E5%88%B6" \t "_blank),而Bit(比特)则表示二进制位,[二进制数](http://baike.baidu.com/item/%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%95%B0" \t "_blank)是用0和1两个[数码](http://baike.baidu.com/item/%E6%95%B0%E7%A0%81" \t "_blank)来表示的数。基数为2,进位规则是“逢二进一”,0或者1分别表示一个Bit二进制位。 Bit位是计算机最小单位,而字节是计算机中数据处理的基本单位,转换单位为:1Byte\=8Bit,4Byte\=32Bit。 随着计算机技术的发展,尤其是中央处理器(Central Processing Unit,CPU)技术的变革,CPU的位数指的是通用寄存器(General\-Purpose Registers, GPRs)的数据宽度,也就是处理器一次可以处理的数据量多少。 目前主流CPU处理器分为32位CPU处理器和64位CPU处理器,32位CPU处理器可以一次性处理4个字节的数据量。而64位处理器一次性处理8个字节的数据量(1Byte\=8bit),64位CPU处理器对计算机处理器在RAM里(随机存取储存器)处理信息的效率比32位CPU做了很多优化,效率更高。 X86\_32位操作系统和X86\_64操作系统也是基于CPU位数的支持,具体区别如下: * 32位操作系统表示32位CPU对内存寻址的能力; * 64位操作系统表示64位CPU对内存寻址的能力; * 32位的操作系统安装在32位CPU处理器和64位CPU处理器上; * 64位操作系统只能安装64位CPU处理器上; * 32位操作系统对内存寻址不能超过4GB; * 64位操作系统对内存寻址可以超过4GB,企业服务器更多安装64位操作系统,支持更多内存资源的利用; * 64位操作系统是为高性能处理需求设计,数据处理、图片处理、实时计算等领域需求; * 32位操作系统是为普通用户设计,普通办公、上网冲浪等需求。 ## Linux内核命名规则 Linux内核是Linux操作系统的核心,一个完整的Linux发行版包括进程管理、内存管理、文件系统、系统管理、网络操作等部分。 Linux内核官网可以下载Linux内核版本、现行版本,历史版本,可以了解版本与版本之间的特性。 Linux内核版本命名在不同的时期有其不同的命名规范,其中在2\.X版本中,X如果为奇数表示开发版、X如果为偶数表示稳定版,从2\.6\.X以及3\.X,内核版本命名就没有严格的约定规范。 从Linux内核1994年发布1\.0发布到目前主流2\.6、3\.X版本,4\.X属于开发调试阶段,查看Linux操作系统内核如图1\-2所示: ![](/media/202411/20241125143328463090.png) 图1\-2操作系统内核 Linux内核命名格式为 “R.X.Y\-Z”,其中R、X、Y、Z命名意义如下: * 数字R表示内核版本号,版本号只有在代码和内核有重大改变的时候才会改变,到目前为止有4个大版本更新。 * 数字X表示内核主版本号,主版本号根据传统的奇偶系统版本编号来分配,奇数为开发版,偶数为稳定版。 * 数字Y表示内核次版本号,次版本号是无论在内核增加安全补丁、修复Bug、实现新的特性或者驱动时都会改变。 * 数字Z表示内核小版本号,小版本号会随着内核功能的修改、Bug修复而发生变化。 官网内核版本如图1\-3所示,Mainline表示主线开发版本,Stable表示稳定版本,稳定版本主要由mainline测试通过而发布。Longterm表示长期支持版,会持续更新及Bug修复,如果长期版本被标记为EOL(End of Life),则表示不再提供更新。 ![](/media/202411/20241125143328469138.png) 图1\-3官网内核版本 # Linux发展及系统安装 互联网飞速发展,用户对网站体验要求也越来越高,目前主流WEB网站后端承载系统均为Linux操作系统,Android手机也是基于Linux内核而研发,企业大数据、云存储、虚拟化等先进技术也均是基于Linux操作系统为载体,满足企业的高速发展。 本章向读者介绍Linux发展前景、Windows与Linux操作系统区别、硬盘分区介绍、CentOS 7 Linux操作系统安装图解及菜鸟学好Linux必备大绝招。 ## Linux发展前景及就业形势 权威部门统计,未来几年内我国软件行业的从业机会十分庞大,中国每年对IT软件人才的需求将达到200万人左右。而对于Linux专业人才的就业前景,更是广阔;据悉在未来5\-10年内Linux专业人才的需求将达到150万,尤其是有Linux行业经验的,资深的Linux工程师非常缺乏,薪资也非常诱人,平均月薪15000\-25000,甚至更高,Linux行业薪资如图2\-1所示: ![](/media/202411/20241125143328474582.png) 图2\-1 Linux行业薪资 ## Windows操作系统简介 为什么要学习Windows操作系统呢,了解Windows系统结构,可以让我们快速学习Linux操作系统,通过对比学习的方法,我们可以更快的学会Linux。 计算机硬件组成包括:CPU、内存、网卡、硬盘、DVD光驱、电源、主板、显示器、鼠标、键盘等设备,计算机硬件是不能直接被人使用的,需要在其上安装各种操作系统,安装完操作系统,并安装驱动程序,方可进行操作、办公、上网冲浪等。 计算机的硬件组成: * CPU,相当于人的大脑,中央处理器; * 内存,存储设备,临时存储,CPU所需要数据,从内存中读取,内存读写速度很快; * 硬盘,持久化设备,内存空间小,费用高,大量的数据存在硬盘,硬盘读写速度比内存慢;(SSD、SAS、SATA); 驱动程序主要指的是设备驱动程序(Device Driver),是一种可以使[计算机](http://baike.baidu.com/item/%E8%AE%A1%E7%AE%97%E6%9C%BA" \t "_blank)系统和设备通信的特殊程序,相当于[硬件](http://baike.baidu.com/item/%E7%A1%AC%E4%BB%B6" \t "_blank)的接口,[操作系统](http://baike.baidu.com/item/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F" \t "_blank)只有通过这个接口,才能控制[硬件](http://baike.baidu.com/item/%E7%A1%AC%E4%BB%B6" \t "_blank)设备,进行资源调度。 Windows操作系统主要以窗口形式对用户展示,操作系统须安装在硬盘上,安装系统之前需对硬盘进行分区并格式化,默认Windows操作系统安装在C盘分区,D盘分区用于存放数据文件。 通俗的讲,安装操作系统时,需要对磁盘进行格式化,格式化需要指定格式化的类型,告诉操作系统如何去管理磁盘空间,文件如何存放,如何查找及调用。操作系统不知道怎么存放文件以及文件结构,文件系统概念就诞生了。 文件系统是[操作系统](http://baike.baidu.com/view/880.htm" \t "_blank)用于明确[磁盘](http://baike.baidu.com/view/157418.htm" \t "_blank)或分区上文件的方法和[数据存储结构](http://baike.baidu.com/view/9900.htm" \t "_blank),文件系统由三部分组成:与文件管理有关软件、被管理文件以及实施文件管理所需数据结构。 Windows操作系统,文件系统类型一般有FAT、FAT16、FAT32、NTFS等,不同的文件系统类型,有不同的特性,例如NTFS文件系统类型支持文件及文件夹安全设置,而FAT32文件系统类型不支持,NTFS支持单文件最多为单个磁盘分区的容量大小2T,而FAT32单个最大文件不能超过4GB。 Windows操作系统从设计层面来讲,主要用来管理[电脑硬件](https://www.baidu.com/s?wd=%E7%94%B5%E8%84%91%E7%A1%AC%E4%BB%B6&tn=44039180_cpr&fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1d-mH04uAR1nWRdnyn3nvf0IAYqnWm3PW64rj0d0AP8IA3qPjfsn1bkrjKxmLKz0ZNzUjdCIZwsrBtEXh9GuA7EQhF9pywdQhPEUiqkIyN1IA-EUBtknjfdrjnznjfsPHDsPWb4nHT4" \t "_blank)与软件资源的程序,大致包括五个方面的管理功能:进程与处理机管理、作业管理、存储管理、设备管理、[文件管理](https://www.baidu.com/s?wd=%E6%96%87%E4%BB%B6%E7%AE%A1%E7%90%86&tn=44039180_cpr&fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1d-mH04uAR1nWRdnyn3nvf0IAYqnWm3PW64rj0d0AP8IA3qPjfsn1bkrjKxmLKz0ZNzUjdCIZwsrBtEXh9GuA7EQhF9pywdQhPEUiqkIyN1IA-EUBtknjfdrjnznjfsPHDsPWb4nHT4" \t "_blank)。Windwos操作系统从个人使用角度来讲,主要用于个人电脑办公、软件安装、上网冲浪、游戏、数据分析、数据存储等功能。 ## 硬盘分区简介 学习Windows、Linux操作系统,必然要了解硬盘设备,硬盘是电脑主要的存储[媒介](http://baike.baidu.com/item/%E5%AA%92%E4%BB%8B" \t "_blank)之一,硬盘要能够安装系统或者存放数据,必须进行分区和格式化,Windows系统常见分区有三种:主磁盘分区、扩展磁盘分区、逻辑磁盘分区。 一块硬盘设备,主分区至少有1个,最多4个,扩展分区可以为0,最多1个,且主分区\+扩展分区总数不能超过4个,逻辑分区可以有若干个。在Windows下激活的主分区是硬盘的启动分区,他是独立的,也是硬盘的第一个分区,通常就是我们所说的C盘系统分区。 扩展分区是不能直接用的,他是以逻辑分区的方式来使用的,扩展分区可分成若干逻辑分区。他们的关系是包含的关系,所有的逻辑分区都是扩展分区的一部分。 在Windows系统安装时,硬盘驱动器是通过磁盘0,磁盘1来显示,其中磁盘0表示第一块硬盘,磁盘1表示第二块硬盘,然后在第一块硬盘磁盘0上进行分区,最多不能超过4个主分区,分区为C、D、E、F。 硬盘接口是[硬盘](http://baike.baidu.com/item/%E7%A1%AC%E7%9B%98" \t "_blank)与[主机系统](http://baike.baidu.com/item/%E4%B8%BB%E6%9C%BA%E7%B3%BB%E7%BB%9F" \t "_blank)间的连接部件,作用是在硬盘[缓存](http://baike.baidu.com/item/%E7%BC%93%E5%AD%98" \t "_blank)和主机内存之间传输数据。不同的硬盘接口决定着硬盘与计算机之间的连接速度,在整个系统中,硬盘接口的优劣直接影响着程序运行快慢和系统性能好坏,常见的硬盘接口类型为:[IDE](http://baike.baidu.com/item/IDE" \t "_blank)(Integrated Drive Electronics)、[SATA](http://baike.baidu.com/item/SATA" \t "_blank)(Serial Advanced Technology Attachment)、[SCSI](http://baike.baidu.com/item/SCSI" \t "_blank)(Small Computer System Interface)、SAS(Serial Attached SCSI)和[光纤通道](http://baike.baidu.com/item/%E5%85%89%E7%BA%A4%E9%80%9A%E9%81%93" \t "_blank)等。 [IDE接口](http://baike.baidu.com/item/IDE%E6%8E%A5%E5%8F%A3" \t "_blank)硬盘多用于家用,部分也应用于传统[服务器](http://baike.baidu.com/item/%E6%9C%8D%E5%8A%A1%E5%99%A8" \t "_blank),[SCSI、SAS接口](http://baike.baidu.com/item/SCSI%E6%8E%A5%E5%8F%A3" \t "_blank)的硬盘则主要应用于服务器市场,而光纤通道用于高端服务器上,SATA主要用于个人家庭办公电脑及低端服务器。 在Linux操作系统中,读者可以看到硬盘驱动器的第一块IDE硬盘接口的硬盘设备为hda,或者SATA硬盘接口的硬盘设备为sda,主分区编号为hda1\-4或者sda1\-4,逻辑分区从5开始。如果有第二块硬盘,主分区编号为hdb1\-4或者sdb1\-4。 不管是Windows还是Linux操作系统,硬盘的总容量\=主分区的容量\+扩展分区的容量,而扩展分区的容量\=各个逻辑分区的容量之和。主分区也可成为“引导分区”,会被操作系统和主板认定为这个硬盘的第一个分区,所以C盘永远都是排在所有磁盘分区的第一的位置上。 MBR(Master Boot Record)和GPT(GUID Partition Table)是在磁盘上存储分区信息的两种不同方式。这些分区信息包含了分区从哪里开始的信息,这样操作系统才知道哪个扇区是属于哪个分区的,以及哪个分区是可以启动操作系统的。 在磁盘上创建分区时,必须选择MBR或者GPT,默认是MBR,也可以通过其他方式修改为GPT方式。MBR分区的硬盘最多支持4个主分区,如果想支持更多主分区,可以考虑使用GPT格式分区。 ## Linux安装环境准备 要学好Linux这门技术,首先需安装Linux操作系统,Linux操作系统安装是每个初学者的门槛。而安装Linux操作系统,最大的困惑莫过于给操作系统进行磁盘分区。 虽然目前各种发行版本的 Linux 已经提供了友好的图形交互界面,但很多初学者还是感觉无从下手,这其中原因主要是不清楚Linux 的分区规定。 Linux 系统安装中规定,同样每块硬盘设备最多只能分 4个主分区(其中包含扩展分区)构成,任何一个扩展分区都要占用一个主分区号码,也就是在一个硬盘中,主分区和扩展分区一共最多是 4 个。 为了让读者能将本书所有Linux技术应用于企业,本书案例以企业里主流Linux操作系统CentOS为蓝本,目前主流CentOS发行版本为CentOS7\.2。 读者在安装CentOS操作系统时,如果没有多余的计算机裸机设备,可以基于Windows主机上安装Vmware workstation工具,该工具的用途可以在Windows主机上创建多个计算机裸机设备资源,包括:CPU、内存、硬盘、网卡、DVD光驱、USB接口、声卡,创建的多个计算机裸机设备共享Windows主机的所有资源。 读者在安装CentOS操作系统时,如果有多余的计算机裸机设备或者企业服务器,可以将CentOS系统直接安装在多余的设备上,安装之前需要下载CentOS7\.2操作系统镜像文件(International Organization for Standardization,ISO 9660标准),通过刻录工具,将ISO镜像文件刻录至DVD光盘或者U盘里,通过DVD或者U盘启动然后安装系统。 如下为在Windwos主机上安装VMware workstation虚拟机软件,虚拟机软件的用途是可以在真实机上模拟一个新的计算机完整的资源设备,进而可以在计算机裸设备上安装CentOS7\.2操作系统步骤: 1. 安装环境准备 * [VMware workstation 10\.0](http://www.xp510.com/xiazai/ossoft/desktools/22610.html) * CentOS 7\.6 x86\_64 1. Vmware Workstation 10\.0下载 | [http://download3\.vmware.com/software/wkst/file/VMware\-workstation\-full\-10\.0\.1\-1379776\.exe](http://download3.vmware.com/software/wkst/file/VMware-workstation-full-10.0.1-1379776.exe) | | --- | 1. CentOS7\.2操作系统ISO镜像下载 | [http://124\.205\.69\.165/files/706900000291EB25/mirror.math.princeton.edu/pub/CentOS/7/isos/x86\_64/CentOS\-7\-x86\_64\-DVD\-1511\.iso](http://124.205.69.165/files/706900000291EB25/mirror.math.princeton.edu/pub/centos/7/isos/x86_64/CentOS-7-x86_64-DVD-1511.iso) | | --- | 1. 将VMware workstation 10\.0和CentOS7 ISO镜像文件下载至Windows系统,双击VMware\-workstation\-full\-10\.0\.1\-1379776\.exe,根据提示完成安装,会在Windows桌面显示VMware Workstation图标,如图2\-2所示: ![](/media/202411/20241125143328484290.png) 图2\-2 VMware Workstation图标 1. 双击桌面VMware Workstation图标打开虚拟机软件,单击“创建新的虚拟机”,如图2\-3所示: ![](/media/202411/20241125143328490227.png) 图2\-3 VMware Workstation创建虚拟机 1. 新建虚拟机向导,选择自定义(高级)(C)选项,如图2\-4所示: ![](/media/202411/20241125143328497151.png) 图2\-4 创建虚拟机向导 1. 安装客户机操作系统,选择“稍后安装操作系统(S)”,如图2\-5所示: ![](/media/202411/20241125143328502757.png) 图2\-5 安装客户机操作系统 1. 选择客户机操作系统,由于我们即将安装CentOS7\.2操作系统,所以需要勾选“Linux(L)”,同时版本(V)选择“CentOS64位”,如图2\-6所示: ![](/media/202411/20241125143328508078.png) 图2\-6 操作系统版本 1. 虚拟机内存设置,默认为1024MB,如图2\-7所示: ![](/media/202411/20241125143328513180.png) 图2\-7 虚拟机内存分配 1. 选择虚拟机网络类型,此处选择\-网络连接为\-“使用桥接模式”,如图2\-8所示: ![](/media/202411/20241125143328518390.png) 图2\-8 虚拟机网络类型 1. 指定磁盘容量,设置虚拟机硬盘大小为40GB,将虚拟磁盘拆分成多个文件,如下图2\-9所示: ![](/media/202411/20241125143328523269.png) 图2\-9设置虚拟机磁盘容量 1. 虚拟机硬件资源创建完成,设备详情里面包括计算机常用设备,例如内存、处理器、硬盘、CD/DVD、网络适配器等,如图2\-10所示: ![](/media/202411/20241125143328528469.png) 图2\-10虚拟机裸机设备 1. 将CentOS7\.2 ISO系统镜像文件添加至虚拟机CD/DVD中,双击虚拟机“CD/DVD(IDE)自动检测”选项,选择CentOS\-7\-x86\_64\-DVD\-1511\.iso镜像文件,如图2\-11所示: ![](/media/202411/20241125143328533425.png) 图2\-11选择系统安装镜像 ## Linux系统安装图解 如果直接在硬件设备上安装CentOS系统,不需要安装虚拟机等步骤,直接将U盘或者光盘插入DVD光驱即可,打开电源设备。 1. 如图2\-12所示,光标选择Install CentOS 7,直接按Enter键进行系统安装。 ![](/media/202411/20241125143328539359.png) 图2\-12选择安装菜单 1. 继续按Enter键启动安装进程,进入光盘检测,按Esc键跳过检测,如图2\-13所示: ![](/media/202411/20241125143328544212.png) 图2\-13跳过ISO镜像检测 1. CentOS7欢迎界面,选择安装过程中界面显示的语言,初学者可以选择“简体中文”或者默认English,如图2\-14所示: ![](/media/202411/20241125143328549352.png) 图2\-14选择安装过程语言 1. CentOS7 Installation Summary安装总览界面,如图2\-15所示: ![](/media/202411/20241125143328557271.png) 图2\-15 Installation Summary界面 1. 选择“I will configure partioning.”,单击Done,如图2\-16所示: ![](/media/202411/20241125143328562429.png) 图2\-16 磁盘分区方式选择 1. 下拉框选择“Standard Partition”,选择\+号,创建分区,如图2\-17所示: ![](/media/202411/20241125143328567590.png) 图2\-17 磁盘分区类型选择 1. Linux操作系统分区与Windows操作系统分区C盘、D盘有很大区别,Liunx操作系统是采用树形的文件系统管理方式,所有的文件存储以/(根)开始,如图2\-18所示。 ![](/media/202411/20241125143328572463.png) 图2\-18 Linux文件系统目录结构 Linux是以文件的方式存储,例如/dev/sda代表整块硬盘,/dev/sda1表示硬盘第一分区,/dev/sda2表示硬盘第二分区,为了能将目录和硬盘分区关联,所以Linux采用挂载点的方式来关联磁盘分区,/boot目录、/根目录、/data目录跟磁盘管理后,称之为分区,每个分区功能如下: * /boot分区用于存放Linux内核及系统启动过程所需文件; * Swap分区又称为交换分区,类似Windows系统的虚拟内存,物理内存不够用时,以供程序使用Swap内存;物理内存32G,虚拟内存512MB!阿里云交换分区设置0; * /分区用于系统安装核心分区及所有文件存放的根系统; * /data分区为自定义分区,企业服务器中用于作应用数据存放。 如图2\-19所示,创建/boot分区并挂载,分区大小为200MB: ![](/media/202411/20241125143328577764.png) 图2\-19 创建/boot分区 单击“Add mount point”即可,磁盘分区默认文件系统类型为XFS,根据如上方法,依次创建swap分区,大小为2048MB,创建/分区,大小为剩余所有空间,最终如图2\-20所示: ![](/media/202411/20241125143328582545.png) 图2\-20 磁盘完整分区 1. 选择SOFTWARE SELECTION,设置为Minimal Install最小化安装,如果后期需要开发包、开发库等软件,可以在系统安装完后,根据需求安装即可,如图2\-21所示: ![](/media/202411/20241125143328587707.png) 图2\-21 选择安装的软件 1. 操作系统时区选择,选择Asia\-Shanghai,关闭Network Time,如图2\-22所示: ![](/media/202411/20241125143328592829.png) 图2\-22 操作系统时区选择 1. 以上配置完毕后,单击“Begin Installation”,单击“Root PASSWORD”设置Root用户密码,如图2\-23所示,如果需要新增普通用户,可以单击“USER CREATEION”进行创建即可。 ![](/media/202411/20241125143328598790.png) 图2\-23 设置ROOT用户密码 1. 安装进程完毕,单击“Reboot”重启系统,如图2\-24所示: ![centos](/media/202411/20241125143328604008.png) 图2\-24 系统安装完毕 1. 重启CentOS 7 Linux操作系统,进入Login登录界面,“localhost login:”处输入root,按Enter键,然后“Password:”处输入系统安装时设定的密码,输入密码时不会提示,密码输入完按Enter键,即可登录CentOS 7 Linux操作系统,默认登录的终端称为Shell终端,所有的后续操作指令均在Shell终端上执行,默认显示字符提示\[root@localhost \~]\#,其中\#代表当前是root用户登录,如果是$表示当前为普通用户。如图2\-25所示: ![](/media/202411/20241125143328609382.png) 图2\-25 Login登录系统界面 ## 菜鸟学好Linux大绝招 系统安装是初学者的门槛,系统安装完毕后,很多初学者不知道该如何学习,不知道如何快速进阶,下面作者总结了菜鸟学好Linux技能的大绝招: * 初学者完成Linux系统分区及安装之后,需熟练掌握Linux系统管理必备命令,命令包括:cd、ls、pwd、clear、chmod、chown、chattr、useradd、userdel、groupadd、vi、vim、cat、more、less、mv、cp、rm、rmdir、touch、ifconfig、ip addr、ping、route、echo、wc、expr、bc、ln、head、tail、who、hostname、top、df、du、netstat、ss、kill、alias、man、tar、zip、unzip、jar、fdisk、free、uptime、lsof、lsmod、lsattr、dd、date、crontab、ps、find、awk、sed、grep、sort、uniq等,每个命令至少练习30遍,逐步掌握每个命令的用法及应用场景; * 初学者进阶之路,需熟练构建Linux下常见服务(DHCP、SAMBA、DNS、Apache、MySQL、Nginx、Zabbix、Squid、Varnish、LVS、Keepalived、ELK、MQ、Zookeeper、Docker、Openstack、Hbase、Mongodb、Redis等,遇到问题先思考,没有头绪可以借助百度、Google搜索引擎,问题解决后,将解决问题的步骤总结并形成文档; * 理解操作系统的每个命令,每个服务的用途,为什么要配置这个服务,为什么需要调整该参数,只有带着目标去学习才能更快的成长,才能让你去发掘更多新知识; * 熟练搭建Linux系统上各种服务之后,需要理解每个服务的完整配置和优化,可以拓展思维。例如LAMP所有服务放在一台机器上,能否分开放在多台服务器以平衡压力呢,该如何去构建和部署呢?一台物理机构建Docker虚拟化,如果是100台、1000台如何去实施呢,会遇到哪些问题呢; * Shell是Linux最经典的命令解释器,Shell脚本可以实现自动化运维,平时多练习Shell脚本编程,每个Shell脚本多练习几遍,从中吸取关键的参数、语法,不断的练习,不断的提高; * 建立个人学习博客,把平时工作、学习中的知识都记录到博客,一方面可以供别人参考,另一方面可以提高自己文档编写及总结的能力; * 学习Linux技术是一个长期的过程,一定要坚持,遇到各种错误、问题可以借助百度、Google搜索引擎,如果解决不了,可以请教同学、朋友及你的老师; * 通过以上步骤的学习方法,不断进步,如果想达到高级、资深大牛级别,还需要进一步深入学习WEB集群架构、网站负载均衡、网站架构优化、自动化运维、运维开发、虚拟化等知识; * 多练习才是硬道理,实践出真知。 ## 本章小结 通过对本章内容的学习,读者对Linux系统有了一个初步的理解,了解Linux行业的发展前景,学会了如何在企业中或者虚拟机中安装Linux系统。 对32位、64位CPU处理器以及对Linux内核版本命名也有进一步的认识,同时掌握了学习Linux的大绝招。 ## 同步作业 1. 企业中服务器品牌DELL R730,其硬盘总量为300G,现需安装CentOS 7 Linux操作系统,请问如何进行分区? 2. GNU与GPL的区别是什么? 3. 企业一台Linux服务器,查看该Linux内核显示:3\.10\.0\-327\.36\.3\.el7\.x86\_64,请分别说出点号分割的每个数字及字母的含义? 4. CentOS Linux至今发布了多少个系统版本? 5. 如果Linux系统采用光盘安装,如何将ISO镜像文件刻录成光盘,请写出具体实现流程? # CentOS系统管理 Linux系统安装完毕,需要对Linux系统进行管理和维护,让Linux服务器能真正应用于企业中。 本章向读者介绍Linux系统引导原理、启动流程、系统目录、权限、命令及CentOS7和CentOS6在系统管理、命令方面有什么区别,让我们一起来遨游在Linux的海洋里。 ## 操作系统启动概念 不管是Windows还是Linux操作系统,底层设备一般均为物理硬件,操作系统启动之前会对硬件进行检测,然后硬盘引导启动操作系统,如下为操作系统启动相关的各个概念: ### BIOS 基本输入输出系统(Basic Input Output System,BIOS)是一组固化到计算机主板上的只读内存[镜像](http://baike.baidu.com/item/%E9%95%9C%E5%83%8F/1574" \t "_blank)(Read Only Memory image,ROM)芯片上的程序,它保存着计算机最重要的基本输入输出的程序、系统设置信息、开机后自检程序和系统自启动程序。主要功能是为计算机提供最底层的、最直接的硬件设置和控制。 ### MBR 全新硬盘在使用之前必须进行分区格式化,硬盘分区初始化的格式主要由两种,分别是:MBR格式和GPT格式。 如果使用MBR格式,操作系统将创建主引导记录扇区(Main Boot Record,MBR),MBR位于整块硬盘的0[磁道](http://baike.baidu.com/view/201106.htm" \t "_blank)0柱面1[扇区](http://baike.baidu.com/view/201129.htm" \t "_blank),主要功能是操作系统对磁盘进行读写时,判断分区的合法性以及分区引导信息的定位。 [主引导扇区](http://baike.baidu.com/view/418400.htm" \t "_blank)总共为512字节,MBR只占用了其中的446个字节,另外的64个字节为[硬盘分区表](http://baike.baidu.com/view/1385.htm" \t "_blank) (Disk Partition Table,DPT),最后两个字节“55,AA”是分区的结束标志。 在MBR硬盘中,硬盘分区信息直接存储于[主引导记录](http://baike.baidu.com/item/%E4%B8%BB%E5%BC%95%E5%AF%BC%E8%AE%B0%E5%BD%95" \t "_blank)(MBR)中,同时主引导记录还存储着系统的[引导程序](http://baike.baidu.com/item/%E5%BC%95%E5%AF%BC%E7%A8%8B%E5%BA%8F" \t "_blank),如图3\-1所示: ![](/media/202411/20241125143328616145.png)图3\-1 MBR分区表内容 MBR是计算机启动最先执行的硬盘上的程序,只有512字节大小,所以不能载入[操作系统](https://www.baidu.com/s?wd=%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F&tn=44039180_cpr&fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1YznWf3m1nzP1fYm16vnhwh0ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6KdThsqpZwYTjCEQLGCpyw9Uz4Bmy-bIi4WUvYETgN-TLwGUv3En1RYP1cvn10L" \t "_blank)的核心,只能先载入一个可以载入计算机核心的程序,我们称之为引导程序。 因为MBR分区标准决定了MBR只支持在2TB以下的硬盘,对于后面的多余空间只能浪费。为了支持能使用大于2T硬盘空间,微软和英特尔公司在可扩展固件接口(Extensible Firmware Interface,EFI)方案中开发了全局唯一的标识符(Globally unique identifier,GUID),进而全面支持大于2T硬盘空间在企业中使用。 ### GPT 全局唯一的标识符(Globally unique identifier,GUID),正逐渐取代MBR成为新标准。它和统一的可扩展固件接口 (Unified Extensible Firmware Interface,UEFI)相辅相成。 UEFI用于取代老旧的BIOS,而GPT则取代老旧的MBR。之所以称为“GUID分区表”,是因为驱动器上的每个分区都有一个全局唯一的标识符。 在GPT硬盘中,分区表的位置信息储存在GPT头中。出于兼容性考虑,第一个扇区同样有一个与MBR类似的标记,叫做受保护的主引导记录(Protected Main Boot Record,PMBR)。 PMBR的作用是当使用不支持GPT的分区工具时,整个硬盘将显示为一个受保护的分区,以防止分区表及硬盘数据遭到破坏,而其中存储的内容和MBR一样,之后才是GPT头。 GPT优点支持2T以上磁盘,如果使用Fdisk分区,最大只能建立2TB大小的分区,创建大于2TB的分区,需使用parted,同时必须使用64位操作系统,Mac、Linux系统都能支持GPT分区格式,Windows 7/8 64bit、Windows Server 2008 64bit支持GPT。图3\-2所示,为GPT硬盘分区表内容: ![](/media/202411/20241125143328621744.png) 图3\-2 GPT分区表内容 ### GRUB GNU项目的多操作系统启动程序(GRand Unified Bootloader,GRUB),可以支持多操作系统的引导,它允许用户可以在[计算机](http://baike.baidu.com/view/3314.htm" \t "_blank)内同时拥有多个[操作系统](http://baike.baidu.com/view/880.htm" \t "_blank),并在计算机启动时选择希望运行的操作系统。 GRUB可用于选择[操作系统](http://baike.baidu.com/view/880.htm" \t "_blank)分区上的不同[内核](http://baike.baidu.com/view/1366.htm" \t "_blank),也可用于向这些[内核](http://baike.baidu.com/view/1366.htm" \t "_blank)传递启动参数。它是一个多重[操作系统](http://baike.baidu.com/view/880.htm" \t "_blank)启动管理器。用来引导不同系统,如Windows,Linux。Linux常见的引导程序包括:LILO、GRUB、GRUB2,CentOS 7 Linux默认使用GRUB2引导程序,引导系统启动。如图3\-3所示为GRUB加载引导流程: ![24774106_1361691166hR1h](/media/202411/20241125143328627683.png) 图3\-3 GRUB引导流程 GRUB2是基于GRUB开发成更加安全强大的多系统引导程序,最新[Linux](http://lib.csdn.net/base/linux" \t "_blank" \o "Linux知识库)发行版都是使用GRUB2作为引导程序。同时GRUB2采用了模块化设计,使得GRUB2核心更加精炼,使用更加灵活,同时也就不需要像GRUB分为stage1,stage1\.5,stage2三个阶段。 ## Linux操作系统启动流程 初学者对Linux操作系统启动流程的理解,能有助于后期在企业中更好的维护Linux服务器,能快速定位系统问题,进而解决问题。Linux操作系统启动流程如图3\-4所示: ![](/media/202411/20241125143328632863.png) 图3\-4 系统启动流程 1. 加载BIOS 计算机电源加电质检,首先加载基本输入输出系统(Basic Input Output System,BIOS),BIOS中包含硬件CPU、内存、硬盘等相关信息,包含设备启动顺序信息、硬盘信息、内存信息、时钟信息、即插即用(Plug\-and\-Play,PNP)特性等。加载完BIOS信息,计算机将根据顺序进行启动。 1. 读取MBR 读取完BIOS信息,计算机将会查找BIOS所指定的硬盘MBR引导扇区,将其内容复制到0x7c00地址所在的物理内存中。被复制到物理内存的内容是Boot Loader,然后进行引导。 1. GRUB引导 GRUB启动引导器是计算机启动过程中运行的第一个软件程序,当计算机读取内存中的GRUB配置信息后,会根据其配置信息来启动硬盘中不同的操作系统。 1. 加载Kernel 计算机读取内存映像,并进行解压缩操作,屏幕一般会输出“Uncompressing Linux”的提示,当解压缩内核完成后,屏幕输出“OK, booting the kernel”。系统将解压后的内核放置在内存之中,并调用start\_kernel()函数来启动一系列的初始化函数并初始化各种设备,完成Linux核心环境的建立。 1. 设定Inittab运行等级 内核加载完毕,会启动Linux操作系统第一个守护进程init,然后通过该进程读取/etc/inittab文件,/etc/inittab文件的作用是设定Linux的运行等级,Linux常见运行级别如下: * 0:关机模式; * 1:单用户模式; * 2:无网络支持的多用户模式; * 3:字符界面多用户模式; * 4:保留,未使用模式; * 5:图像界面多用户模式; * 6:重新引导系统,重启模式。 1. 加载rc.sysinit 读取完运行级别,Linux系统执行的第一个用户层文件/etc/rc.d/rc.sysinit,该文件功能包括:设定PATH运行变量、设定网络配置、启动swap分区、设定/proc、系统函数、配置Selinux等。 1. 加载内核模块 读取/etc/modules.conf文件及/etc/modules.d目录下的文件来加载系统内核模块。该模块文件,可以后期添加或者修改及删除。 1. 启动运行级别程序 根据之前读取的运行级别,操作系统会运行rc0\.d到rc6\.d中的相应的脚本程序,来完成相应的初始化工作和启动相应的服务。其中以S开头表示系统即将启动的程序,如果以K开头,则代表停止该服务。S和K后紧跟的数字为启动顺序编号。如图3\-5所示:![](/media/202411/20241125143328639054.png)图3\-5 运行级别服务 1. 读取rc.local文件 操作系统启动完相应服务之后,会读取执行/etc/rc.d/rc.local文件,可以将需要开机启动的任务加入到该文件末尾,系统会逐行去执行并启动相应命令,如图3\-6所示: ![](/media/202411/20241125143328644189.png) 图3\-6 开机运行加载文件 1. 执行/bin/login程序 执行/bin/login程序,启动到系统登录界面,操作系统等待用户输入用户名和密码,即可登录到Shell终端,如图3\-7所示,输入用户名、密码即可登录Linux操作系统,至此Linux操作系统完整流程启动完毕。 ![](/media/202411/20241125143328650027.png) 图3\-7 系统登录界面 ## CentOS6与CentOS7区别 CentOS6默认采用Sysvinit风格,Sysvinit就是system V风格的init系统,Sysvinit用术语runlevel 来定义"预订的运行模式"。Sysvinit 检查 '/etc/inittab' 文件中是否含有'initdefault' 项,该选项指定init的默认运行模式。Sysvinit 使用脚本,文件命名规则和软链接来实现不同的Runlevel,串行启动各个进程及服务。 CentOS7默认采用Systemd风格,Systemd是Linux系统中最新的初始化系统(init),它主要的设计目标是克服 Sysvinit 固有的缺点,提高系统的启动速度。 Systemd 和 Ubuntu 的 Upstart 是竞争对手,预计会取代 UpStart。Systemd的目标是尽可能启动更少的进程,尽可能将更多进程并行启动。如图3\-8所示为CentOS6与CentOS7操作系统的区别: ![](/media/202411/20241125143328655098.png)图3\-8 CentOS6与CentOS7操作系统区别 Linux操作系统文件系统类型主要由EXT3、EXT4、XFS等,其中CentOS6普遍采用EXT3和EXT4文件系统格式,而CentOS7默认采用XFS格式。如下为EXT3、EXT4、XFS区别: * EXT4是第四代扩展文件系统(Fourth EXtended filesystem,EXT4)是Linux系统下的日志文件系统,是EXT3文件系统的后继版本; * EXT3类型文件系统支持最大16TB文件系统和最大2TB文件; * EXT4分别支持1EB(1EB\=1024PB,1PB\=1024TB)的文件系统,以及16TB的单个文件; * EXT3只支持32,000个子目录,而EXT4支持无限数量的子目录; * EXT4磁盘结构的inode个数支持40亿,而且EXT4的单个文件大小支持到16T(4K block size) ; * XFS是一个64位文件系统,最大支持8EB减1字节的单个文件系统,实际部署时取决于宿主操作系统的最大块限制,常用语64位操作系统,发挥更好的性能; * XFS一种高性能的日志文件系统,最早于1993年,由[Silicon Graphics](http://baike.baidu.com/item/Silicon%20Graphics" \t "_blank)为他们的[IRIX](http://baike.baidu.com/item/IRIX" \t "_blank)[操作系统](http://baike.baidu.com/item/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F" \t "_blank)而开发,是IRIX 5\.3版的默认文件系统; * XFS于2000年5月,[Silicon Graphics](http://baike.baidu.com/item/Silicon%20Graphics" \t "_blank)以[GPL](http://baike.baidu.com/item/GNU%E9%80%9A%E7%94%A8%E5%85%AC%E5%85%B1%E8%AE%B8%E5%8F%AF%E8%AF%81" \t "_blank)发布这套系统的源代码,之后被移植到Linux内核上,XFS特别擅长处理大文件,同时提供平滑的[数据传输](http://baike.baidu.com/item/%E6%95%B0%E6%8D%AE%E4%BC%A0%E8%BE%93" \t "_blank)。 ## TCP/IP协议概述 要学好Linux,对网络协议也要有充分的了解和掌握,例如传输控制协议/[因特网](http://baike.baidu.com/view/1706.htm" \t "_blank)互联协议(Transmission Control Protocol/Internet Protocol,TCP/IP),TCP/IP名为网络[通讯协议](http://baike.baidu.com/view/278358.htm" \t "_blank),是Internet最基本的协议、Internet国际[互联网](http://baike.baidu.com/view/6825.htm" \t "_blank)络的基础,由[网络层](http://baike.baidu.com/view/239600.htm" \t "_blank)的IP协议和[传输层](http://baike.baidu.com/view/239605.htm" \t "_blank)的TCP协议组成。 TCP/IP 定义了电子设备如何连入[因特网](http://baike.baidu.com/view/1706.htm" \t "_blank),以及数据如何在它们之间传输的标准。协议采用了4层的层级结构,每一层都呼叫它的下一层所提供的协议来完成自己的需求。 TCP负责发现[传输](http://baike.baidu.com/view/389471.htm" \t "_blank)的问题,一有问题就发出信号,要求重新传输,直到所有[数据安全](http://baike.baidu.com/view/2308446.htm" \t "_blank)正确地传输到目的地,而IP是给[因特网](http://baike.baidu.com/view/1706.htm" \t "_blank)的每台联网设备规定一个地址。 基于TCP/IP的参考模型将协议分成四个层次,它们分别是网络接口层、网际互连层(IP层)、[传输层](http://baike.baidu.com/view/239605.htm" \t "_blank)(TCP层)和应用层。如图3\-9为TCP/IP跟OSI参考模型层次的对比: ![0_1309781837bovw](/media/202411/20241125143328662772.png) 图3\-9 ISO7层模型与TCP/IP四层对比 OSI模型与TCP/IP模型协议功能实现对照表,如图3\-10所示: ![](/media/202411/20241125143328667725.png) 图3\-10 ISO7层模型与TCP/IP层次功能对比 ## IP地址及网络常识 互联网协议地址(Internet Protocol Address,IP),IP地址是[IP协议](http://baike.baidu.com/view/2802.htm" \t "_blank)提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异。IP地址被用来给[Internet](http://baike.baidu.com/view/11165.htm" \t "_blank)上的每个通信设备的一个编号,每台联网的PC上都需要有IP地址,这样才能正常通信。 IP地址是一个32位的二进制数,通常被分割为4个“8位[二进制](http://baike.baidu.com/view/18536.htm" \t "_blank)数”(即4个字节)。IP地址通常用“[点分十进制](http://baike.baidu.com/view/828066.htm" \t "_blank)”表示成(a.b.c.d)的形式,其中,a,b,c,d都是0\~255之间的十进制整数。 常见的IP地址,分为[IPv4](http://baike.baidu.com/view/21992.htm" \t "_blank)与[IPv6](http://baike.baidu.com/view/5228.htm" \t "_blank)两大类。IP地址编址方案将IP地址空间划分为A、B、C、D、E五类,其中A、B、C是基本类,D、E类作为多播和保留使用。 IPV4有4段数字,每一段最大不超过255。由于互联网的蓬勃发展,IP位址的需求量愈来愈大,使得IP位址的发放愈趋严格,各项资料显示全球IPv4位址在2011年已经全部分发完毕。 地址空间的不足必将妨碍互联网的进一步发展。为了扩大[地址空间](http://baike.baidu.com/view/1507129.htm" \t "_blank),拟通过IPv6重新定义地址空间。IPv6采用128位地址长度。在IPv6的设计过程中除了一劳永逸地解决了地址短缺问题以外,IPV6的诞生可以给全球每一粒沙子配置一个IP地址,还考虑了在IPv4中解决不好的其它问题,如图3\-11所示: ![](/media/202411/20241125143328673851.png) 图3\-11 IPV4与IPV6地址 ### **IP地址分类** IPV4地址编址方案有A、B、C、D、E五类,其中A、B、C是基本类,D、E类作为多播和保留使用,如下为分类详解: 1. A类IP地址 一个A类IP地址是指,在IP地址的四段号码中,第一段号码为网络号码,剩下的三段号码为本地计算机的号码。如果用二进制表示IP地址的话,A类IP地址就由1字节的网络地址和3字节主机地址组成,网络地址的最高位必须是“0”。A类IP地址中网络的标识长度为8位,主机标识的长度为24位,A类网络地址数量较少,有126个网络,每个网络可以容纳主机数达1600万台。 A类IP地址 地址范围1\.0\.0\.0到127\.255\.255\.255 (二进制表示为:00000001 00000000 00000000 00000000 \- 01111110 11111111 11111111 11111111),最后一个为广播地址,A类IP地址的子网掩码为255\.0\.0\.0,每个网络支持的最大主机数为256的3次方\-2\=16777214台。 1. B类IP地址 一个B类IP地址是指在IP地址的四段号码中,前两段号码为网络号码。如果用二进制表示IP地址的话,B类IP地址就由2字节的网络地址和2字节主机地址组成,网络地址的最高位必须是“10”。 B类IP地址中网络的标识长度为16位,主机标识的长度为16位,B类网络地址适用于中等规模的网络,有16384个网络,每个网络所能容纳的计算机数为6万多台。 B类IP地址地址范围128\.0\.0\.0\-191\.255\.255\.255(二进制表示为:10000000 00000000 00000000 00000000\-\-\-\-10111111 11111111 11111111 11111111)。 最后一个是广播地址,B类IP地址的子网掩码为255\.255\.0\.0,每个网络支持的最大主机数为256的2次方\-2\=65534台。 1. C类IP地址 一个C类IP地址是指在IP地址的四段号码中,前三段号码为网络号码,剩下的一段号码为本地计算机的号码。如果用二进制表示IP地址的话,C类IP地址就由3字节的网络地址和1字节主机地址组成,网络地址的最高位必须是“110”。C类IP地址中网络的标识长度为24位,主机标识的长度为8位,C类网络地址数量较多,有209万余个网络。适用于小规模的局域网络,每个网络最多只能包含254台计算机。 C类IP地址范围192\.0\.0\.0\-223\.255\.255\.255\[3] (二进制表示为: 11000000 00000000 00000000 00000000 \- 11011111 11111111 11111111 11111111)。C类IP地址的子网掩码为255\.255\.255\.0,每个网络支持的最大主机数为256\-2\=254台。 1. D类IP地址 D类IP地址又称之为多播地址(Multicast Address),即组播地址。在以太网中,多播地址命名了一组应该在这个网络中应用接收到一个分组的站点。多播地址的最高位必须是“1110”,范围从224\.0\.0\.0到239\.255\.255\.255。 1. 特殊的地址 每一个字节都为0的地址(“0\.0\.0\.0”)表示当前主机,IP地址中的每一个字节都为1的IP地址(“255.255.255.255”)是当前子网的广播地址,IP地址中凡是以“11110”开头的E类IP地址都保留用于将来和实验使用。 IP地址中不能以十进制“127”作为开头,而以数字127.0.0.1到127.255.255.255段的IP地址称为回环地址,用于回路测试,如:127\.0\.0\.1可以代表本机IP地址,网络ID的第一个8位组也不能全置为“0”,全“0”表示本地网络。 ### **子网掩码** 子网掩码(Subnet Mask)又名[网络掩码](http://baike.baidu.com/view/1169777.htm" \t "_blank)、[地址掩码](http://baike.baidu.com/view/4040643.htm" \t "_blank),它是一种用来指明一个[IP地址](http://baike.baidu.com/view/3930.htm" \t "_blank)的哪些位标识的是[主机](http://baike.baidu.com/view/23880.htm" \t "_blank)所在的子网,以及哪些位标识的是主机的位掩码。 通常的讲,子网掩码不能单独存在,它必须结合IP地址一起使用。子网掩码只有一个作用,就是将某个IP地址划分成[网络地址](http://baike.baidu.com/view/547479.htm" \t "_blank)和[主机地址](http://baike.baidu.com/view/547482.htm" \t "_blank)两部分。 子网掩码是一个32位地址,用于屏蔽IP地址的一部分以区别网络标识和主机标识,并说明该IP地址是在局域网上,还是在远程网上。 对于A类地址,默认的子网掩码是255\.0\.0\.0,而对于B类地址来说默认的子网掩码是255\.255\.0\.0;对于C类地址来说默认的子网掩码是255\.255\.255\.0。 [互联网](http://baike.baidu.com/view/6825.htm" \t "_blank)是由各种小型[网络构成](http://baike.baidu.com/view/2039649.htm" \t "_blank)的,每个网络上都有许多[主机](http://baike.baidu.com/view/23880.htm" \t "_blank),这样便构成了一个有层次的结构。IP地址在设计时就考虑到地址分配的层次特点,将每个IP地址都分割成[网络号](http://baike.baidu.com/view/2271538.htm" \t "_blank)和[主机](http://baike.baidu.com/view/23880.htm" \t "_blank)号两部分,以便于IP地址的[寻址](http://baike.baidu.com/view/1303626.htm" \t "_blank)操作。 子网掩码的设定必须遵循一定的规则。与[二进制](http://baike.baidu.com/item/%E4%BA%8C%E8%BF%9B%E5%88%B6" \t "_blank)IP地址相同,子网掩码由1和0组成,且1和0分别连续。子网掩码的长度也是32位,左边是网络位,用[二进制](http://baike.baidu.com/item/%E4%BA%8C%E8%BF%9B%E5%88%B6" \t "_blank)数字“1”表示,1的数目等于网络位的长度;右边是主机位,用二进制数字“0”表示,0的数目等于主机位的长度。 ### **网关地址** [网关](http://baike.baidu.com/view/807.htm" \t "_blank)(Gateway)是一个网络连接到另一个网络的“关口”, 网关实质上是一个网络通向其他网络的IP[地址](http://baike.baidu.com/view/494802.htm" \t "_blank)。主要用于不同网络传输数据。 例如我们电脑设备上网,如果是接入到同一个交换机,在交换机内部传输数据是不需要经过网关的,但是如果两台设备不在一个交换机网络,则需要在本机配置网关,内网服务器的数据通过网关,网关把数据转发到其他的网络的网关,直至找到对方的主机网络,然后返回数据。 ### **MAC地址** 媒体访问控制(Media Access Control或者Medium Access Control,MAC),也即是物理地址、硬件地址,用来定义[网络设备](http://baike.baidu.com/view/1158081.htm" \t "_blank)的位置。 在[OSI模型](http://baike.baidu.com/view/571842.htm" \t "_blank)中,第三层[网络层](http://baike.baidu.com/view/239600.htm" \t "_blank)负责 [IP地址](http://baike.baidu.com/view/3930.htm" \t "_blank),第二层数据链路层则负责 MAC地址。因此一个主机会有一个MAC地址,而每个[网络位置](http://baike.baidu.com/view/1643855.htm" \t "_blank)会有一个专属于它的IP地址。 IP地址工作在OSI参考模型的第三层网络层。两者之间分工明确,默契合作,完成通信过程。IP地址专注于网络层,将数据包从一个网络转发到另外一个网络;而MAC地址则专注于数据链路层,将一个数据帧从一个节点传送到相同链路的另一个节点。 IP地址和MAC地址一般是成对出现。如果一台计算机要和网络中另一外计算机通信,那么这两台设备必须配置IP地址和MAC地址,而MAC地址是网卡出厂时设定的,这样配置的IP地址就和MAC地址形成了一种对应关系。 在数据通信时,IP地址负责表示计算机的网络层地址,网络层设备(如路由器)根据IP地址来进行操作;MAC地址负责表示计算机的数据链路层地址,数据链路层设备,根据MAC地址来进行操作。IP和MAC地址这种映射关系是通过[地址解析协议](http://baike.baidu.com/view/149421.htm" \t "_blank)(Address Resolution Protocol,ARP)来实现的。 ## Linux系统配置IP Linux操作系统安装完毕,那接下来如何让Linux操作系统能上外网呢?如下为Linux服务器配置IP的方法。 Linux服务器网卡默认配置文件在/etc/sysconfig/network\-scripts/下,命名的名称一般为:ifcfg\-eth0 ifcfg\-eth1 ,eth0表示第一块网卡,eth1表示第二块网卡,依次类推,例如DELL R720标配有4块千兆网卡,在系统显示的名称依次为:eth0、eth1、eth2、eth3。 修改服务器网卡IP地址命令为vi /etc/sysconfig/network\-scripts/ifcfg\-eth0 (注CentOS7网卡名ifcfg\-eno16777736)。vi命令打开网卡配置文件,默认为DHCP方式,配置如下: | DEVICE\=eth0BOOTPROTO\=dhcpHWADDR\=00:0c:29:52:c7:4eONBOOT\=yesTYPE\=Ethernet | | --- | vi命令打开网卡配置文件,修改BOOTPROTO为DHCP方式,同时添加IPADDR、NETMASK、GATEWAY信息如下: | DEVICE\=eth0BOOTPROTO\=staticHWADDR\=00:0c:29:52:c7:4eONBOOT\=yesTYPE\=EthernetIPADDR\=192\.168\.1\.103NETMASK\=255\.255\.255\.0GATEWAY\=192\.168\.1\.1 | | --- | 服务器网卡配置文件,详细参数如下: | DEVICE\=eth0 \#物理设备名ONBOOT\=yes \# \[yes\|no](重启网卡是否激活网卡设备)BOOTPROTO\=static \#\[none\|static\|bootp\|dhcp](不使用协议\|静态分配\|BOOTP协议\|DHCP协议)TYPE\=Ethernet \#网卡类型IPADDR\=192\.168\.1\.103 \#IP地址NETMASK\=255\.255\.255\.0 \#子网掩码GATEWAY\=192\.168\.1\.1 \#网关地址 | | --- | 服务器网卡配置完毕后,重启网卡服务:/etc/init.d/network restart 即可。 然后查看ip地址,命令为:ifconfig或者ip addr show 查看当前服务器所有网卡的IP地址。 CentOS 7 Linux中,如果没有ifconfig命令,可以用ip addr list/show查看,也可以安装ifconfig命令,需安装软件包net\-tools,命令如图3\-12所示: | yum install net\-tools \-y | | --- | ![](/media/202411/20241125143328684078.png) 图3\-12 YUM安装net\-tools工具 ## Linux系统配置DNS 如上网卡IP地址配置完毕,如果服务器需上外网,还需配置域名解析地址(Domain Name System,DNS),DNS主要用于将请求的域名转换为IP地址,DNS地址配置方法如下: 修改vi /etc/resolv.conf 文件,在文件中加入如下两条: | nameserver 202\.106\.0\.20nameserver 8\.8\.8\.8 | | --- | 如上分别表示主DNS于备DNS,DNS配置完毕后,无需重启网络服务,DNS是立即生效。 可以ping \-c 6 [www.baidu.com](http://www.baidu.com/) 查看返回结果,如果有IP返回,则表示服务器DNS配置正确,如图3\-13所示: ![](/media/202411/20241125143328690130.png) 图3\-13 ping命令返回值 ## Linux网卡名称命名 CentOS7服务器,默认网卡名为ifcfg\-eno16777736,如果我们想改成ifcfg\-eth0,使用如下步骤即可: 1. 编辑/etc/sysconfig/grub文件,命令为vi /etc/sysconfig/grub,在倒数第二行quiet后加入如下代码,并如图3\-14所示: | net.ifnames\=0 biosdevname\=0 | | --- | ![](/media/202411/20241125143328695253.png) 图3\-14 网卡配置ifnames设置 1. 执行命令grub2\-mkconfig \-o /boot/grub2/grub.cfg,生成新的grub.cfg文件,如图3\-15所示: | grub2\-mkconfig \-o /boot/grub2/grub.cfg | | --- | ![](/media/202411/20241125143328700487.png) 图3\-15 生成新的grub.cnf文件 1. 重命名网卡名称,执行命令mv ifcfg\-eno16777736 ifcfg\-eth0,修改ifcfg\-eth0文件中DEVICE\= eno16777736为DEVICE\= eth0,如图3\-16所示: ![](/media/202411/20241125143328705337.png)图3\-16 重命名网卡名称 1. 重启服务器,并验证网卡名称是否为eth0,Reboot完后,如图3\-17所示: ![](/media/202411/20241125143328710509.png)图3\-17 验证网卡设备名称 ## CentOS7密码重置 修改CentOS7 ROOT密码非常简单,只需登录系统,执行命令passwd回车即可,但是如果忘记ROOT,无法登录系统,该如何去重置ROOT用户的密码呢?如下为重置ROOT用户的密码的方法: 1. Reboot重启系统,系统启动进入欢迎界面,加载内核步骤时,按e,然后选中“CentOS Linux (3\.10\.0\-327\.e17\.x86\_64)7 (Core)”,如图3\-18所示: ![](/media/202411/20241125143328715535.png) 图3\-18 内核菜单选择界面 1. 继续按e进入编辑模式,找到ro crashkernel\=auto xxx项,将ro改成rw init\=/sysroot/bin/sh,如图3\-19所示: ![](/media/202411/20241125143328720906.png) 图3\-19 内核编辑界面 1. 修改为后如图3\-20所示: ![](/media/202411/20241125143328725774.png) 图3\-20 内核编辑界面 1. 按ctrl\+x按钮进入单用户模式,如图3\-21所示: ![](/media/202411/20241125143328730765.png) 图3\-21 进入系统单用户模式 1. 执行命令chroot /sysroot访问系统,并使用passwd修改root密码,如图3\-22所示: ![](/media/202411/20241125143328735689.png) 图3\-22 修改ROOT用户密码 1. 更新系统信息,touch /.autorelabel,执行命令touch /.autorelabel,在/目录下创建一个.autorelabel文件,如果该文件存在,系统在重启时就会对整个文件系统进行relabeling重新标记,可以理解为对文件进行底层权限的控制和标记,如果seLinux属于disabled关闭状态则不需要执行这条命令,如图3\-23所示: ![](/media/202411/20241125143328740654.png) 图3\-23 创建autorelabel文件 ## 远程管理Linux服务器 系统安装完毕后,可以通过远程工具来连接到Linux服务器,远程连接服务器管理的好处在于可以跨地区管理服务器,例如读者在北京,想管理的服务器在上海某IDC机房,通过远程管理后,不需要到IDC机房现场去操作,直接通过远程工具即可管理,与在现场的管理是一模一样。 远程管理Linux服务器要满足如下三个步骤: 1. 服务器配置IP地址,如果服务器在公网,需配置公网IP,如果服务器在内部局域网,可以直接配置内部私有IP即可; 2. 服务器安装SSHD软件服务并启动该服务,几乎所有的Linux服务器系统安装完毕均会自动安装并启动SSHD服务,SSHD服务监听22端口,关于SSHD服务、OpenSSH及SSH协议后面章节会讲解; 3. 在服务器中防火墙服务需要允许22端口对外开放,初学者可以临时关闭防火墙,CentOS6 Linux关闭防火墙的命令:service iptables stop,而CentOS7 Linux关闭防火墙的命令:systemctl stop firewalld.service。 常见的Linux远程管理工具包括:SecureCRT、Xshell、Putty、Xmanger等工具。目前主流的远程管理Linux服务器工具为SecureCRT,官网<https://www.vandyke.com> 下载并安装SecureCRT,打开工具,点击左上角quick connect快速连接,弹出界面如图3\-24所示,连接配置具体步骤如下: * 协议(P):选择SSH2 * 主机名(H):输入Linux服务器IP地址 * 端口(o): 22 * 防火墙(F):None * 用户名(U):root 单击下方的“连接”,会提示输入密码,输入root用户对应密码即可。 ![](/media/202411/20241125143328746076.png) 图3\-24 SecureCRT远程Linux服务器 通过SecureCRT远程连接Linux服务器之后,会发现如图3\-25所示界面,与服务器本地操作界面一样,在命令行可以执行命令,操作结果与在服务器现场操作是一样。 ![](/media/202411/20241125143328751543.png) 图3\-25 SecureCRT远程Linux服务器 ## Linux系统目录功能 通过以上知识的学习,读者已经能够独立安装并配置Linux服务器IP并远程连接,为了进一步学习Linux,需熟练掌握Linux系统各个目录的功能。 Linux主要树结构目录包括:/、/root、/home、/usr、/bin、/tmp、/sbin、/proc、/boot等,如图3\-26所示,为典型的Linux目录结构如下: ![](/media/202411/20241125143328757229.png) 图3\-26 Linux目录树形结构 Linux系统中常见目录功能如下: * / 根目录; * /bin 存放必要的命令; * /boot 存放内核以及启动所需的文件; * /[dev](http://www.baike.com/wiki/dev" \o "dev) 存放硬件设备文件; * /etc 存放系统配置文件; * /home 普通用户的宿主目录,用户数据存放在其主目录中; * /lib\|lib64 存放必要的运行库; * /mnt 存放临时的映射文件系统,通常用来挂载使用; * /proc 存放存储进程和系统信息; * /root 超级用户的主目录; * /sbin 存放系统管理程序; * /tmp 存放临时文件; * /usr 存放应用程序,命令程序文件、程序库、手册和其它文档; * /var 系统默认日志存放目录。 # Linux必备命令 Linux系统启动默认为字符界面,一般不会启动图形界面,所以对命令行的熟练程度能更加方便、高效的管理Linux系统。 本章向读者介绍Linux系统必备命令各项参数及功能场景,Linux常见命令包括:cd、ls、pwd、mkdir、rm、cp、mv、touch、cat、head、tail、chmod、vim等。 ## Linux命令集 初学者完成Linux系统安装以后,学习Linux操作系统必备的指令,基于Linux指令管理Linux操作系统,必备Linux指令有哪些? * 基础命令相关一: Cd、ls、pwd、help、man、if、for、while、case、select、read、test、ansible、iptables、firewall\-cmd、salt、mv、cut、uniq、sort、wc、source、sestatus、setenforce; * 基础命令相关二: Date、ntpdate、crontab、rsync、ssh、scp、nohup、sh、bash、hostname、hostnamectl、source、ulimit、export、env、set、at、dir、db\_load、diff、dmsetup、declare; * 用户权限相关: Useradd、userdel、usermod、groupadd、groupmod、groupdel、Chmod、chown、chgrp、umask、chattr、lsattr、id、who、whoami、last、su、sudo、w、chpasswd、chroot; * 文件管理相关: Touch、mkdir、rm、rmdi、vi、vim、cat、head、tail、less、more、find、sed、grep、awk、echo、ln、stat、file; * 软件资源管理: Rpm、yum、tar、unzip、zip、gzip、wget、curl、rz、sz、jar、apt\-get、bzip2、service、systemctl、make、cmake、chkconfig; * 系统资源管理: Fdisk、mount、umount、mkfs.ext4、fsck.ext4、parted、lvm、dd、du、df、top、iftop、free、w、uptime、iostat、vmstat、iotop、ps、netstat、lsof、ss、sar; * 网络管理相关: Ping、ifconfig、ip addr、ifup、ifdown、nmcli、route、nslookup、traceroute、dig、tcpdump、nmap、brctl、ethtool、setup、arp、ab、iperf; * Linux系统开关机: Init、reboot、shutdown、halt、poweroff、runlevel、login、logout、exit; ## cd命令详解 cd命令主要用于目录切换,例如:cd /home切换至/home目录,cd /root表示切换至/root目录 ;cd ../切换至上一级目录;cd ./切换至当前目录。 其中.和..可以理解为相对路径,例如cd ./test表示以当前目录为参考,表示相对于当前,而cd /home/test表示完整的路径,理解为绝对路径),如图4\-1所示: ![](/media/202411/20241125143328767058.png) 图4\-1 Linux cd命令操作 ## ls命令详解 ls命令主要用于浏览目录下的文件或者文件夹,使用方法参考:ls ./ 查看当前目录所有的文件和目录,ls \-a 查看所有的文件,包括隐藏文件,以.开头的文件,常用参数详解如下: | \-a, \-\-all 不隐藏任何以. 开始的项目;\-A, \-\-almost\-all 列出除. 及.. 以外的任何项目; \-\-author 与\-l 同时使用时列出每个文件的作者;\-b, \-\-escape 以八进制溢出序列表示不可打印的字符; \-\-block\-size\=大小 块以指定大小的字节为单位;\-B, \-\-ignore\-backups 不列出任何以"\~"字符结束的项目;\-d, \-\-directory 当遇到目录时列出目录本身而非目录内的文件;\-D, \-\-dired 产生适合Emacs 的dired 模式使用的结果;\-f 不进行排序,\-aU 选项生效,\-lst 选项失效;\-i, \-\-inode 显示每个文件的inode 号;\-I, \-\-ignore\=PATTERN 不显示任何符合指定shell PATTERN 的项目;\-k 即\-\-block\-size\=1K;\-l 使用较长格式列出信息;\-n, \-\-numeric\-uid\-gid 类似 \-l,但列出UID 及GID 号;\-N, \-\-literal 输出未经处理的项目名称 (如不特别处理控制字符) ;\-r, \-\-reverse 排序时保留顺序;\-R, \-\-recursive 递归显示子目录;\-s, \-\-size 以块数形式显示每个文件分配的尺寸;\-S 根据文件大小排序;\-t 根据修改时间排序;\-u 同\-lt 一起使用:按照访问时间排序并显示; 同\-l一起使用:显示访问时间并按文件名排序; 其他:按照访问时间排序;\-U 不进行排序;按照目录顺序列出项目;\-v 在文本中进行数字(版本)的自然排序。 | | --- | ## pwd命令详解 pwd命令主要用于显示或者查看当前所在的目录路径,如图4\-2所示: ![](/media/202411/20241125143328775423.png) 图4\-2 pwd命令查看当前目录 ## mkdir命令详解 mkdir命令主要用于创建目录,用法mkdir dirname,命令后接目录的名称,常用参数详解如下: | 用法:mkdir \[选项]... 目录;若指定目录不存在则创建目录;长选项必须使用的参数对于短选项时也是必需使用的;\-m, \-\-mode\=模式 设置权限模式(类似chmod),而不是rwxrwxrwx 减umask;\-p, \-\-parents 需要时创建目标目录的上层目录,但即使这些目录已存在也不当作错误处理;\-v, \-\-verbose 每次创建新目录都显示信息;\-Z, \-\-context\=CTX 将每个创建的目录的SELinux 安全环境设置为CTX;\-\-help 显示此帮助信息并退出;\-\-version 显示版本信息并退出。 | | --- | ## **rm**命令**详解** rm 命令主要用于删除文件或者目录,用法 rm –rf test.txt (\-r表示递归,\-f表示强制),常用参数详解如下: | 用法:rm \[选项]... 文件...删除 (unlink) 文件。\-f, \-\-force 强制删除。忽略不存在的文件,不提示确认;\-i 在删除前需要确认;\-I 在删除超过三个文件或者递归删除前要求确认。此选项比\-i 提示内容更少,但同样可以阻止大多数错误发生;\-r, \-R, \-\-recursive 递归删除目录及其内容;\-v, \-\-verbose 详细显示进行的步骤;\-\-help 显示此帮助信息并退出;\-\-version 显示版本信息并退出;默认时,rm 不会删除目录,使用\-\-recursive(\-r 或\-R)选项可删除每个给定的目录,以及其下所有的内容;要删除第一个字符为"\-"的文件 (例如"\-foo"),请使用以下方法之一:rm \-\- \-foorm ./\-foo | | --- | ## **cp命令详解** cp 命令主要用于拷贝文件,用法,cp old.txt /tmp/new.txt ,常用来备份,如果拷贝目录需要加\-r参数,常用参数详解如下: | 用法:cp \[选项]... \[\-T] 源文件 目标文件 或:cp \[选项]... 源文件... 目录 或:cp \[选项]... \-t 目录 源文件...将源文件复制至目标文件,或将多个源文件复制至目标目录。长选项必须使用的参数对于短选项时也是必需使用的。\-a, \-\-archive 等于\-dR \-\-preserve\=all; \-\-backup\[\=CONTROL 为每个已存在的目标文件创建备份;\-b 类似\-\-backup 但不接受参数; \-\-copy\-contents 在递归处理是复制特殊文件内容;\-d 等于\-\-no\-dereference \-\-preserve\=links;\-f, \-\-force 如果目标文件无法打开则将其移除并重试(当 \-n 选项; 存在时则不需再选此项);\-i, \-\-interactive 覆盖前询问(使前面的 \-n 选项失效);\-H 跟随源文件中的命令行符号链接;\-l, \-\-link 链接文件而不复制;\-L, \-\-dereference 总是跟随符号链接;\-n, \-\-no\-clobber 不要覆盖已存在的文件(使前面的 \-i 选项失效);\-P, \-\-no\-dereference 不跟随源文件中的符号链接;\-p 等于\-\-preserve\=模式,所有权,时间戳; \-\-preserve\[\=属性列表 保持指定的属性(默认:模式,所有权,时间戳),如果; 可能保持附加属性:环境、链接、xattr 等;\-c same as \-\-preserve\=context; \-\-sno\-preserve\=属性列表 不保留指定的文件属性; \-\-parents 复制前在目标目录创建来源文件路径中的所有目录;\-R, \-r, \-\-recursive 递归复制目录及其子目录内的所有内容。 | | --- | ## **mv命令详解** mv 命令主要用于重命名或者移动文件或者目录,用法, mv old.txt new.txt,常用参数详解如下: | 用法:mv \[选项]... \[\-T] 源文件 目标文件;或:mv \[选项]... 源文件... 目录;或:mv \[选项]... \-t 目录 源文件;将源文件重命名为目标文件,或将源文件移动至指定目录。长选项必须使用的参数对于短选项时也是必需使用的。 \-\-backup\[\=CONTROL] 为每个已存在的目标文件创建备份;\-b 类似\-\-backup 但不接受参数;\-f, \-\-force 覆盖前不询问;\-i, \-\-interactive 覆盖前询问;\-n, \-\-no\-clobber 不覆盖已存在文件,如果您指定了\-i、\-f、\-n 中的多个,仅最后一个生效; \-\-strip\-trailing\-slashes 去掉每个源文件参数尾部的斜线;\-S, \-\-suffix\=SUFFIX 替换常用的备份文件后缀;\-t, \-\-target\-directory\=DIRECTORY 将所有参数指定的源文件或目录; 移动至 指定目录;\-T, \-\-no\-target\-directory 将目标文件视作普通文件处理;\-u, \-\-update 只在源文件文件比目标文件新,或目标文件; 不存在时才进行移动;\-v, \-\-verbose 详细显示进行的步骤;\-\-help 显示此帮助信息并退出;\-\-version 显示版本信息并退出。 | | --- | ## **touch命令详解** touch 命令主要用于创建普通文件,用法为touch test.txt,如果文件存在,则表示修改当前文件时间,常用参数详解如下: | 用法:touch \[选项]... 文件...将每个文件的访问时间和修改时间改为当前时间;不存在的文件将会被创建为空文件,除非使用\-c 或\-h 选项;如果文件名为"\-"则特殊处理,更改与标准输出相关的文件的访问时间;长选项必须使用的参数对于短选项时也是必需使用的;\-a 只更改访问时间;\-c, \-\-no\-create 不创建任何文件;\-d, \-\-date\=字符串 使用指定字符串表示时间而非当前时间;\-f (忽略);\-h, \-\-no\-dereference 会影响符号链接本身,而非符号链接所指示的目的地; (当系统支持更改符号链接的所有者时,此选项才有用);\-m 只更改修改时间;\-r, \-\-reference\=文件 使用指定文件的时间属性而非当前时间;\-t STAMP 使用\[\[CC]YY]MMDDhhmm\[.ss] 格式的时间而非当前时间;\-\-time\=WORD 使用WORD 指定的时间:access、atime、use 都等于\-a; 选项的效果,而modify、mtime 等于\-m 选项的效果;\-\-help 显示此帮助信息并退出;\-\-version 显示版本信息并退出。 | | --- | ## **cat命令详解** cat 命令主要用于查看文件内容,用法 cat test.txt 可以查看test.txt内容,常用参数详解如下: | 用法:cat \[选项]... \[文件]...将\[文件]或标准输入组合输出到标准输出。\-A, \-\-show\-all 等于\-vET;\-b, \-\-number\-nonblank 对非空输出行编号;\-e 等于\-vE;\-E, \-\-show\-ends 在每行结束处显示"$";\-n, \-\-number 对输出的所有行编号;\-s, \-\-squeeze\-blank 不输出多行空行;\-t 与\-vT 等价;\-T, \-\-show\-tabs 将跳格字符显示为^I;\-u (被忽略);\-v, \-\-show\-nonprinting 使用^ 和M\- 引用,除了LFD和 TAB 之外;\-\-help 显示此帮助信息并退出;\-\-version 显示版本信息并退出。 | | --- | cat还有一种用法,cat …EOF…EOF,表示追加内容至/tmp/test.txt文件中,如下: | cat \>\>/tmp/test.txt\<\<EOFMy Name is JFEDU.NETI am From Bei jing.EOF | | --- | cat test.txt \|more 分页显示text内容,\|符号是管道符,用于把\|前的输出作为后面命令的输入。More命令常用于分页查看某文件或者内容。 ## **head命令详解** head命令主要用于查看文件内容,通常查看文件前10行,head \-10 /var/log/messages可以查看该文件前10行的内容,常用参数详解如下: | 用法:head \[选项]... \[文件]...将每个指定文件的头10 行显示到标准输出。如果指定了多于一个文件,在每一段输出前会给出文件名作为文件头。如果不指定文件,或者文件为"\-",则从标准输入读取数据,长选项必须使用的参数对于短选项时也是必需使用的;\-q, \-\-quiet, \-\-silent 不显示包含给定文件名的文件头;\-v, \-\-verbose 总是显示包含给定文件名的文件头;\-\-help 显示此帮助信息并退出;\-\-version 显示版本信息并退出;\-c, \-\-bytes\=\[\-]K 显示每个文件的前K 字节内容,如果附加"\-"参数,则除了每个文件的最后K字节数据外显示剩余全部内容;\-n, \-\-lines\=\[\-]K 显示每个文件的前K 行内容,如果附加"\-"参数,则除了每个文件的最后K 行外显示剩余全部内容。 | | --- | ## **tail命令详解** tail命令主要用于查看文件内容,通常查看末尾10行,tail –fn 100 /var/log/messages可以实时查看该文件末尾100行的内容,常用参数详解如下: | 用法:tail \[选项]... \[文件]...显示每个指定文件的最后10 行到标准输出。若指定了多于一个文件,程序会在每段输出的开始添加相应文件名作为头。如果不指定文件或文件为"\-" ,则从标准输入读取数据。长选项必须使用的参数对于短选项时也是必需使用的。\-n, \-\-lines\=K 输出的总行数,默认为10行;\-q, \-\-quiet, \-\-silent 不输出给出文件名的头;\-\-help 显示此帮助信息并退出;\-\-version 显示版本信息并退出;\-f, \-\-follow\[\={name\|descriptor}] 即时输出文件变化后追加的数据; \-f, \-\-follow 等于\-\-follow\=descriptor \-F 即\-\-follow\=name –retry\-c, \-\-bytes\=K 输出最后K字节;另外,使用\-c \+K 从每个文件的第K字节输出。 | | --- | ## **echo命令详解** echo命令主要用于打印字符或者回显,例如输入echo ok,会显示ok, echo ok \> test.txt 则会把ok字符覆盖test.txt内容。\>表示覆盖,原内容被覆盖,\>\>表示追加,原内容不变。 例如echo ok \>\> test.txt,表示向test.txt文件追加OK字符,不覆盖原文件里的内容,常用参数详解如下: | 使用\-e扩展参数选项时,与如下参数一起使用,有不同含义,例如:\\a 发出警告声\\b 删除前一个字符\\c 最后不加上换行符号;\\f 换行但光标仍旧停留在原来的位置;\\n 换行且光标移至行首;\\r 光标移至行首,但不换行;\\t 插入tab; \\v 与\\f相同;\\\\ 插入\\字符;\\033\[30m 黑色字 \\033\[0m\\033\[31m 红色字 \\033\[0m\\033\[32m 绿色字 \\033\[0m\\033\[33m 黄色字 \\033\[0m\\033\[34m 蓝色字 \\033\[0m\\033\[35m 紫色字 \\033\[0m\\033\[36m 天蓝字 \\033\[0m\\033\[37m 白色字 \\033\[0m\\033\[40;37m 黑底白字 \\033\[0m\\033\[41;37m 红底白字 \\033\[0m\\033\[42;37m 绿底白字 \\033\[0m\\033\[43;37m 黄底白字 \\033\[0m\\033\[44;37m 蓝底白字 \\033\[0m\\033\[45;37m 紫底白字 \\033\[0m\\033\[46;37m 天蓝底白字 \\033\[0m\\033\[47;30m 白底黑字 \\033\[0m | | --- | echo颜色打印扩展,auto\_lamp\_v2\.sh内容如下: | echo \-e "\\033\[36mPlease Select Install Menu follow:\\033\[0m"echo \-e "\\033\[32m1\)Install Apache Server\\033\[1m"echo "2\)Install MySQL Server"echo "3\)Install PHP Server"echo "4\)Configuration index.php and start LAMP server"echo \-e "\\033\[31mUsage: { /bin/sh $0 1\|2\|3\|4\|help}\\033\[0m" | | --- | 执行结果如图4\-3所示: ![](/media/202411/20241125143328793366.png)图4\-3 echo –e颜色打印 ## **df命令详解** df命令常用于磁盘分区查询,常用命令df –h,查看磁盘分区信息,常用参数详解如下: | 用法:df \[选项]... \[文件]...显示每个文件所在的文件系统的信息,默认是显示所有文件系统。长选项必须使用的参数对于短选项时也是必需使用的。\-a, \-\-all 显示所有文件系统的使用情况,包括虚拟文件系统;\-B, \-\-block\-size\=SIZE 使用字节大小块;\-h, \-\-human\-readable 以人们可读的形式显示大小;\-H, \-\-si 同\-h,但是强制使用1000而不是1024;\-i, \-\-inodes 显示inode 信息而非块使用量;\-k 即\-\-block\-size\=1K;\-l, \-\-local 只显示本机的文件系统; \-\-no\-sync 取得使用量数据前不进行同步动作(默认);\-P, \-\-portability 使用POSIX 兼容的输出格式; \-\-sync 取得使用量数据前先进行同步动作;\-t, \-\-type\=类型 只显示指定文件系统为指定类型的信息;\-T, \-\-print\-type 显示文件系统类型;\-x, \-\-exclude\-type\=类型 只显示文件系统不是指定类型信息;\-\-help 显示帮助信息并退出;\-\-version 显示版本信息并退出。 | | --- | ## mount命令详解 挂接命令(mount) 首先,介绍一下挂接(mount)命令的使用方法,mount命令参数非常多,这里主要讲一下今天我们要用到的。 命令格式: mount \[\-t vfstype] \[\-o options] device dir 其中: 1\.\-t vfstype 指定文件系统的类型,通常不必指定。mount 会自动选择正确的类型。常用类型有: 光盘或光盘镜像:iso9660 DOS fat16文件系统:msdos Windows 9x fat32文件系统:vfat Windows NT ntfs文件系统:ntfs Mount Windows文件网络共享:smbfs UNIX(LINUX) 文件网络共享:nfs 2\.\-o options 主要用来描述设备或档案的挂接方式。常用的参数有: loop:用来把一个文件当成硬盘分区挂接上系统 ro:采用只读方式挂接设备 rw:采用读写方式挂接设备 iocharset:指定访问文件系统所用字符集 3\.device 要挂接(mount)的设备。 4\.dir设备在系统上的挂接点(mount point)。 挂接光盘镜像文件 1、从光盘制作光盘镜像文件。将光盘放入光驱,执行下面的命令。 \#cp /dev/cdrom /home/sunky/mydisk.iso 或 \#dd if\=/dev/cdrom of\=/home/sunky/mydisk.iso 注:执行上面的任何一条命令都可将当前光驱里的光盘制作成光盘镜像文件/home/sunky/mydisk.iso 2、将文件和目录制作成光盘镜像文件,执行下面的命令。 \#mkisofs \-r \-J \-V mydisk \-o /home/sunky/mydisk.iso /home/sunky/ mydir 注:这条命令将/home/sunky/mydir目录下所有的目录和文件制作成光盘镜像文件/home/sunky/mydisk.iso,光盘卷标为:mydisk 3、光盘镜像文件的挂接(mount) \#mkdir /mnt/vcdrom 注:建立一个目录用来作挂接点(mount point) \#mount \-o loop \-t iso9660 /home/sunky/mydisk.iso /mnt/vcdrom 注:使用/mnt/vcdrom就可以访问盘镜像文件mydisk.iso里的所有文件了。 挂接移动硬盘 对linux系统而言,USB接口的移动硬盘是当作SCSI设备对待的。插入移动硬盘之前,应先用fdisk –l 或 more /proc/partitions查看系统的硬盘和硬盘分区情况。 \[root at pldyrouter /]\# fdisk \-l 接好移动硬盘后,再用fdisk –l 或 more /proc/partitions查看系统的硬盘和硬盘分区情况.应该可以发现多了一个SCSI硬盘/dev/sdc和它的两个磁盘分区/dev /sdc1?、/dev/sdc2,其中/dev/sdc5是/dev/sdc2分区的逻辑分区。我们可以使用下面的命令挂接/dev/sdc1和 /dev/sdc5。 \#mkdir \-p /mnt/usbhd1 \#mkdir \-p /mnt/usbhd2 注:建立目录用来作挂接点(mount point) \#mount \-t ntfs /dev/sdc1 /mnt/usbhd1 \#mount \-t vfat /dev/sdc5 /mnt/usbhd2 注:对ntfs格式的磁盘分区应使用\-t ntfs 参数,对fat32格式的磁盘分区应使用\-t vfat参数。若汉字文件名显示为乱码或不显示,可以使用下面的命令格式。 \#mount \-t ntfs \-o iocharset\=cp936 /dev/sdc1 /mnt/usbhd1 \#mount \-t vfat \-o iocharset\=cp936 /dev/sdc5 /mnt/usbhd2 linux系统下使用fdisk分区命令和mkfs文件系统创建命令可以将移动硬盘的分区制作成linux系统所特有的ext2、ext3格式。这样,在linux下使用就更方便了。使用下面的命令直接挂接即可。 \#mount /dev/sdc1 /mnt/usbhd1 挂接U盘 和USB接口的移动硬盘一样对linux系统而言U盘也是当作SCSI设备对待的。使用方法和移动硬盘完全一样。插入U盘之前,应先用fdisk –l 或 more /proc/partitions查看系统的硬盘和硬盘分区情况。 \[root at pldyrouter root]\# fdisk \-l 插入U盘后,再用fdisk –l 或 more /proc/partitions查看系统的硬盘和硬盘分区情况。 \[root at pldyrouter root]\# fdisk \-l 系统多了一个SCSI硬盘/dev/sdd和一个磁盘分区/dev/sdd1,/dev/sdd1就是我们要挂接的U盘。 \#mkdir \-p /mnt/usb 注:建立一个目录用来作挂接点(mount point) \#mount \-t vfat /dev/sdd1 /mnt/usb 注:现在可以通过/mnt/usb来访问U盘了, 若汉字文件名显示为乱码或不显示,可以使用下面的命令。 \#mount \-t vfat \-o iocharset\=cp936 /dev/sdd1 /mnt/usb 挂接Windows文件共享 Windows网络共享的核心是SMB/CIFS,在linux下要挂接(mount)windows的磁盘共享,就必须安装和使用samba 软件包。现在流行的linux发行版绝大多数已经包含了samba软件包,如果安装linux系统时未安装samba请首先安装samba。当然也可以到 http://www.samba.org网站下载......新的版本是3\.0\.10版。 当windows系统共享设置好以后,就可以在linux客户端挂接(mount)了,具体操作如下: \# mkdir –p /mnt/samba 注:建立一个目录用来作挂接点(mount point) \# mount \-t smbfs \-o username\=administrator,password\=pldy123 //10\.140\.133\.23/c$ /mnt/samba 注:administrator 和 pldy123 是ip地址为10\.140\.133\.23 windows计算机的一个用户名和密码,c$是这台计算机的一个磁盘共享 如此就可以在linux系统上通过/mnt/samba来访问windows系统磁盘上的文件了。以上操作在redhat as server 3、redflag server 4\.1、suse server 9以及windows NT 4\.0、windows 2000、windows xp、windows 2003环境下测试通过。 挂接UNIX系统NFS文件共享 类似于windows的网络共享,UNIX(Linux)系统也有自己的网络共享,那就是NFS(网络文件系统),下面我们就以SUN Solaris2\.8和REDHAT as server 3 为例简单介绍一下在linux下如何mount nfs网络共享。 在linux客户端挂接(mount)NFS磁盘共享之前,必须先配置好NFS服务端。 1、Solaris系统NFS服务端配置方法如下: (1\)修改 /etc/dfs/dfstab, 增加共享目录 share \-F nfs \-o rw /export/home/sunky (2\)启动nfs服务 \# /etc/init.d/nfs.server start (3\)NFS服务启动以后,也可以使用下面的命令增加新的共享 \# share /export/home/sunky1 \# share /export/home/sunky2 注:/export/home/sunky和/export/home/sunky1是准备共享的目录 2、linux系统NFS服务端配置方法如下: (1\)修改 /etc/exports,增加共享目录 /export/home/sunky 10\.140\.133\.23(rw) /export/home/sunky1 \*(rw) /export/home/sunky2 linux\-client(rw) 注:/export/home/目录下的sunky、sunky1、sunky2是准备共享的目录,10\.140\.133\.23、\*、 linux\-client是被允许挂接此共享linux客户机的IP地址或主机名。如果要使用主机名linux\-client必须在服务端主机 /etc/hosts文件里增加linux\-client主机ip定义。格式如下: 10\.140\.133\.23 linux\-client (2\)启动与停止NFS服务 /etc/rc.d/init.d/portmap start (在REDHAT中PORTMAP是默认启动的) /etc/rc.d/init.d/nfs start 启动NFS服务 /etc/rc.d/init.d/nfs stop 停止NFS服务 注:若修改/etc/export文件增加新的共享,应先停止NFS服务,再启动NFS服务方能使新增加的共享起作用。使用命令exportfs \-rv也可以达到同样的效果。 3、linux客户端挂接(mount)其他linux系统或UNIX系统的NFS共享 \# mkdir –p /mnt/nfs 注:建立一个目录用来作挂接点(mount point) \#mount \-t nfs \-o rw 10\.140\.133\.9:/export/home/sunky /mnt/nfs 注:这里我们假设10\.140\.133\.9是NFS服务端的主机IP地址,当然这里也可以使用主机名,但必须在本机/etc/hosts文件里增加服务端ip定义。/export/home/sunky为服务端共享的目录。 如此就可以在linux客户端通过/mnt/nfs来访问其它linux系统或UNIX系统以NFS方式共享出来的文件了。以上操作在 redhat as server 3、redflag server4\.1、suse server 9以及Solaris 7、Solaris 8、Solaris 9 for x86\&sparc环境下测试通过 linux加载光驱 (1)使用光驱前,要先mount一下:#mount /dev/cdrom /mnt/cdrom,然后您就可以进入/mnt/cdrom目录下读取光盘内容了; (2)当您想退出光盘时,须使用umout命令,否则光驱就会一直处于死锁状态:#umount /mnt/cdrom。 ## 本章小结 通过对本章内容的学习,读者对Linux操作系统引导有了进一步的理解,能够快速解决Linux启动过程中的故障,同时学习了CentOS6与CentOS7系统的区别,理解了TCP/IP协议及IP地址相关基础内容。 学会了Linux初学必备的16个Linux命令,能使用命令熟练的操作Linux系统,通过对VIM编辑器的深入学习,能够熟练编辑、修改系统中任意的文本及配置文件。对Linux系统的认识及操作有了更进一步的飞跃。 ## 同步作业 1. 修改密码的命令默认为passwd,需要按Enter键两次,如何一条命令快速修改密码呢? 2. 企业服务器,某天发现系统访问很慢,需要查看系统内核日志,请写出查看系统内核日志的命令; 3. 如果在Linux系统/tmp/目录,快速创建1000个目录,目录名为:jfedu1、jfedu2、jfedu依次类推,不断增加; 4. Httpd.conf配置文件中存在很多以\#号开头的行,请使用vim相关指令删除\#开头的行; # Linux用户及权限管理 Linux是一个多用户的操作系统,引入用户,可以更加方便管理Linux服务器,系统默认需要以一个用户的身份登入,而且在系统上启动进程也需要以一个用户身份去运行,用户可以限制某些进程对特定资源的权限控制。 本章向读者介绍Linux系统如何管理创建、删除、修改用户角色、用户权限配置、组权限配置及特殊权限深入剖析。 ## Linux用户及组 Linux操作系统对多用户的管理,是非常繁琐的,所以用组的概念来管理用户就变得简单,每个用户可以在一个独立的组,每个组也可以有零个用户或者多个用户。 Linux系统用户是根据用户ID来识别的,从默认ID编号从0开始,但是为了和老式系统兼容,用户ID限制在60000以下,Linux用户分总共分为三种,分别如下: * root用户 (ID 0) * 系统用户 (ID 1\-499) * 普通用户 (ID 500以上) Linux系统中的每个文件或者文件夹,都有一个所属用户及所属组,使用id命令可以显示当前用户的信息,使用passwd命令可以修改当前用户密码。Linux操作系统用户的特点如下: * 每个用户拥有一个UserID,操作系统实际读取的是UID,而非用户名; * 每个用户属于一个主组,属于一个或多个附属组,一个用户最多有31个附属组; * 每个组拥有一个GroupID; * 每个进程以一个用户身份运行,该用户可对进程拥有资源控制权限; * 每个可登陆用户拥有一个指定的Shell环境。 ## Linux用户管理 Linux用户在操作系统可以进行日常管理和维护,涉及到的相关配置文件如下: * /etc/passwd 保存用户信息 * /etc/shdaow 保存用户密码(以加密形式保存) * /etc/group 保存组信息 * /etc/login.defs 用户属性限制,密码过期时间,密码最大长度等限制 * /etc/default/useradd 显示或更改默认的useradd配置文件 如需创建新用户,可以使用命令useradd,执行命令useradd jfedu1即可创建jfedu1用户,同时会创建一个同名的组jfedu1,默认该用户属于jfedu1主组。 Useradd jfedu1命令默认创建用户jfedu1,会根据如下步骤进行操作: * 读取/etc/default/useradd,根据配置文件执行创建操作; * 在/etc/passwd文件中添加用户信息; * 如使用passwd命令创建密码,密码会被加密保存在/etc/shdaow中; * 为jfedu1创建家目录:/home/jfedu1; * 将/etc/skel中的.bash开头的文件复制至/home/jfedu1家目录; * 创建与用户名相同的jfedu1组,jfedu1用户默认属于jfeud1同名组; * Jfedu1组信息保存在/etc/group配置文件中。 在使用useradd命令创建用户时,可以支持如下参数: | 用法:useradd \[选项] 登录useradd \-Duseradd \-D \[选项]选项:\-b, \-\-base\-dir BASE\_DIR 指定新账户的家目录;\-c, \-\-comment COMMENT 新账户的 GECOS 字段;\-d, \-\-home\-dir HOME\_DIR 新账户的主目录;\-D, \-\-defaults 显示或更改默认的 useradd 配置;\-e, \-\-expiredate EXPIRE\_DATE 新账户的过期日期;\-f, \-\-inactive INACTIVE 新账户的密码不活动期;\-g, \-\-gid GROUP 新账户主组的名称或ID;\-G, \-\-groups GROUPS 新账户的附加组列表;\-h, \-\-help 显示此帮助信息并推出;\-k, \-\-skel SKEL\_DIR 使用此目录作为骨架目录;\-K, \-\-key KEY\=VALUE 不使用 /etc/login.defs 中的默认值;\-l, \-\-no\-log\-init 不要将此用户添加到最近登录和登录失败数据库;\-m, \-\-create\-home 创建用户的主目录;\-M, \-\-no\-create\-home 不创建用户的主目录;\-N, \-\-no\-user\-group 不创建同名的组;\-o, \-\-non\-unique 允许使用重复的 UID 创建用户;\-p, \-\-password PASSWORD 加密后的新账户密码;\-r, \-\-system 创建一个系统账户;\-R, \-\-root CHROOT\_DIR chroot 到的目录;\-s, \-\-shell SHELL 新账户的登录 shell;\-u, \-\-uid UID 新账户的用户 ID;\-U, \-\-user\-group 创建与用户同名的组;\-Z, \-\-selinux\-user SEUSER 为SELinux 用户映射使用指定 SEUSER。 | | --- | Useradd案例演示: 1. 新建jfedu用户,并加入到jfedu1,jfedu2附属组; | useradd \-G jfedu1,jfedu2 jfedu | | --- | 1. 新建jfedu3用户,并指定新的家目录,同时指定其登陆的SHELL; | useradd jfedu3 \-d /tmp/ \-s /bin/bash | | --- | ## Linux组管理 所有的Linux或者Windows系统都有组的概念,通过组可以更加方便的管理用户,组的概念应用于各行行业,例如企业会使用部门、职能或地理区域的分类方式来管理成员,映射在Linux系统,同样可以创建用户,并用组的概念对其管理。 Linux组有如下特点: * 每个组有一个组ID; * 组信息保存在/etc/group中; * 每个用户至少拥有一个主组,同时还可以拥有31个附属组。 通过命令groupadd、groupdel、groupmod来对组进行管理,详细参数使用如下: | groupadd用法\-f, \-\-force 如果组已经存在则成功退出; 并且如果 GID 已经存在则取消 –g;\-g, \-\-gid GID 为新组使用 GID;\-h, \-\-help 显示此帮助信息并推出;\-K, \-\-key KEY\=VALUE 不使用 /etc/login.defs 中的默认值;\-o, \-\-non\-unique 允许创建有重复 GID 的组;\-p, \-\-password PASSWORD 为新组使用此加密过的密码;\-r, \-\-system 创建一个系统账户;groupmod用法 \-g, \-\-gid GID 将组 ID 改为 GID;\-h, \-\-help 显示此帮助信息并推出;\-n, \-\-new\-name NEW\_GROUP 改名为 NEW\_GROUP;\-o, \-\-non\-unique 允许使用重复的 GID;\-p, \-\-password PASSWORD 将密码更改为(加密过的) PASSWORD;groupdel用法groupdel jfedu 删除jfedu组; | | --- | Groupadd案例演示: 1. groupadd创建jingfeng组 | groupadd jingfeng | | --- | 1. groupadd创建jingfeng组,并指定GID为1000; | groupadd \-g 1000 jingfeng | | --- | 1. groupadd创建一个system组,名为jingfeng组 | groupadd \-r jingfeng | | --- | Groupmod案例演示: 1. groupmod修改组名称,将jingfeng组名,改成jingfeng1; | groupmod \-n jingfeng1 jingfeng | | --- | 1. groupmod修改组GID号,将原jingfeng1组gid改成gid 1000; | groupmod –g 1000 jingfeng1 | | --- | ## Linux用户及组案例 Useradd主要用于新建用户,而用户新建完毕,可以使用usermod来修改用户及组的属性,如下为usermod详细参数: | 用法:usermod \[选项] 登录选项:\-c, \-\-comment 注释 GECOS 字段的新值;\-d, \-\-home HOME\_DIR 用户的新主目录;\-e, \-\-expiredate EXPIRE\_DATE 设定帐户过期的日期为 EXPIRE\_DATE;\-f, \-\-inactive INACTIVE 过期 INACTIVE 天数后,设定密码为失效状态;\-g, \-\-gid GROUP 强制使用 GROUP 为新主组;\-G, \-\-groups GROUPS 新的附加组列表 GROUPS;\-a, \-\-append GROUP 将用户追加至上边 \-G 中提到的附加组中, 并不从其它组中删除此用户;\-h, \-\-help 显示此帮助信息并推出;\-l, \-\-login LOGIN 新的登录名称;\-L, \-\-lock 锁定用户帐号;\-m, \-\-move\-home 将家目录内容移至新位置 (仅于 \-d 一起使用);\-o, \-\-non\-unique 允许使用重复的(非唯一的) UID;\-p, \-\-password PASSWORD 将加密过的密码 (PASSWORD) 设为新密码;\-R, \-\-root CHROOT\_DIR chroot 到的目录;\-s, \-\-shell SHELL 该用户帐号的新登录shell环境;\-u, \-\-uid UID 用户帐号的新UID;\-U, \-\-unlock 解锁用户帐号;\-Z, \-\-selinux\-user SEUSER 用户账户的新SELinux 用户映射。 | | --- | Usermod案例演示: 1. 将jfedu用户属组修改为jfedu1,jfedu2附属组; | usermod \-G jfedu1,jfedu2 jfedu | | --- | 1. 将jfedu用户加入到jfedu3,jfedu4附属组,\-a为添加新组,原组保留; | usermod –a \-G jfedu3,jfedu4 jfedu | | --- | 1. 修改jfedu用户,并指定新的家目录,同时指定其登陆的SHELL; | usermod \-d /tmp/ \-s /bin/sh jfedu | | --- | 1. 将jfedu用户名修改为jfedu1; | usermod \-l jfedu1 jfedu | | --- | 1. 锁定jfedu1用户及解锁jfedu1用户方法; | usermod –L jfedu1usermod \-U jfedu1 | | --- | Userdel案例演示: 使用userdel可以删除指定用户及其用户的邮箱目录或者Selinux映射环境: * userdel jfedu1 保留用户的家目录; * userdel \-r jfedu1 删除用户及用户家目录,用户login系统无法删除; * userdel \-rf jfedu1 强制删除用户及该用户家目录,不论是否login系统。 ## Linux权限管理 Linux权限是操作系统用来限制对资源访问的机制,权限一般分为读、写、执行。系统中每个文件都拥有特定的权限、所属用户及所属组,通过这样的机制来限制哪些用户或用户组可以对特定文件进行相应的操作。 Linux每个进程都是以某个用户身份运行,进程的权限与该用户的权限一样,用户的权限越大,则进程拥有的权限就越大。 Lnux中有的文件及文件夹都有至少权限三种权限,常见的权限如表5\-1所示: | **权限** | **对文件的影响** | **对目录的影响** | | --- | --- | --- | | r(读取) | 可读取文件内容 | 可列出目录内容 | | w(写入) | 可修改文件内容 | 可在目录中创建删除内容 | | x(执行) | 可作为命令执行 | 可访问目录内容 | | 目录必须拥有x权限,否则无法查看其内容 | | | 表5\-1 Linux 文件及文件及权限 Linux权限授权,默认是授权给三种角色,分别是user、group、other,Linux权限与用户之间的关联如下: * U代表User,G代表Group,O代表Other; * 每个文件的权限基于UGO进行设置; * 权限三位一组(rwx),同时需授权给三种角色,UGO; * 每个文件拥有一个所属用户和所属组,对应UGO,不属于该文件所属用户或所属组使用O来表示; 在Linux系统中,可以通过ls –l查看jfedu.net目录的详细属性,如图5\-1所示: | drwxrwxr\-x 2 jfedu1 jfedu1 4096 Dec 10 01:36 jfedu.net | | --- | ![](/media/202411/20241125143328816341.png)图5\-1 Linux jfedu.net目录详细属性 jfedu.net目录属性参数详解如下: * d 表示目录,同一位置如果为\-则表示普通文件; * rwxrwxr\-x 表示三种角色的权限,每三位为一种角色,依次为u,g,o权限,如上则表示user的权限为rwx,group的权限为rwx,other的权限为r\-x; * 2表示文件夹的链接数量,可理解为该目录下子目录的数量; * 从左到右,第一个jfedu1表示该用户名,第二个jfedu1则为组名,其他人角色默认不显示; * 4096表示该文件夹占据的字节数; * Dec 10 01:36 表示文件创建或者修改的时间; * Jfedu.net 为目录的名,或者文件名。 ## Chown属主及属组 修改某个用户、组对文件夹的属主及属组,用命令chown实现,案例演示如下: 1. 修改jfedu.net文件夹所属的用户为root,其中\-R参数表示递归处理所有的文件及子目录。 | chown \-R root jfedu.net | | --- | 1. 修改jfedu.net文件夹所属的组为root。 | chown \-R :root jfedu.net或者chgrp –R root jfedu.net | | --- | 1. 修改jfedu.net文件夹所属的用户为root,组也为root。 | chown \-R root:root jfedu.net | | --- | ## Chmod用户及组权限 修改某个用户、组对文件夹的权限,用命令chmod实现,其中以代指ugo,、\-、\=代表加入、删除和等于对应权限,具体案例如下: 1. 授予用户对jfedu.net目录拥有rwx权限 | chmod –R u\+rwx jfedu.net | | --- | 1. 授予组对jfedu.net目录拥有rwx权限 | chmod –R g\+rwx jfedu.net | | --- | 1. 授予用户、组、其他人对jfedu.net目录拥有rwx权限 | chmod –R u\+rwx,g\+rwx,o\+rwx jfedu.net | | --- | 1. 撤销用户对jfedu.net目录拥有w权限 | chmod –R u\-w jfedu.net | | --- | 1. 撤销用户、组、其他人对jfedu.net目录拥有x权限 | chmod –R u\-x,g\-x,o\-x jfedu.net | | --- | 1. 授予用户、组、其他人对jfedu.net目录只有rx权限 | chmod –R u\=rx,g\=rx,o\=rx jfedu.net | | --- | ## Chmod二进制权限 Linux权限默认使用rwx来表示,为了更简化在系统中对权限进行配置和修改,Linux权限引入二进制表示方法,如下代码: | Linux权限可以将rwx用二进制来表示,其中有权限用1表示,没有权限用0表示;Linux权限用二进制显示如下:rwx\=111r\-x\=101rw\-\=110r\-\-\=100依次类推,转化为十进制,对应十进制结果显示如下:rwx\=111\=4\+2\+1\=7r\-x\=101\=4\+0\+1\=5rw\-\=110\=4\+4\+0\=6r\-\-\=100\=4\+0\+0\=4得出结论,用r\=4,w\=2,x\=1来表示权限。 | | --- | 使用二进制方式来修改权限案例演示如下,其中默认jfedu.net目录权限为755: 1. 授予用户对jfedu.net目录拥有rwx权限 | chmod –R 755 jfedu.net | | --- | 1. 授予组对jfedu.net目录拥有rwx权限 | chmod –R 775 jfedu.net | | --- | 1. 授予用户、组、其他人对jfedu.net目录拥有rwx权限 | chmod –R 777 jfedu.net | | --- | 1. 撤销用户对jfedu.net目录拥有w权限 | chmod –R 555 jfedu.net | | --- | 1. 撤销用户、组、其他人对jfedu.net目录拥有x权限 | chmod –R 644 jfedu.net | | --- | 1. 授予用户、组、其他人对jfedu.net目录只有rx权限 | chmod –R 555 jfedu.net | | --- | ## Linux特殊权限及掩码 Linux权限除了常见的rwx权限之外,还有很多特殊的权限,细心的读者会发现,为什么Linux目录默认权限755,而文件默认权限为644呢,这是因为Linux权限掩码umask导致。 每个Linux终端都拥有一个umask属性,umask熟悉可以用来确定新建文件、目录的默认权限,默认系统权限掩码为022。在系统中每创建一个文件或者目录,文件默认权限是666,而目录权限则为777,权限对外开放比较大,所以设置了权限掩码之后,默认的文件和目录权限减去umask值才是真实的文件和目录的权限。 * 对应目录权限为:777\-022\=755; * 对应文件权限为:666\-022\=644; * 执行umask命令可以查看当前默认的掩码,umask \-S 023可以设置默认的权限掩码。 在Linux权限中,除了普通权限外,还有如下表5\-2所示,三个特殊权限: | 权限 | 对文件的影响 | 对目录的影响 | | --- | --- | --- | | Suid | 以文件的所属用户身份执行,而非执行文件的用户 | 无 | | sgid | 以文件所属组身份去执行 | 在该目录中创建任意新文件的所属组与该目录的所属组相同 | | sticky | 无 | 对目录拥有写入权限的用户仅可以删除其拥有的文件,无法删除其他用户所拥有的文件 | 表5\-2 Linux三种特殊权限 Linux中设置特殊权限方法如下: * 设置suid: chmod u\+s jfedu.net * 设置sgid: chmod g\+s jfedu.net * 设置sticky: chmod o\+t jfedu.net 特殊权限与设置普通权限一样,可以使用数字方式表示: * SUID \= 4 * SGID \= 2 * Sticky \= 1 可以通过chmod 4755 jfedu.net对该目录授予特殊权限为s的权限,Linux系统中s权限的应用常见包括:su、passwd、sudo,如图5\-2所示: ![](/media/202411/20241125143328827096.png)图5\-2 Linux特殊权限s应用 ## 本章小结 通过对本章内容的学习,读者可以了解Linux用户和组的系统知识,同时账号Linux用户和组在系统中各种案例操作。读者可以熟练新建用户、删除用户、修改用户属性、添加组、修改组以及删除组。 ## 同步作业 1. 某互联网公司职能及员工信息表,如表5\-3所示,请在Linux系统中创建相关员工,并把员工加入到部门。 | **部门** | **职能** | | --- | --- | | 讲师部(teacher) | jfwu,jfcai | | 市场部(market) | jfxin,jfqi | | 管理部(manage) | jfedu,jfteach | | 运维部(operater) | jfhao,jfyang | 表5\-3 Linux用户和组管理 1. 批量创建1\-100个用户,用户名以jfedu开头,后面紧跟1,2,3,例如jfedu1,jfedu2,jfedu3。 2. 使用useradd创建用户并通过\-p参数指定密码,设定完密码需通过系统能正常验证并登陆。 3. 小王公司服务器,使用Root用户通过SecureCRT远程登陆后,如图5\-3所示,发现登录终端变成bash\-4\.1\#,是什么原因导致?以及如何修复为正常的登录SHELL环境,请写出答案。 ![](/media/202411/20241125143328833218.png)图5\-3 SecureCRT登录Linux系统界面 # Linux软件包企业实战 通过前几章的学习,读者掌握了Linux系统基本命令、用户及权限等知识,Linux整个体系的关键不在于系统本身,而是在于可以基于Linux系统去安装和配置企业中相关的软件、数据及应用程序,所以对软件的维护是运维工程师的重中之重。 本章向读者介绍Linux系统软件的安装、卸载、配置、维护以及如何构建企业本地YUM光盘源及HTTP本地源。 ## RPM软件包管理 Linux软件包管理大致可分为二进制包、源码包,使用的工具也各不相同。Linux常见软件包分为两种,分别是源代码包(Source Code)、二进制包(Binary Code),源代码包是没有经过编译的包,需要经过GCC、C\+\+编译器环境编译才能运行,二进制包无需编译,可以直接安装使用。 通常而言,可以通过后缀简单区别源码包和二进制包,例如.tar.gz、.zip、.rar结尾的包通常称之为源码包,以.rpm结尾的软件包称之为二进制包。真正区分是否为源码还是二进制还得基于代码里面的文件来判断,例如包含.h、.c、.cpp、.cc等结尾的源码文件,称之为源码包,而代码代码里面存在bin可执行文件,称之为二进制包。 CentOS操作系统中有一款默认软件管理的工具,红帽包管理工具(Red Hat Package Manager,RPM)。 使用RPM工具可以对软件包实现快速安装、管理及维护。RPM管理工具适用的操作系统包括:CentOS,RedHat,Fedora,SUSE等,RPM工具常用于管理.rpm后缀结尾的软件包。 RPM软件包命令规则详解如下: | RPM包命名格式为:name\-version.rpmname\-version\-noarch.rpmname\-version\-arch.src.rpm如下软件包格式:epel\-release\-6\-8\.noarch.rpmperl\-Pod\-Plainer\-1\.03\-1\.el6\.noarch.rpmyasm\-1\.2\.0\-4\.el7\.x86\_64\.rpmRPM包格式解析如下:* name 软件名称,例如yasm、perl\-pod\-Plainer; * version 版本号,1\.2\.0通用格式:“主版本号.次版本号.修正号”; 4表示是发布版本号,该RPM包是第几次编译生成的;* arch 适用的硬件平台,RPM支持的平台有:i386、i586、i686、x86\_64、sparc、alpha等。 * .rpm 后缀包表示编译好的二进制包,可用rpm命令直接安装; * .src.rpm 源代码包,源码编译生成.rpm格式的RPM包方可使用; * el\* 软件包发行版本,el6表示该软件包适用于RHEL 6\.x/CentOS 6\.x; * devel: 开发包; * noarch: 软件包可以在任何平台上安装。 | | --- | RPM工具命令详解如下: | RPM 选项 PACKAGE\_NAME\-a, \-\-all 查询所有已安装软件包;\-q,\-\-query 表示询问用户,输出信息;\-l, \-\-list 打印软件包的列表;\-f, \-\-file FILE 查询包含 FILE 的软件包;\-i, \-\-info 显示软件包信息,包括名称,版本,描述;\-v, \-\-verbose 打印输出详细信息;\-U, \-\-upgrade 升级RPM软件包;\-h,\-\-hash 软件安装,可以打印安装进度条;\-\-last 列出软件包时,以安装时间排序,最新的在上面;\-e, \-\-erase 卸载rpm软件包\-\-force 表示强制,强制安装或者卸载;\-\-nodeps RPM包不依赖\-l, \-\-list 列出软件包中的文件;\-\-provides 列出软件包提供的特性;\-R, \-\-requires 列出软件包依赖的其他软件包;\-\-scripts 列出软件包自定义的小程序。 | | --- | RPM企业案例演示: | rpm \-q httpd 检查httpd包是否安装;rpm \-ql httpd 查看软件安装的路径;rpm \-qi httpd 查看软件安装的版本信息;rpm \-e httpd 卸载httpd软件;rpm \-e \-\-nodeps httpd 强制卸载httpd;rpm \-qa\|grep httpd 检查httpd相关的软件包是否安装。rpm \-ivh httpd\-2\.4\.10\-el7\.x86\_64\.rpm 安装httpd软件包;rpm \-Uvh httpd\-2\.4\.10\-el7\.x86\_64\.rpm 升级httpd软件;rpm \-ivh \-\-nodeps httpd\-2\.4\.10\-el7\.x86\_64\.rpm 不依赖其他软件包; | | --- | ## Tar软件包管理 Linux操作系统除了使用RPM管理工具对软件包管理之外,还可以通过tar、zip、jar等工具进行源码包的管理。 ### Tar命令参数详解 | \-A, \-\-catenate, \-\-concatenate 将存档与已有的存档合并\-c, \-\-create 建立新的存档\-d, \-\-diff, \-\-compare 比较存档与当前文件的不同之处\-\-delete 从存档中删除\-r, \-\-append 附加到存档结尾\-t, \-\-list 列出存档中文件的目录\-u, \-\-update 仅将较新的文件附加到存档中\-x, \-\-extract, \-\-get 解压文件\-j, \-\-bzip2, \-\-bunzip2 有bz2属性的软件包;\-z, \-\-gzip, \-\-ungzip 有gz属性的软件包;\-b, \-\-block\-size N 指定块大小为 Nx512 字节(缺省时 N\=20\);\-B, \-\-read\-full\-blocks 读取时重组块;\-C, \-\-directory DIR 指定新的目录;\-\-checkpoint 读取存档时显示目录名;\-f, \-\-file \[HOSTNAME:]F 指定存档或设备,后接文件名称;\-\-force\-local 强制使用本地存档,即使存在克隆;\-G, \-\-incremental 建立老 GNU 格式的备份;\-g, \-\-listed\-incremental 建立新 GNU 格式的备份;\-h, \-\-dereference 不转储动态链接,转储动态链接指向的文件;\-i, \-\-ignore\-zeros 忽略存档中的 0 字节块(通常意味着文件结束);\-\-ignore\-failed\-read 在不可读文件中作 0 标记后再退出;\-k, \-\-keep\-old\-files 保存现有文件;从存档中展开时不进行覆盖;\-K, \-\-starting\-file F 从存档文件 F 开始;\-l, \-\-one\-file\-system 在本地文件系统中创建存档;\-L, \-\-tape\-length N 在写入 N\*1024 个字节后暂停,等待更换磁盘;\-m, \-\-modification\-time 当从一个档案中恢复文件时,不使用新的时间标签;\-M, \-\-multi\-volume 建立多卷存档,以便在几个磁盘中存放;\-O, \-\-to\-stdout 将文件展开到标准输出;\-P, \-\-absolute\-paths 不要从文件名中去除 '/';\-v, \-\-verbose 详细显示处理的文件;\-\-version 显示tar 程序的版本号;\-\-exclude FILE不把指定文件包含在内;\-X, \-\-exclude\-from FILE 从指定文件中读入不想包含的文件的列表。 | | --- | ### TAR企业案例演示 | tar \-cvf jfedu.tar.gz jfedu 打包jfedu文件或者目录,打包后名称jfedu.tar.gz;tar \-tf jfedu.tar.gz 查看jfedu.tar.gz包中内容;tar \-rf jfedu.tar.gz jfedu.txt 将jfedu.txt文件追加到jfedu.tar.gz中tar \-xvf jfedu.tar.gz 解压jfedu.tar.gz程序包;tar \-czvf jfedu.tar.gz jfedu 使用gzip格式打包并压缩jfedu目录;tar \-cjvf jfedu.tar.bz2 jfedu 使用bzip2格式打包并压缩jfedu目录;tar \-czf jfedu.tar.gz \* \-X list.txt 使用gzip格式打包并压当前目录所有文件,排除list.txt中记录的文件;tar \-czf jfedu.tar.gz \* \-\-exclude\=zabbix\-3\.2\.4\.tar.gz \-\-exclude\=nginx\-1\.12\.0\.tar.gz 使用gzip格式打包并压当前目录所有文件及目录,排除zabbix\-3\.2\.4\.tar.gz和nginx\-1\.12\.0\.tar.gz软件包。 | | --- | ### TAR实现Linux操作系统备份 Tar命令工具除了用于日常打包、解压源码包或者压缩包之外,最大的亮点是还可以用于Linux操作系统文件及目录的备份,使用tar \-g可以基于GNU 格式的增量备份,备份原理是基于检查目录或者文件的atime、mtime、ctime属性是否被修改。文件及目录时间属性详解如下: * 文件被访问的时间(Access time,atime); * 文件内容被改变的时间(Modified time,mtime); * 文件写入、权限更改的时间(Change time,ctime)。 总结,更改文件内容mtime和ctime都会改变,但ctime可以在mtime未发生变化时被更改,例如修改文件权限,文件mtime时间不变,而ctime时间改变。TAR增量备份案例演示步骤如下: 1. /root目录创建jingfeng文件夹,同时在jingfeng文件夹中,新建jf1\.txt,jf2\.txt文件,如图6\-1所示: ![](/media/202411/20241125143328849283.png)图6\-1 创建jingfeng目录及文件 1. 使用tar命令第一次完整备份jingfeng文件夹中的内容,\-g指定快照snapshot文件,第一次没有该文件则会自动创建,如图6\-2所示: | cd /root/jingfeng/tar \-g /data/backup/snapshot \-czvf /data/backup/2022jingfeng.tar.gz | | --- | ![](/media/202411/20241125143328854768.png) 图6\-2 tar备份jingfeng目录中文件 1. 使用tar命令第一次完整备份jingfeng文件夹中之后,会生成快照文件:/data/backup/snapshot,后期增量备份会以snapshot文件为参考,在jingfeng文件夹中再创建jf3\.txt jf4\.txt文件,然后通过tar命令增量备份jingfeng目录所有内容,如图6\-3所示: | cd /root/jingfeng/touch jf3\.txt jf4\.txttar \-g /data/backup/snapshot \-czvf /data/backup/2022jingfeng\_add1\.tar.gz \* | | --- | ![](/media/202411/20241125143328860192.png) 图6\-3 tar增量备份jingfeng目录中文件 如上图6\-3所示,增量备份时,需\-g指定第一次完整备份的快照snapshot文件,同时增量打包的文件名不能跟第一次备份后的文件名重复,通过tar –tf可以查看打包后的文件内容。 ### Shell\+TAR实现增量备份 企业中日常备份的数据包括/boot、/etc、/root、/data目录等,备份的策略参考:每周1\-6执行增量备份,每周日执行全备份。同时在企业中备份操作系统数据均使用Shell脚本完成,此处auto\_backup\_system.sh脚本供参考,后面章节会系统讲解Shell脚本,脚本内容如下: | \#!/bin/bash\#Automatic Backup Linux System Files\#By Author www.jfedu.net\#Define VariablesSOURCE\_DIR\=( $\*)TARGET\_DIR\=/data/backup/YEAR\=\`date \+%Y\`MONTH\=\`date \+%m\`DAY\=\`date \+%d\`WEEK\=\`date \+%u\`FILES\=system\_backup.tgzCODE\=$?if \[ \-z $SOURCE\_DIR ];then echo \-e "Please Enter a File or Directory You Need to Backup:\\n\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\\nExample $0 /boot /etc ......" exitfi\#Determine Whether the Target Directory Existsif \[ ! \-d $TARGET\_DIR/$YEAR/$MONTH/$DAY ];then mkdir \-p $TARGET\_DIR/$YEAR/$MONTH/$DAY echo "This $TARGET\_DIR Created Successfully !"fi\#EXEC Full\_Backup Function CommandFull\_Backup(){if \[ "$WEEK" \-eq "7" ];then rm \-rf $TARGET\_DIR/snapshot cd $TARGET\_DIR/$YEAR/$MONTH/$DAY ;tar \-g $TARGET\_DIR/snapshot \-czvf $FILES \`echo ${SOURCE\_DIR\[@]}\` \[ "$CODE" \=\= "0" ]\&\&echo \-e "\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\\nFull\_Backup System Files Backup Successfully !"fi}\#Perform incremental BACKUP Function CommandAdd\_Backup(){ cd $TARGET\_DIR/$YEAR/$MONTH/$DAY ;if \[ \-f $TARGET\_DIR/$YEAR/$MONTH/$DAY/$FILES ];then read \-p "$FILES Already Exists, overwrite confirmation yes or no ? : " SURE if \[ $SURE \=\= "no" \-o $SURE \=\= "n" ];then sleep 1 ;exit 0 fi\#Add\_Backup Files System if \[ $WEEK \-ne "7" ];then cd $TARGET\_DIR/$YEAR/$MONTH/$DAY ;tar \-g $TARGET\_DIR/snapshot \-czvf $$\_$FILES \`echo ${SOURCE\_DIR\[@]}\` \[ "$CODE" \=\= "0" ]\&\&echo \-e "\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\\nAdd\_Backup System Files Backup Successfully !" fielse if \[ $WEEK \-ne "7" ];then cd $TARGET\_DIR/$YEAR/$MONTH/$DAY ;tar \-g $TARGET\_DIR/snapshot \-czvf $FILES \`echo ${SOURCE\_DIR\[@]}\` \[ "$CODE" \=\= "0" ]\&\&echo \-e "\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\\nAdd\_Backup System Files Backup Successfully !" fifi}Full\_Backup;Add\_Backup | | --- | ## ZIP软件包管理 ZIP也是计算机文件的压缩的算法,原名Deflate(真空),发明者为菲利普·卡兹(Phil Katz)),他于1989年1月公布了该格式的资料。ZIP通常使用后缀名“.zip”。 主流的压缩格式包括tar、rar、zip、war、gzip、bz2、iso等。从性能上比较,TAR、WAR、RAR格式较ZIP格式压缩率较高,但压缩时间远远高于ZIP,Zip命令行工具可以实现对zip属性的包进行管理,也可以将文件及文件及打包成zip格式。如下为ZIP工具打包常见参数详解: | \-f freshen:只更改文件;\-u update:只更改或新文件;\-d 从压缩文件删除文件;\-m 中的条目移动到zipfile(删除OS文件);\-r 递归到目录;\-j junk(不记录)目录名;\-l 将LF转换为CR LF(\-11 CR LF至LF);\-1 压缩更快1\-9压缩更好;\-q 安静操作,不输出执行的过程;\-v verbose操作/打印版本信息;\-c 添加一行注释;\-z 添加zipfile注释;\-o 读取名称使zip文件与最新条目一样旧;\-x 不包括以下名称;\-F 修复zipfile(\-FF尝试更难);\-D 不要添加目录条目; \-T 测试zip文件完整性;\-X eXclude eXtra文件属性;\-e 加密 \- 不要压缩这些后缀;\-h2 显示更多的帮助。 | | --- | ZIP企业案例演示: 1. 通过zip工具打包jingfeng文件夹中所有内容,如图6\-4所示: | zip \-rv jingfeng.zip /root/jingfeng/ | | --- | ![](/media/202411/20241125143328870817.png)图6\-4 zip对jingfeng目录打包备份 1. 通过zip工具打包jingfeng文件夹中所有内容,排除部分文件,如图6\-5所示: | zip \-rv jingfeng.zip \* \-x jf1\.txtzip \-rv jingfeng.zip \* \-x jf2\.txt \-x jf3\.txt | | --- | ![](/media/202411/20241125143328876224.png)图6\-5 zip对jingfeng目录打包备份,排除部分文件 1. 通过zip工具删除jingfeng.zip中jf3\.txt文件,如图6\-6所示 | zip jingfeng.zip \-d jf3\.txt | | --- | 1. 通过unzip工具解压jingfeng.zip文件夹中所有内容,如图6\-6所示: | unzip jingfeng.zipunzip jingfeng.zip \-d /data/backup/ 可以\-d指定解压后的目录 | | --- | ![](/media/202411/20241125143328881503.png) 图6\-6 unzip对jingfeng目录解压 ## 源码包软件安装 通常使用RPM工具管理.rpm结尾的二进制包,而标准的.zip、tar结尾的源代码包则不能使用RPM工具去安装、卸载及升级,源码包安装有三个步骤,如下: | * ./configure 预编译,主要用于检测系统基准环境库是否满足,生成MakeFile文件; * make 编译,基于第一步生成的makefile文件,进行源代码的编译; * make install 安装,编译完毕之后,将相关的可运行文件安装至系统中; 使用make编译时,Linux操作系统必须有GCC编译器,用于编译源码。 | | --- | 源码包安装通常需要./configure、make、make install三个步骤,某些特殊源码可以只有三步中的其中一个步骤,或者两个步骤。 以CentOS 7 Linux系统为基准,在其上安装Nginx源码包,企业中源码安装的详细步骤如下: 1. Nginx.org官网下载Nginx\-1\.13\.0\.tar.gz包 | wget http://nginx.org/download/nginx\-1\.13\.0\.tar.gz | | --- | 1. Nginx源码包解压 | tar \-xvf nginx\-1\.13\.0\.tar.gz | | --- | 1. 源码Configure预编译,需进入解压后的目录执行./configure指令,分号“;”表示连接多个命令。 | cd nginx\-1\.13\.0;./configure | | --- | 1. make编译 | make | | --- | 1. make install安装 | make install | | --- | 通过以上五个步骤,源码包软件安装成功,源码包在编译及安装时,可能会遇到各种错误,需要把错误解决之后,然后再进行下一步安装即可,后面章节会重点针对企业使用的软件进行案例演练。 ## YUM软件包管理 前端软件包管理器(Yellow Updater Modified,YUM)适用于CentOS、Fedora、RedHat及SUSE中的Shell命令行,主要用于管理RPM包,于RPM工具使用范围类似,YUM工具能够从指定的服务器自动下载RPM包并且安装,还可以自动处理依赖性关系。 使用RPM工具管理和安装软件时,会发现rpm包有依赖,需要逐个手动下载安装,而YUM工具的最大便利就是可以自动安装所有依赖的软件包,从而提升效率,节省时间。 ### YUM工作原理 学习YUM,一定要理解YUM工作原理,YUM正常运行,需要依赖两个部分,一是YUM源端,二是YUM客户端,也即用户使用端。 YUM客户端安装的所有RPM包都是来自YUM服务端,YUM源端通过HTTP或者FTP服务器发布。而YUM客户端能够从YUM源端下载依赖的RPM包是由于在YUM源端生成了RPM包的基准信息,包括RPM包版本号、配置文件、二进制信息、依赖关系等。 YUM客户端需要安装软件或者搜索软件,会查找/etc/yum.repos.d下以.repo结尾文件,CentOS Linux默认的.repo文件名为CentOS\-Base.repo,该文件中配置了YUM源端的镜像地址,所以每次安装、升级RPM包,YUM客户端均会查找.repo文件。 YUM客户端如果配置了CentOS官方repo源,客户端操作系统必须能联外网,满足网络条件,才能下载软件并安装,如果没有网络,也可以构建光盘源或者内部YUM源。在只要YUM客户端时,YUM客户端安装软件,默认会把YUM源地址、Header信息、软件包、数据库信息、缓存文件存储在/var/cache/yum中,每次使用YUM工具,YUM优先通过Cache查找相关软件包,Cache中不存在,然后在访问外网YUM源。 ### YUM企业案例演练 由于YUM工具的使用简便、快捷、高效,在企业中得到广泛的使用,得到众多IT运维、程序人员的青睐,要能熟练使用YUM工具,需要先掌握YUM命令行参数的使用,如下为YUM命令工具的参数详解及实战步骤: | YUM命令工具指南,YUM格式为:YUM \[command] \[package] \-y\|\-q 其中的\[options]是可选。\-y安装或者卸载出现YES时,自动确认yes;\-q不显示安装的过程。yum install httpd 安装httpd软件包;yum search YUM搜索软件包;yum list httpd 显示指定程序包安装情况httpd;yum list 显示所有已安装及可安装的软件包;yum remove httpd 删除程序包httpd;yum erase httpd 删除程序包httpd;yum update 内核升级或者软件更新;yum update httpd 更新httpd软件;yum check\-update 检查可更新的程序;yum info httpd 显示安装包信息httpd;yum provides 列出软件包提供哪些文件;yum provides "\*/rz" 列出rz命令由哪个软件包提供;yum grouplist 查询可以用groupinstall安装的组名称;yum groupinstall "Chinese Support" 安装中文支持;yum groupremove "Chinese Support" 删除程序组Chinese Support;yum deplist httpd 查看程序httpd依赖情况;yum clean packages 清除缓存目录下的软件包;yum clean headers 清除缓存目录下的headers;yum clean all 清除缓存目录下的软件包及旧的headers。 | | --- | 1. 基于CentOS 7 Linux,执行命令yum install httpd \-y,安装httpd服务,如图6\-7所示: ![](/media/202411/20241125143328892923.png)图6\-7 YUM 安装httpd软件 1. 执行命令yum grouplist,检查groupinstall的软件组名,如图6\-8所示: ![](/media/202411/20241125143328898123.png)图6\-8 YUM Grouplist显示组安装名称 1. 执行命令yum groupinstall "GNOME Desktop" \-y,安装Linux图像界面,如图6\-9所示: ![](/media/202411/20241125143328903109.png) 图6\-9 GNOME Desktop图像界面安装 1. 执行命令yum install httpd php php\-devel php\-mysql mariadb mariadb\-server \-y,安装中小企业LAMP架构环境,如图6\-10所示: ![](/media/202411/20241125143328908428.png) 图6\-10 LAMP中小企业架构安装 1. 执行命令yum remove ntpdate \-y,卸载ntpdate软件包,如图6\-11所示: ![](/media/202411/20241125143328913829.png)图6\-11 卸载NTPDATE软件 1. 执行命令yum provides rz或者yum provides "\*/rz",查找rz命令的提供者,如图6\-12所示: ![](/media/202411/20241125143328918964.png)图6\-12 查找RZ命令的提供者 1. 执行命令yum update \-y,升级Linux所有可更新的软件包或Linux内核升级,如图6\-13所示: ![](/media/202411/20241125143328924040.png)图6\-13 软件包升级或内核升级 ## YUM优先级配置实战 基于YUM安装软件时,通常会配置多个Repo源,而Fastest mirror 插件是为拥有多个镜像的软件库配置文件而设计的。它会连接到每一个镜像,计算连接所需的时间,然后将镜像按快到慢排序供YUM应用。 默认CentOS Linux系统,Fastestmirror插件是开启的,所以安装软件会从最快的镜像源安装,但是由于Repo源很多,而在这些源中都存在某些软件包,但有些软件有重复,甚至冲突,能否可以优先从一些Repo源中去查找,如果找不到,再去其他源中找呢? 可以使用YUM优先级插件解决该问题,YUM提供的插件yum\-plugin\-priorities,直接YUM安装即可,命令如下: yum install \-y yum\-plugin\-priorities ![](/media/202411/20241125143328929135.png) 修改YUM源优先级配置文件,设置为Enabled,开启优先级插件,1为开启,0为禁止; vim /etc/yum/pluginconf.d/priorities.conf enabled \= 1 ![](/media/202411/20241125143328933921.png) vim 修改/etc/yum.repos./xx.repo文件,在base段中加入如下指令:(优先级为1表示优先被查找,越大其反而被后续查找) priority\=1 ![](/media/202411/20241125143328939101.png) 基于YUM安装ntpdate软件,测试已经优先从163源中查找; ![](/media/202411/20241125143328943686.png) ## 基于ISO镜像构建YUM本地源 通常而言,YUM客户端使用前提是必须联外网,YUM安装软件时,检查repo配置文件查找相应的YUM源仓库,企业IDC机房很多服务器为了安全起见,是禁止服务器上外网的,所以不能使用默认的官方YUM源仓库。 构建本地YUM光盘源,其原理是通过查找光盘中的软件包,实现YUM安装,配置步骤如下: 1. 将CentOS\-7\-x86\_64\-DVD\-1511\.iso镜像加载至虚拟机CD/DVD或者放入服务器CD/DVD光驱中,并将镜像文件挂载至服务器/mnt目录,如图6\-14所示,挂载命令: | mount /dev/cdrom /mnt/ | | --- | ![](/media/202411/20241125143328948969.png) 图6\-14 CentOS ISO镜像文件挂载 1. 备份/etc/yum.repos.d/CentOS\-Base.repo文件为CentOS\-Base.repo.bak,同时在/etc/yum.repos.d目录下创建media.repo文件,并写入如下内容: | \[yum]name\=CentOS7baseurl\=file:///mntenabled\=1gpgcheck\=1gpgkey\=file:///mnt/RPM\-GPG\-KEY\-CentOS\-7 | | --- | Media.repo配置文件详解: | name\=CentOS7 YUM源显示名称;baseurl\=file:///mnt ISO镜像挂载目录;gpgcheck\=1 是否检查GPG\-KEY;enabled\=1 是否启用YUM源;gpgkey\=file:///mnt/RPM\-GPG\-KEY\-CentOS\-7 指定载目录下的GPG\-KEY文件验证。 | | --- | 1. 运行命令yum clean all清空YUM Cache,执行yum install screen –y安装screen软件如图6\-15所示: ![](/media/202411/20241125143328955286.png)图6\-15 YUM 安装Screen软件 1. 至此YUM光盘源构建完毕,在使用YUM源时,会遇到部分软件无法安装,原因是因为光盘中软件包不完整导致,同时光盘源只能本机使用,其他局域网服务器无法使用。 ## 基于HTTP构建YUM网络源 YUM光盘源默认只能本机使用,局域网其他服务器无法使用YUM光盘源,如果想使用的话,需要在每台服务器上构建YUM本地源,该方案在企业中不可取,所以需要构建HTTP局域网YUM源解决,可以通过CreateRepo创建本地YUM源端,repo即为Repository。 构建HTTP局域网YUM源方法及步骤如下: 1. 挂载光盘镜像文件至/mnt | mount /dev/cdrom /mnt/ | | --- | 1. 拷贝/mnt/Packages目录下所有软件包至/var/www/html/centos/ | mkdir \-p /var/www/html/centos/ cp \-R /mnt/Packages/\* /var/www/html/centos/ | | --- | 1. 使用Createrepo创建本地源,执行如下命令会在Centos目录生成repodata目录,目录内容如图6\-16所示: | yum install createrepo\* \-ycd /var/www/htmlcreaterepo centos/ | | --- | ![](/media/202411/20241125143328960902.png)图6\-16 Createrepo生成repodata目录 1. 利用HTTP发布YUM本地源 本地YUM源通过CreateRepo搭建完毕,需要借助HTTP WEB服务器发布/var/www/html/centos/中所有软件,YUM或者RPM安装HTTP WEB服务器,并启动httpd服务。 | yum install httpd httpd\-devel \-y 安装HTTP WEB服务;useradd apache \-g apache 创建apache用户和组;systemctl restart httpd.service 重启HTTPD服务;setenforce 0 临时关闭SeLinux应用级安全策略;systemctl stop firewalld.service 停止防火墙;ps \-ef \|grep httpd 查看HTTPD进程是否启动。 | | --- | 1. 在YUM客户端,创建/etc/yum.repos.d/http.repo文件,写入如下内容: | \[base]name\="CentOS7 HTTP YUM"baseurl\=http://192\.168\.1\.115/centos/gpgcheck\=0enabled\=1\[updates]name\="CentOS7 HTTP YUM"baseurl\=http://192\.168\.1\.115/centosgpgcheck\=0enabled\=1 | | --- | 1. 至此在YUM客户端上执行如下命令,如图6\-17所示: | yum clean all 清空YUM Cache; yum install ntpdate \-y 安装NTPDATE软件。 | | --- | ![](/media/202411/20241125143328967566.png)图6\-17 HTTP YUM源客户端验证 ## YUM源端软件包扩展 默认使用ISO镜像文件中的软件包构建的HTTP YUM源,会发现缺少很多软件包,如果服务器需要挂载移动硬盘,Mount挂载移动硬盘需要ntfs\-3g软件包支持,而本地光盘镜像中没有该软件包,此时需要往YUM源端添加ntfs\-3g软件包,添加方法如下: 1. 切换至/var/www/html/centos目录,官网下载NTFS\-3G软件包。 | cd /var/www/html/centos/wget [http://dl.fedoraproject.org/pub/epel/7/x86\_64/n/ntfs\-3g\-2016\.2\.22\-3\.el7\.x86\_64\.rpm](http://dl.fedoraproject.org/pub/epel/7/x86_64/n/ntfs-3g-2016.2.22-3.el7.x86_64.rpm) [http://dl.fedoraproject.org/pub/epel/7/x86\_64/n/ntfs\-3g\-devel\-2016\.2\.22\-3\.el7\.x86\_64\.rpm](http://dl.fedoraproject.org/pub/epel/7/x86_64/n/ntfs-3g-devel-2016.2.22-3.el7.x86_64.rpm) | | --- | 1. Createrepo命令更新软件包,同理,如需新增其他软件包,同样把软件下载至本地,然后通过createrepo更新即可,如图6\-18所示: | createrepo \-\-update centos/ | | --- | ![](/media/202411/20241125143328972905.png) 图6\-18 CreateRepo update更新软件包 1. 客户端YUM验证,安装NTFS\-3G软件包,如图6\-19所示: ![](/media/202411/20241125143328977803.png)图6\-19 YUM INSTALL NTFS\-3G软件包 ## 同步外网YUM源 在企业实际应用场景中,仅仅靠光盘里面的RPM软件包是不能满足需要,我们可以把外网的YUM源中的所有软件包同步至本地,可以完善本地YUM源的软件包数量及完整性。 获取外网YUM源软件常见方法包括Rsync、Wget、Reposync,三种同步方法的区别Rsync方式需要外网YUM源支持RSYNC协议,Wget可以直接获取,而Reposync可以同步几乎所有的YUM源,下面以Reporsync为案例,同步外网YUM源软件至本地,步骤如下: 1. 下载CentOS7 REPO文件至/etc/yum.repos.d/,并安装reposync命令工具: | wget [http://mirrors.163\.com/.help/CentOS7\-Base\-163\.repo](http://mirrors.163.com/.help/CentOS7-Base-163.repo -O centos.repo)[mv CentOS7\-Base\-163\.repo /etc/yum.repos.d/centos.repo](http://mirrors.163.com/.help/CentOS7-Base-163.repo -O centos.repo)yum clean allyum install yum\-utils createrepo –yyum repolist | | --- | 1. 通过reposync命令工具获取外网YUM源所有软件包,\-r指定repolist id,默认不加\-r表示获取外网所有YUM软件包,\-p参数表示指定下载软件的路径,如图6\-20(a)、图6\-20(b)所示: | reposync \-r base \-p /var/www/html/centos/reposync \-r updates \-p /var/www/html/centos/ | | --- | ![](/media/202411/20241125143328983576.png) 图6\-20(a) Reposync获取外网YUM源软件包 ![](/media/202411/20241125143328988540.png) 图6\-20(b) Reposync获取外网YUM源软件包 1. 通过reposync工具下载完所有的软件包之后,需要执行createrepo更新本地YUM仓库: | createrepo /var/www/html/centos/ | | --- | ## 本章小结 通过对本章内容的学习,读者掌握了Linux安装不同包的工具及命令,使用RPM及YUM管理.RPM结尾的二进制包,基于configure、make、make install实现源码包安装,并能够对软件进行安装、卸载及维护。 能够独立构建企业光盘源、HTTP网络YUM源,实现无外网网络使用YUM安装各种软件包及工具,同时能随时添加新的软件包至本地Yum源中。 ## 同步作业 1. RPM及YUM管理工具的区别是什么? 2. 企业中安装软件,何时选择YUM安装或者源码编译安装? 3. 将Linux系统中PHP5\.3版本升级至PHP5\.5版本,升级方法有几种,分别写出升级步骤? 4. 使用源码编译安装httpd\-2\.4\.25\.tar.bz2,写出安装的流程及注意事项。 5. 如何将CentOS 7 Linux字符界面升级为图形界面,并设置系统启动默认为图形界面? # Linux磁盘管理 Linux系统一切以文件的方式存储于硬盘,应用程序数据需要时刻读写硬盘,所以企业生产环境中对硬盘的操作变得尤为重要,对硬盘的维护和管理也是每个运维工程师必备工作之一。 本章向读者介绍硬盘简介、硬盘数据存储方式、如何在企业生产服务器添加硬盘、对硬盘进行分区、初始化以及对硬盘进行故障修复等。 ## 计算机硬盘简介 硬盘是计算机主要存储[媒介](http://baike.baidu.com/item/%E5%AA%92%E4%BB%8B" \t "_blank)之一,由一个或者多个铝制或者玻璃制的[碟片](http://baike.baidu.com/item/%E7%A2%9F%E7%89%87" \t "_blank)组成,[碟片](http://baike.baidu.com/item/%E7%A2%9F%E7%89%87" \t "_blank)外覆盖有[铁磁性](http://baike.baidu.com/item/%E9%93%81%E7%A3%81%E6%80%A7" \t "_blank)材料,硬盘内部由磁道、柱面、扇区、磁头等部件组成,如图7\-1所示: ![](/media/202411/20241125143328994478.png) 图7\-1 硬盘内部结构组成 Linux系统中硬件设备相关配置文件存放在/dev/下,常见硬盘命名:/dev/hda、/dev/sda、/dev/sdb、/dev/sdc、/dev/vda。不同硬盘接口,在系统中识别的设备名称不一样。 IDE硬盘接口在Linux中设备名为/dev/hda,SAS、SCSI、SATA硬盘接口在Linux中设备名为sda,高效云盘硬盘接口会识别为/dev/vda等。 文件储存在硬盘上,硬盘的最小存储单位叫做Sector(扇区),每个Sector储存512字节。操作系统在读取硬盘的时候,不会逐个Sector的去读取,这样效率非常低,为了提升读取效率,操作系统会一次性连续读取多个Sector,即一次性读取多个Sector称为一个Block(块)。 由多个Sector组成的Block是文件存取的最小单位。Block的大小常见的有1KB、2KB、4KB,Block在Linux中常设置为4KB,即连续八个Sector组成一个Block。 /boot分区Block一般为1KB,而/data/分区或者/分区的Block为4K。可以通过如下三种方法查看Linux分区的Block大小: | dumpe2fs /dev/sda1 \|grep "Block size"tune2fs \-l /dev/sda1 \|grep "Block size"stat /boot/\|grep "IO Block" | | --- | 例如创建一个普通文件,文件大小为10Bytes,而默认设置Block为4K,如果有1万个小文件,由于每个Block只能存放一个文件,如果文件的大小比Block大,会申请更多的Block,相反如果文件的大小比默认Block小,仍会占用一个Block,这样剩余的空间会被浪费掉。 * 1万个文件理论只占用空间大小:10000x10\=100000Bytes\=97\.65625MBytes; * 1万个文件真实占用空间大小:10000x4096Bytes\=40960000Bytes\=40000MBytes\=40GB。 * 根据企业实际需求,此时可以将Block设置为1K,从而节省更多的空间。 ## 硬盘Block及Inode详解 通常而言,操作系统对于文件数据的存放包括两个部分:文件内容、权限及文件属性。操作系统文件存放是基于文件系统,文件系统会将文件的实际内容存储到Block中,而将权限与属性等信息存放至Inode中。 在硬盘分区中,还有一个超级区块 (SuperBlock) ,SuperBlock会记录整个文件系统的整体信息,包括 Inode、Block 总量、使用大小、剩余大小等信息,每个 inode 与 block 都有编号对应,方便Linux系统快速定位查找文件。 * Superblock:记录文件系统的整体信息,包括inode与block的总量、使用大小、剩余大小, 以及文件系统的格式与相关信息等; * Inode:记录文件的属性,权限,同时会记录该文件的数据所在的block编号; * Block:存储文件的内容,如果文件超过默认Block大小,会自动占用多个Block。 因为每个 inode 与 block 都有编号,而每个文件都会占用一个 inode ,inode 内则有文件数据放置的 block 号码。如果能够找到文件的 inode,就可以找到该文件所放置数据的block号码,从而读取该文件内容。 操作系统进行格式化分区时,操作系统自动将硬盘分成两个区域。一个是数据Block区,用于存放文件数据;另一个是Inode Table区,用于存放inode包含的元信息。 每个inode节点的大小,可以在格式化时指定,默认为128Bytes或256Bytes,/boot分区Inode默认为128Bytes,其他分区默认为256Bytes,查看Linux系统Inode方法如下: | dumpe2fs /dev/sda1 \|grep " Inode size "tune2fs \-l /dev/sda1 \|grep " Inode size"stat /boot/\|grep "Inode" | | --- | 格式化磁盘时,可以指定默认Inode和Block的大小,\-b指定默认Block值,\-I指定默认Inode值,如图7\-2所示,命令如下: | mkfs.ext4 \-b 4096 \-I 256 /dev/sdb | | --- | ![](/media/202411/20241125143329001496.png)图7\-2 格式化硬盘指定Inode和Block ## 硬链接介绍 一般情况下,文件名和inode编号是一一对应的关系,每个inode号码对应一个文件名。但UNIX/Linux系统多个文件名也可以指向同一个inode号码。这意味着可以用不同的文件名访问同样的内容,对文件内容进行修改,会影响到所有文件名。但删除一个文件名,不影响另一个文件名的访问。这种情况就被称为硬链接(hard link)。 创建硬链接的命令为:ln jf1\.txt jf2\.txt,其中jf1\.txt为源文件,jf2\.txt为目标文件。如上命令源文件与目标文件的inode号码相同,都指向同一个inode。inode信息中有一项叫做"链接数",记录指向该inode的文件名总数,这时会增加1,变成2,如图7\-3所示: ![](/media/202411/20241125143329006451.png)图7\-3 jf1\.txt jf2\.txt硬链接inode值变化 同样删除一个jf2\.txt文件,就会使得jf1\.txt inode节点中的"链接数"减1。如果该inode值减到0,表明没有文件名指向这个inode,系统就会回收这个inode号码,以及其所对应block区域,如图7\-4所示: ![](/media/202411/20241125143329011371.png)图7\-4 删除jf2\.txt硬链接inode值变化 实用小技巧:硬链接不能跨分区链接,硬链接只能对文件生效,对目录无效,也即是目录不能创建硬链接。硬链接源文件与目标文件共用一个inode值,从某种意义上来,节省inode空间。不管是单独删除源文件还是删除目标文件,文件内容始终存在。同时链接后的文件不占用系统多余的空间。 ## 软链接介绍 除了硬链接以外,还有一种链接\-软链接。文件jf1\.txt和文件jf2\.txt的inode号码虽然不一样,但是文件jf2\.txt的内容是文件jf1\.txt的路径。读取文件jf2\.txt时,系统会自动将访问者导向文件jf1\.txt。 无论打开哪一个文件,最终读取的都是文件jf1\.txt。这时,文件jf2\.txt就称为文件jf1\.txt的"软链接"(soft link)或者"符号链接(symbolic link)。 文件jf2\.txt依赖于文件jf1\.txt而存在,如果删除了文件jf1\.txt,打开文件jf2\.txt就会报错:"No such file or directory"。 软链接与硬链接最大的不同是文件jf2\.txt指向文件jf1\.txt的文件名,而不是文件jf1\.txt的inode号码,因此文件jf1\.txt的inode链接数不会发生变化,如图7\-5所示: ![](/media/202411/20241125143329016568.png) 图7\-5 删除jf1\.txt源文件链接数不变 实用小技巧:软链接可以跨分区链接,软链接支持目录同时也支持文件的链接。软链接源文件与目标文件Inode不相同,从某种意义上来,会消耗省inode空间。不管是删除源文件还是重启系统,该软链接还存在,但是文件内容会丢失,一旦新建源同名文件名,软链接文件恢复正常。 ## Linux下磁盘实战操作命令 企业真实场景由于硬盘常年大量读写,经常会出现坏盘,需要更换硬盘。或者由于磁盘空间不足,需添加新硬盘,新添加的硬盘需要经过格式化、分区才能被Linux系统所使用,虚拟机CentOS 7 Linux模拟DELL R730真实服务器添加一块新硬盘,不需要关机,直接插入用硬盘即可,一般硬盘均支持热插拔功能。企业中添加新硬盘的操作流程如下: 1. 检测Linux系统识别的硬盘设备,新添加硬盘被识别为/dev/sdb,如果有多块硬盘,会依次识别成/dev/sdc、/dev/sdd等设备名称,如图7\-6所示: | fdisk \-l | | --- | ![](/media/202411/20241125143329021856.png) 图7\-6 Fdisk查看Linux系统硬盘设备 1. 基于新硬盘/dev/sdb设备,创建磁盘分区/dev/sdb1,如图7\-7所示: | fdisk /dev/sdb | | --- | ![](/media/202411/20241125143329026899.png)图7\-7 Fdisk /dev/sdb分区 1. fdisk分区命令参数如下,常用参数包括m、n、p、e、d、w。 | b 编辑bsd disklabel;c 切换dos兼容性标志;d 删除一个分区;g 创建一个新的空GPT分区表;G 创建一个IRIX(SGI)分区表;l 列出已知的分区类型;m 打印帮助菜单;n 添加一个新分区;o 创建一个新空DOS分区表;p 打印分区表信息;q 退出而不保存更改;s 创建一个新的空的Sun磁盘标签;t 更改分区的系统ID;u 更改显示/输入单位;v 验证分区表;w 将分区表写入磁盘并退出;x 额外功能。 | | --- | 1. 创建/dev/sdb1分区方法,fdisk /dev/sdb,然后按n\-p\-1\-Enter键\- \+20G\-Enter键\-w,最后执行fdisk –l\|tail \-10,如图7\-8(a)、图7\-8(b)所示: ![](/media/202411/20241125143329034610.png) 图7\-8(a) Fdisk /dev/sdb创建/dev/sdb1分区 ![](/media/202411/20241125143329039347.png)图7\-8(b) Fdisk –l查看/dev/sdb1分区 1. mkfs.ext4 /dev/sdb1格式化磁盘分区,如图7\-9所示: ![](/media/202411/20241125143329044688.png)图7\-9 mkfs.ext4格式化磁盘分区 1. /dev/sdb1分区格式化,使用mount命令挂载到/data/目录,如图7\-10所示: | mkdir \-p /data/ 创建/data/数据目录mount /dev/sdb1 /data 挂载/dev/sdb1分区至/data/目录df \-h 查看磁盘分区详情echo "mount /dev/sdb1 /data" \>\>/etc/rc.local 将挂载分区命令加入/etc/rc.local开机启动 | | --- | ![](/media/202411/20241125143329050494.png)图7\-10 MOUNT挂载/dev/sdb1磁盘分区 1. 自动挂载分区除了可以加入到/etc/rc.local开机启动之外,还可以加入到/etc/fstab文件中,如图7\-11所示: | /dev/sdb1 /data/ ext4 defaults 0 0mount \-o rw,remount / 重新挂载/系统,检测/etc/fstab是否有误。 | | --- | ![](/media/202411/20241125143329055833.png) 图7\-11 /dev/sdb1磁盘分区加入/etc/fstab文件 ## 基于GPT格式磁盘分区 MBR分区标准决定了MBR只支持在2TB以下的硬盘,为了支持能使用大于2T硬盘空间,需使用GPT格式进行分区。创建大于2TB的分区,需使用parted工具。 在企业真实环境中,通常一台服务器有多块硬盘,整个硬盘容量为10T,需要基于GTP格式对10T硬盘进行分区,操作步骤如下: | parted \-s /dev/sdb mklabel gpt 设置分区类型为gpt格式;mkfs.ext3 /dev/sdb 基于Ext3文件系统类型格式化;mount /dev/sdb /data/ 挂载/dev/sdb设备至/data/目录。 | | --- | 1. 如图7\-12所示,假设/dev/sdb 为10T硬盘,使用GPT格式来格式化磁盘: ![](/media/202411/20241125143329061223.png)图7\-12 假设/dev/sdb为10T设备 1. 执行命令:parted \-s /dev/sdb mklabel gpt,如图7\-13所示: ![](/media/202411/20241125143329066043.png)图7\-13 设置/dev/sdb为GPT格式磁盘 1. 基于mkfs.ext3 /dev/sdb格式化磁盘,如图7\-14所示: ![](/media/202411/20241125143329070967.png)图7\-14 格式/dev/sdb磁盘 parted命令行也可以进行分区,如图7\-15(a)、7\-15(b)、7\-15(c)所示: | parted🡪select /dev/sdb🡪mklabel gpt🡪mkpart primary 0 \-1🡪printmkfs.ext3 /dev/sdb1mount /dev/sdb1 /data/ | | --- | ![](/media/202411/20241125143329076527.png)图7\-15(a)parted工具执行GPT格式分区 ![](/media/202411/20241125143329081492.png) 图7\-15(b)parted工具执行GPT格式分区 ![](/media/202411/20241125143329086370.png) 图7\-15(c) parted工具执行GPT格式分区 ## MOUNT命令工具 Mount命令工具主要用于将设备或者分区挂载至Linux系统目录下,Linux系统在分区时,也是基于mount机制将/dev/sda分区挂载至系统目录,将设备与目录挂载之后,Linux操作系统方可进行文件的存储。 ### Mount命令参数详解 如下为企业中Mount命令常用参数详解: | mount \[\-Vh]mount \-a \[\-fFnrsvw] \[\-t vfstype]mount \[\-fnrsvw] \[\-o options \[,...]] device \| dirmount \[\-fnrsvw] \[\-t vfstype] \[\-o options] device dir\-V: 显示mount工具版本号;\-l: 显示已加载的文件系统列表;\-h: 显示帮助信息并退出;\-v: 输出指令执行的详细信息;\-n: 加载没有写入文件/etc/mtab中的文件系统;\-r: 将文件系统加载为只读模式; \-a: 加载文件/etc/fstab中配置的所有文件系统;\-o: 指定mount挂载扩展参数,常见扩展指令:rw、remount、loop等,其中\-o相关指令如下:\-o atime: 系统会在每次读取文档时更新文档时间;\-o noatime: 系统会在每次读取文档时不更新文档时间;\-o defaults: 使用预设的选项 rw,suid,dev,exec,auto,nouser等;\-o exec 允许执行档被执行;\-o user、\-o nouser: 使用者可以执行 mount/umount的动作;\-o remount: 将已挂载的系统分区重新以其他再次模式挂载;\-o ro: 只读模式挂载;\-o rw: 可读可写模式挂载;\-o loop 使用loop模式,把文件当成设备挂载至系统目录。\-t: 指定mount挂载设备类型,常见类型nfs、ntfs\-3g、vfat、iso9660等,其中\-t相关指令如下:iso9660 光盘或光盘镜像;msdos Fat16文件系统;vfat Fat32文件系统;ntfs NTFS文件系统;ntfs\-3g 识别移动硬盘格式;smbfs 挂载Windows文件网络共享;nfs Unix/Linux文件网络共享。 | | --- | ### 企业常用Mount案例 Mount常用案例演示如下: | mount /dev/sdb1 /data 挂载/dev/sdb1分区至/data/目录mount /dev/cdrom /mnt 挂载Cdrom光盘至/mnt目录;mount \-t ntfs\-3g /dev/sdc /data1 挂载/dev/sdc移动硬盘至/data1目录;mount \-o remount,rw / 重新以读写模式挂载/系统;mount \-t iso9660 \-o loop centos7\.iso /mnt 将centos7\.iso镜像文件挂载至/mnt目录;mount \-t fat32 /dev/sdd1 /mnt 将U盘/dev/sdd1挂载至/mnt/目录;mount \-t nfs 192\.168\.1\.11:/data/ /mnt 将远程192\.168\.1\.11:/data目录挂载至本地/mnt目录。 | | --- | ## Linux硬盘故障修复 企业服务器运维中,经常会发现操作系统的分区变成只读文件系统,错误提示信息为 “Read\-only file system”,出现只读文件系统,会导致只能读取,而无法写入新文件、新数据等操作。 造成该问题的原因包括:磁盘老旧长期大量的读写、文件系统文件被破坏、磁盘碎片文件、异常断电、读写中断等等。 以企业CentOS 7 Linux为案例,来修复文件系统,步骤如下: 1. 远程备份本地其他重要数据,出现只读文件系统,需先备份其他重要数据,基于rsync\|scp远程备份,其中/data为源目录,/data/backup/2022/为目标备份目录。 | rsync \-av /data/ root@192\.168\.111\.188:/data/backup/2022/ | | --- | 1. 可以重新挂载/系统,挂载命令如下,测试文件系统是否可以写入文件。 | mount \-o remount,rw / | | --- | 1. 如果重新挂载/系统无法解决问题,则需重启服务器,以CD/DVD光盘引导进入Linux Rescue修复模式,如图7\-16(a)、7\-16(b)所示,光标选择“Troubleshooting”,按Enter键,然后选择“Rescue a CentOS system”,按Enter键。 ![](/media/202411/20241125143329096336.png)图7\-16(a) 光盘引导进入修复模式 ![](/media/202411/20241125143329101670.png)图7\-16(b) 光盘引导进入修复模式 1. 选择“1)Continue”继续操作,如图7\-17所示: ![](/media/202411/20241125143329106516.png) 图7\-17 选择Continue继续进入系统 1. 登录修复模式,执行如下命令,df –h显示原来的文件系统,如图7\-18所示: | chroot /mnt/sysimagedf \-h | | --- | ![](/media/202411/20241125143329111624.png)图7\-18 切换原分区目录 1. 对有异常的分区进行检测并修复,根据文件系统类型,执行相应的命令如下: | umount /dev/sda3fsck.ext4 /dev/sda3 –y | | --- | 1. 修复完成之后,重启系统即可 | reboot | | --- | ## 本章小结 通过对本章内容的学习,读者掌握了Linux硬盘内部结构、Block及Inode特性,能够对企业硬盘进行分区、格式化等操作,满足企业的日常需求。 基于mount工具,能对硬盘、各类文件系统进行挂载操作,同时对只读文件系统能快速修复并投入使用。 ## 同步作业 1. 软链接与硬链接的区别是什么? 2. 有一块4T的移动硬盘,如何将数据拷贝至服务器/data/目录,服务器空间为10T,请写出详细步骤? 3. 运维部小刘发现公司IDC机房一台DELL R730服务器,/data/目录不可写,而/boot目录可读可写,请问原因是什么导致,如何修复/data/目录? 4. 公司一台DELL R730服务器/data/images目录存放了大量的小文件,运维人员向该目录写入1M测试文件,提示磁盘空间不足,而通过df –h显示剩余可用空间为500G,请问是什么原因导致,如何解决该问题? 5. 机房一台DELL R730服务器,由于业务需求,临时重启,重启完,20分钟后还无法登陆系统,检查控制台输出,一直卡在MySQL服务启动项,请问如何快速解决让系统正常启动,请写出解决步骤。 # Linux文件服务器企业实战 运维和管理企业Linux服务器,除了要熟练Linux系统本身的维护和管理之外,最重要的是熟练甚至精通基于Linux系统安装配置各种应用软件,对软件进行调优以及软件在使用中遇到各类问题,能够快速定位并解决问题。 本章向读者介绍进程、线程、企业Vsftpd服务器实战、匿名用户访问、系统用户访问及虚拟用户实战等。 ## 进程与线程概念及区别 Linux系统各种软件和服务,存在于系统,必然会占用系统各种资源,系统资源是如何分配及调度的呢,本节将给读者展示系统进程、资源及调度相关的内容。 进程(Process)是计算机中的软件程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是[操作系统](http://baike.baidu.com/view/880.htm" \t "_blank)结构的基础。 在早期面向进程设计的计算机结构中,进程是程序的基本执行实体,在当代面向线程设计的计算机结构中,进程是线程的容器。软件程序是对指令、数据及其组织形式的描述,而进程是程序的实体,通常而言,把运行在系统中的软件程序称之为进程。 除了进程,读者通常会听到线程的概念,线程也被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令[指针](http://baike.baidu.com/view/159417.htm" \t "_blank)(PC),[寄存器](http://baike.baidu.com/view/6159.htm" \t "_blank)集合和[堆栈](http://baike.baidu.com/view/93201.htm" \t "_blank)组成。 线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有操作系统资源,但是该线程可与同属进程的其它线程共享该进程所拥有的全部资源。 程序、进程、线程三者区别如下: * 程序:程序并不能单独执行,是静止的,只有将程序加载到内存中,系统为其分配资源后才能够执行; * 进程:程序对一个数据集的动态执行过程,一个进程包含一个或者更多的线程,一个线程同时只能被一个进程所拥有,进程是分配资源的基本单位。进程拥有独立的内存单元,而多个线程共享内存,从而提高了应用程序的运行效率。 * 线程:线程是进程内的基本调度单位,线程的划分尺度小于进程,并发性更高,线程本身不拥有系统资源, 但是该线程可与同属进程的其它线程共享该进程所拥有的全部资源。每一个独立的线程,都有一个程序运行的入口、顺序执行序列、和程序的出口。 如图8\-1所示,程序、进程、线程三者的关系拓扑图: ![1_conew4](/media/202411/20241125143329118518.jpeg)图8\-1 程序、进程、线程关系图 如上图8\-1所示,多进程、多线程的区别如下: * 多进程,每个进程互相独立,不影响主程序的稳定性,某个子进程崩溃对其他进程没有影响,通过增加CPU可以扩充软件的性能,可以减少线程加锁/解锁的影响,极大提高性能。缺点是多进程逻辑控制复杂,需要和主程序交互,需要跨进程边界,进程之间上下文切换比线程之间上下文切换代价大。 * 多线程,无需跨进程,程序逻辑和控制方式简单,所有线程共享该进程的内存和变量等。缺点是每个线程与主程序共用地址空间,线程之间的同步和加锁控制比较麻烦,一个线程的崩溃会影响到整个进程或者程序的稳定性。 ## Vsftpd服务器企业实战 文件传输协议(File Transfer Protocol,FTP),基于该协议FTP客户端与服务端可以实现共享文件、上传文件、下载文件。 FTP 基于[TCP](http://baike.baidu.com/subview/32754/8048820.htm" \t "_blank)协议生成一个虚拟的连接,主要用于控制FTP连接信息,同时再生成一个单独的TCP连接用于FTP[数据传输](http://baike.baidu.com/view/875888.htm" \t "_blank)。用户可以通过客户端向FTP服务器端上传、下载、删除文件,FTP服务器端可以同时提供给多人共享使用。 FTP服务是Client/Server(简称C/S)模式,基于FTP协议实现FTP文件对外共享及传输的软件称之为FTP服务器源端,客户端程序基于FTP协议,则称之为FTP客户端,FTP客户端可以向FTP服务器上传、下载文件。 ### FTP传输模式 FTP基于C/S模式,FTP客户端与服务器端有两种传输模式,分别是FTP主动模式、FTP被动模式,主被动模式均是以FTP服务器端为参照。主被动模式如图8\-2(a)、8\-2(b)所示,主被动模式详细区别如下: * FTP主动模式:客户端从一个任意的端口N(N\>1024)连接到FTP服务器的port 21命令端口,客户端开始监听端口N\+1,并发送FTP命令“port N\+1”到FTP服务器,FTP服务器以数据端口(20)连接到客户端指定的数据端口(N\+1)。 * FTP被动模式:客户端从一个任意的端口N(N\>1024)连接到FTP服务器的port 21命令端口,客户端开始监听端口N\+1,客户端提交 PASV命令,服务器会开启一个任意的端口(P \>1024),并发送PORT P命令给客户端。客户端发起从本地端口N\+1到服务器的端口P的连接用来传送数据。 在企业实际环境中,如果FTP客户端与FTP服务端均开放防火墙,FTP需以主动模式工作,这样只需要在FTP服务器端防火墙规则中,开放20、21端口即可。关于防火墙配置后面章节会讲解。 ![](/media/202411/20241125143334452056.png) 图8\-2(a) FTP主动模式 ![](/media/202411/20241125143336916603.png)图8\-2(b) FTP被动模式 ### Vsftpd服务器简介 目前主流的FTP服务器端软件包括:Vsftpd、ProFTPD、PureFTPd、Wuftpd、Server\-U FTP、 FileZilla Server等软件,其中Unix/Linux使用较为广泛的FTP服务器端软件为Vsftpd 。 非常安全的FTP服务进程(Very Secure FTP daemon,Vsftpd),Vsftpd在Unix/[Linux](http://www.ha97.com/category/linux" \o "Linux)发行版中最主流的FTP服务器程序,优点小巧轻快,安全易用、稳定高效、满足企业跨部门、多用户的使用(1000用户)等。 Vsftpd基于GPL开源协议发布,在中小企业中得到广泛的应用,Vsftpd可以快速上手,基于Vsftpd虚拟用户方式,访问验证更加安全。Vsftpd还可以基于MYSQL数据库做安全验证,多重安全防护。 ### Vsftpd服务器安装配置 Vsftpd服务器端安装有两种方法,一是基于YUM方式安装,而是基于源码编译安装,最终实现效果完全一致,本文采用YUM安装Vsftpd,步骤如下: 1. 在命令行执行如下命令,如图8\-3所示: | yum install vsftpd\* \-y | | --- | ![](/media/202411/20241125143336923563.png)图8\-3 YUM安装Vsftpd服务端 1. 打印vsftpd安装后的配置文件路径、启动Vsftpd服务及查看进程是否启动,如图8\-4所示: | rpm \-ql vsftpd\|moresystemctl restart vsftpd.serviceps \-ef \|grep vsftpd | | --- | ![](/media/202411/20241125143336930462.png)图8\-4 打印Vsftpd软件安装后路径 1. Vsftpd.conf默认配置文件详解如下: | anonymous\_enable\=YES 开启匿名用户访问;local\_enable\=YES 启用本地系统用户访问;write\_enable\=YES 本地系统用户写入权限;local\_umask\=022 本地用户创建文件及目录默认权限掩码;dirmessage\_enable\=YES 打印目录显示信息,通常用于用户第一次访问目录时,信息提示;xferlog\_enable\=YES 启用上传/下载日志记录; connect\_from\_port\_20\=YES FTP使用20端口进行数据传输;xferlog\_std\_format\=YES 日志文件将根据xferlog的标准格式写入;listen\=NO Vsftpd不以独立的服务启动,通过Xinetd服务管理,建议改成YES;listen\_ipv6\=YES 启用IPV6监听;pam\_service\_name\=vsftpd 登录FTP服务器,依据/etc/pam.d/vsftpd中内容进行认证;userlist\_enable\=YES vsftpd.user\_list和ftpusers配置文件里用户禁止访问FTP;tcp\_wrappers\=YES 设置vsftpd与tcp wrapper结合进行主机的访问控制,Vsftpd服务器检查/etc/hosts.allow 和/etc/hosts.deny中的设置,来决定请求连接的主机,是否允许访问该FTP服务器。 | | --- | 1. 启动Vsftpd服务后,通过Windows客户端资源管理器访问Vsftp服务器端,如图8\-5所示: | ftp://192\.168\.111\.131/ | | --- | ![](/media/202411/20241125143336937015.png)图8\-5 匿名用户访问FTP默认目录 FTP主被动模式,默认为主动模式,设置为被动模式使用端口方法如下: | pasv\_enable\=YESpasv\_min\_port\=60000pasv\_max\_port\=60100 | | --- | ### Vsftpd匿名用户配置 Vsftpd默认以匿名用户访问,匿名用户默认访问的FTP服务器端路径为:/var/ftp/pub,匿名用户只有查看权限,无法创建、删除、修改。如需关闭FTP匿名用户访问,需修改配置文件/etc/vsftpd/vsftpd.conf,将anonymous\_enable\=YES修改为anonymous\_enable\=NO,重启Vsftpd服务即可。 如果允许匿名用户能够上传、下载、删除文件,需在/etc/vsftpd/vsftpd.conf配置文件中加入如下代码: | anon\_upload\_enable\=YES 允许匿名用户上传文件;anon\_mkdir\_write\_enable\=YES 允许匿名用户创建目录;anon\_other\_write\_enable\=YES 允许匿名用户其他写入权限。 | | --- | 匿名用户完整vsftpd.conf配置文件代码如下: | anonymous\_enable\=YESlocal\_enable\=YESwrite\_enable\=YESlocal\_umask\=022anon\_upload\_enable\=YESanon\_mkdir\_write\_enable\=YESanon\_other\_write\_enable\=YESdirmessage\_enable\=YESxferlog\_enable\=YESconnect\_from\_port\_20\=YESxferlog\_std\_format\=YESlisten\=NOlisten\_ipv6\=YESpam\_service\_name\=vsftpduserlist\_enable\=YEStcp\_wrappers\=YES | | --- | 由于默认Vsftpd匿名用户有两种:anonymous、ftp,所以匿名用户如果需要上传文件、删除及修改等权限,需要ftp用户对/var/ftp/pub目录有写入权限,使用如下chown和chmod任意一种即可,设置命令如下: | chown \-R ftp pub/chmod o\+w pub/ | | --- | 如上Vsftpd.conf配置文件配置完毕,同时权限设置完,重启vsftpd服务即可,通过Windows客户端访问,能够上传文件、删除文件、创建目录等操作,如图8\-6所示: ![](/media/202411/20241125143336946486.png) 图8\-6 匿名用户访问上传文件 ### Vsftpd系统用户配置 Vsftpd匿名用户设置完毕,匿名用户,任何人都可以查看FTP服务器端的文件、目录,甚至可以修改、删除,此方案如适合存放私密文件在FTP服务器端,如何保证文件或者目录专属拥有者呢,Vsftpd系统用户可以实现该需求。 实现Vsftpd系统用户方式验证,只需在Linux系统中创建多个用户即可,创建用户使用useradd,同时给用户设置密码,即可通过用户和密码登录FTP,进行文件上传、下载、删除等操作。Vsftpd系统用户实现方法步骤如下: 1. Linux系统中创建系统用户jfedu1、jfedu2,分别设置密码为123456: | useradd jfedu1useradd jfedu2echo 123456\|passwd \-\-stdin jfedu1echo 123456\|passwd \-\-stdin jfedu2 | | --- | 1. 修改vsftpd.conf配置文件代码如下: | anonymous\_enable\=NOlocal\_enable\=YESwrite\_enable\=YESlocal\_umask\=022dirmessage\_enable\=YESxferlog\_enable\=YESconnect\_from\_port\_20\=YESxferlog\_std\_format\=YESlisten\=NOlisten\_ipv6\=YESpam\_service\_name\=vsftpduserlist\_enable\=YEStcp\_wrappers\=YES | | --- | 1. 通过Windows资源客户端验证,使用jfedu1、jfedu2用户登录FTP服务器,即可上传文件、删除文件、下载文件,jfedu1、jfedu2系统用户上传文件的家目录在/home/jfedu1、/home/jfedu2下,如图8\-7(a)、8\-7(b)所示: ![](/media/202411/20241125143336953731.png)图8\-7(a) jfedu1用户登录FTP服务器 ![](/media/202411/20241125143336959150.png)图8\-7(b) jfedu1登录FTP服务器上传文件 ### Vsftpd虚拟用户配置 如果基于Vsftpd系统用户访问FTP服务器,系统用户越多越不利于管理,而且不利于系统安全管理,鉴于此,为了能更加的安全使用VSFTPD,需使用Vsftpd虚拟用户方式。 Vsftpd虚拟用户原理:虚拟用户就是没有实际的真实系统用户,而是通过映射到其中一个真实用户以及设置相应的权限来实现访问验证,虚拟用户不能登录Linux系统,从而让系统更加的安全可靠。 Vsftpd虚拟用户企业案例配置步骤如下: 1. 安装Vsftpd虚拟用户需用到的软件及认证模块: | yum install pam\* libdb\-utils libdb\* \-\-skip\-broken \-y | | --- | 1. 创建虚拟用户临时文件/etc/vsftpd/ftpusers.txt,新建虚拟用户和密码,其中jfedu001、jfedu002为虚拟用户名,123456为密码,如果有多个用户,依次格式填写即可: | jfedu001123456jfedu002123456 | | --- | 1. 生成Vsftpd虚拟用户数据库认证文件,设置权限700: | db\_load \-T \-t hash \-f /etc/vsftpd/ftpusers.txt /etc/vsftpd/vsftpd\_login.dbchmod 700 /etc/vsftpd/vsftpd\_login.db | | --- | 1. 配置PAM认证文件,/etc/pam.d/vsftpd行首加入如下两行: | auth required pam\_userdb.so db\=/etc/vsftpd/vsftpd\_loginaccount required pam\_userdb.so db\=/etc/vsftpd/vsftpd\_login | | --- | 1. 所有Vsftpd虚拟用户需要映射到一个系统用户,该系统用户不需要密码,也不需要登录,主要用于虚拟用户映射使用,创建命令如下: | useradd \-s /sbin/nologin ftpuser | | --- | 1. 完整vsftpd.conf配置文件代码如下: | \#global config Vsftpd 2022anonymous\_enable\=YESlocal\_enable\=YESwrite\_enable\=YESlocal\_umask\=022dirmessage\_enable\=YESxferlog\_enable\=YESconnect\_from\_port\_20\=YESxferlog\_std\_format\=YESlisten\=NOlisten\_ipv6\=YESuserlist\_enable\=YEStcp\_wrappers\=YES\#config virtual user FTPpam\_service\_name\=vsftpdguest\_enable\=YESguest\_username\=ftpuseruser\_config\_dir\=/etc/vsftpd/vsftpd\_user\_confvirtual\_use\_local\_privs\=YES | | --- | 如上Vsftpd虚拟用户配置文件参数详解: | \#config virtual user FTPpam\_service\_name\=vsftpd 虚拟用户启用pam认证;guest\_enable\=YES 启用虚拟用户;guest\_username\=ftpuser 映射虚拟用户至系统用户ftpuser;user\_config\_dir\=/etc/vsftpd/vsftpd\_user\_conf 设置虚拟用户配置文件所在的目录;virtual\_use\_local\_privs\=YES 虚拟用户使用与本地用户相同的权限。 | | --- | 1. 至此,所有虚拟用户共同基于/home/ftpuser主目录实现文件上传与下载,可以在/etc/vsftpd/vsftpd\_user\_conf目录创建虚拟用户各自的配置文件,创建虚拟用户配置文件主目录: | mkdir \-p /etc/vsftpd/vsftpd\_user\_conf/ | | --- | 1. 如下分别为虚拟用户jfedu001、jfedu002用户创建配置文件: vim /etc/vsftpd/vsftpd\_user\_conf/jfedu001,同时创建私有的虚拟目录,代码如下: | local\_root\=/home/ftpuser/jfedu001write\_enable\=YESanon\_world\_readable\_only\=YESanon\_upload\_enable\=YESanon\_mkdir\_write\_enable\=YESanon\_other\_write\_enable\=YES | | --- | vim /etc/vsftpd/vsftpd\_user\_conf/jfedu002,同时创建私有的虚拟目录,代码如下: | local\_root\=/home/ftpuser/jfedu002write\_enable\=YESanon\_world\_readable\_only\=YESanon\_upload\_enable\=YESanon\_mkdir\_write\_enable\=YESanon\_other\_write\_enable\=YES | | --- | 虚拟用户配置文件内容详解: | local\_root\=/home/ftpuser/jfedu002 jfedu002虚拟用户配置文件路径;write\_enable\=YES 允许登陆用户有写权限; anon\_world\_readable\_only\=YES 允许匿名用户下载,然后读取文件;anon\_upload\_enable\=YES 允许匿名用户上传文件权限,只有在write\_enable\=YES时该参数才生效;anon\_mkdir\_write\_enable\=YES 允许匿名用户创建目录,只有在write\_enable\=YES时该参数才生效;anon\_other\_write\_enable\=YES 允许匿名用户其他权限,例如删除、重命名等。 | | --- | 1. 创建虚拟用户各自虚拟目录: | mkdir \-p /home/ftpuser/{jfedu001,jfedu002} ;chown \-R ftpuser:ftpuser /home/ftpuser | | --- | 重启Vsftpd服务,通过Windows客户端资源管理器登录Vsftpd服务端,测试结果如图8\-8(a)、8\-8(b)所示: ![](/media/202411/20241125143336968229.png)图8\-8(a) jfedu001虚拟用户登录FTP服务器 ![](/media/202411/20241125143336973353.png)图8\-8(b) jfedu001虚拟用户上传下载文件 # Apache WEB服务器企业实战 万维网 (WORLD WIDE WEB,WWW)服务器,也称之为WEB服务器,主要[功能](http://baike.baidu.com/view/587727.htm" \t "http://baike.baidu.com/_blank)是提供网上[信息](http://baike.baidu.com/view/1527.htm" \t "http://baike.baidu.com/_blank)浏览服务。WWW是 [Internet](http://baike.baidu.com/view/11165.htm" \t "http://baike.baidu.com/_blank)的多媒体信息查询工具,是Internet上飞快发展的服务,也是目前用的最广泛的服务。正是因为有了WWW软件,才使得近年来 Internet 迅速发展。 目前主流的WEB服务器软件包括:Apache、Nginx、Lighttpd、IIS、Resin、Tomcat、WebLogic、Jetty等。 本章向读者介绍Apache WEB服务器发展历史、Apache工作模式深入剖析、Apache虚拟主机、配置文件详解及Apache Rewrite企业实战等。 ## Apache WEB服务器入门简介 Apache HTTP [Server](http://baike.baidu.com/view/488131.htm" \t "_blank)是[Apache软件基金会](http://baike.baidu.com/view/7044910.htm" \t "_blank)的一个开源的网页服务器,是世界使用排名第一的Web[服务器](http://baike.baidu.com/view/899.htm" \t "_blank)软件,可以运行在几乎所有广泛使用的[计算机平台](http://baike.baidu.com/view/2269685.htm" \t "_blank)上,由于其[跨平台](http://baike.baidu.com/view/469855.htm" \t "_blank)和安全性被广泛使用,是目前最流行的Web服务器端软件之一。 Apache服务器是一个多模块化的服务器,经过多次修改,成为目前世界使用排名第一的[Web服务器](http://baike.baidu.com/view/460250.htm" \t "_blank)软件。Apache取自“A Patchy Server”的读音,即充满补丁的服务器,因为Apache基于GPL发布,大量开发者不断为Apache贡献新的代码、功能、新的特性、修改原来的缺陷。 Apache服务器的特点是使用简单、速度快、性能稳定,可以做负载均衡及[代理服务器](http://baike.baidu.com/view/751.htm" \t "_blank)来使用。 ## Prefork MPM工作原理 每辆汽车都有发动机引擎,不同的引擎,对车子运行效率也不一样,同样Apache也有类似工作引擎或者处理请求的模块,亦可称之为多路处理模块(Multi\-Processing Modules,MPM),Apache WEB服务器有三种处理模块:Prefork MPM、Worker MPM、Event MPM。 在企业中最常用的处理模块为Prefork MPM和Worker MPM,Event MPM不支持HTTPS方式,官网也给出“This MPM is experimental, so it may or may not work as expected”提示,所以很少被使用。 默认Apache处理模块为Prefork MPM方式,Prefork采用的预派生子进程方式,Prefork用单独的子进程来处理不同的请求,进程之间是彼此独立的,所以比较稳定。 Prefork的工作原理:控制进程Master在最初建立“StartServers”个进程后,为了满足MinSpareServers设置的最小空闲进程,所以需创建第一个空闲进程,等待一秒钟,继续创建两个,再等待一秒钟,继续创建四个,依次按照递增指数级创建进程数,最多每秒同时创建32个空闲进程,直到满足至少有MinSpareServers设置的值为止。 Apache的预派生模式(Prefork),基于预派生模式,不必在请求到来时再产生新的进程,从而减小了系统开销以增加性能,不过由于Prefork MPM引擎是基于多进程方式提供对外服务,每个进程占内存也相对较高。 ## Worker MPM工作原理 相对于Prefork MPM,Worker方式是2\.0版中全新的支持多线程和多进程混合模型的MPM,由于使用线程来处理,所以可以处理海量的HTTP请求,而系统资源的开销要小于基于Prefork多进程的方式。Worker也是基于多进程,但每个进程又生成多个线程,这样可以保证多线程可以获得进程的稳定性。 Worker MPM工作原理:控制进程Master在最初建立“StartServers”个进程,每个进程会创建ThreadsPerChild设置的线程数,多个线程共享该进程内存空间,同时每个线程独立地处理用户的HTTP请求。为了不在请求到来时再生成线程,Worker MPM也可以设置最大最小空闲线程。 Worker MPM模式下同时处理的请求总数\=进程总数xThreadsPerChild,也即等于MaxClients。如果服务器负载很高,当前进程数不满足需求,Master控制进程会fork新的进程,最大进程数不能超过ServerLimit数,如果需调整的StartServers进程数,需同时调整ServerLimit值。 Prefork MPM与Worker MPM引擎区别小结如下: * Prefork MPM模式:使用多个进程,每个进程只有一个线程,每个进程在某个确定的时间只能维持一个连接,稳定,内存开销较高; * Worker MPM模式:使用多个进程,每个子进程包含多个线程,每个线程在某个确定的时间只能维持一个连接,内存占用量比较小,适合大并发、高流量的WEB服务器。Worker MPM缺点是一个线程崩溃,整个进程就会连同其任何线程一起挂掉。 ## Apache WEB服务器安装 从Apache官方分站点下载目前稳定版本httpd\-2\.2\.32版本,目前最新版本为2\.4版本,下载地址如下: | [http://mirrors.hust.edu.cn/apache/httpd/httpd\-2\.2\.32\.tar.bz2](http://mirrors.hust.edu.cn/apache/httpd/httpd-2.2.32.tar.bz2) | | --- | Apache WEB服务器安装步骤如下: | tar \-xjvf httpd\-2\.2\.32\.tar.bz2 tar工具解压httpd包;cd httpd\-2\.2\.32/ 进入解压后目录;yum install apr apr\-devel apr\-util apr\-util\-devel \-y 安装APR相关优化模块;./configure \-\-prefix\=/usr/local/apache2/ \-\-enable\-rewrite \-\-enable\-so \-\-enable\-mpms\-shared\=all \-\-with\-mpm\=event预编译Apache,启用rewrite规则、启用动态加载库、开启Apache三种工作引擎,如果开启模块支持,需要添加配置:\#LoadModule mpm\_prefork\_module modules/mod\_mpm\_prefork.so\#LoadModule mpm\_event\_module modules/mod\_mpm\_event.so\#LoadModule mpm\_worker\_module modules/mod\_mpm\_worker.somake 编译make install 安装 | | --- | Apache2\.2\.32安装完毕,如图10\-1所示: ![](/media/202411/20241125143336982857.png) 图10\-1 Apache2\.2\.32安装图解 启动Apache服务,临时关闭selinux、firewalld防火墙: | /usr/local/apache2/bin/apachectl startsetenforce 0systemctl stop firewalld.service | | --- | 查看Apache服务进程,通过客户端浏览器访问[http://192\.168\.111\.131/](http://192.168.111.131/),如图10\-2(a)、10\-2(b)所示: ![](/media/202411/20241125143336988689.png)图10\-2(a) Apache启动及查看进程 ![](/media/202411/20241125143336993555.png) 图10\-2(b) 浏览器访问Apache WEB服务器 ## Apache虚拟主机企业应用 企业真实环境中,一台WEB服务器发布单个网站会非常浪费资源,所以一台WEB服务器上会发布多个网站,少则3\-5个,多则2\-30个网站。 在一台服务器上发布多网站,也称之为部署多个虚拟主机,WEB虚拟主机配置方法有三种: * 基于单IP多个Socket端口; * 基于多IP地址一个端口; * 基于单IP一个端口不同域名。 其中基于同一端口不同域名的方式在企业中得到广泛的使用和应用,如下为基于一个端口不同域名,在一台Apache WEB服务器上部署多个网站,步骤如下: 1. 创建虚拟主机配置文件httpd\-vhosts.conf,该文件默认已存在,只需去掉httpd.conf配置文件中\#号即可,如图10\-3所示: ![](/media/202411/20241125143336998906.png)图10\-3 httpd.conf配置文件开启虚拟主机 1. 配置文件/usr/local/apache2/conf/extra/httpd\-vhosts.conf中代码设置为如下: | NameVirtualHost \*:80\<VirtualHost \*:80\> ServerAdmin support@jfedu.net DocumentRoot "/usr/local/apache2/htdocs/jf1" ServerName www.jf1\.com ErrorLog "logs/www.jf1\.com\_error\_log" CustomLog "logs/www.jf1\.com\_access\_log" common\</VirtualHost\>\<VirtualHost \*:80\> ServerAdmin support@jfedu.net DocumentRoot "/usr/local/apache2/htdocs/jf2" ServerName www.jf2\.com ErrorLog "logs/www.jf2\.com\_error\_log" CustomLog "logs/www.jf2\.com\_access\_log" common\</VirtualHost\> | | --- | Httpd\-vhosts.conf参数详解: | NameVirtualHost \*:80 开启虚拟主机,并且监听本地所有网卡接口的80端口;\<VirtualHost \*:80\> 虚拟主机配置起始; ServerAdmin support@jfedu.net 管理员邮箱; DocumentRoot "/usr/local/apache2/htdocs/jf1" 该虚拟主机发布目录; ServerName www.jf1\.com 虚拟主机完整域名; ErrorLog "logs/www.jf1\.com\_error\_log" 错误日志路径及文件名; CustomLog "logs/www.jf1\.com\_access\_log" common 访问日志路径及文件名;\</VirtualHost\> 虚拟主机配置结束。 | | --- | 1. 创建www.jf1\.com及www.jf2\.com发布目录,重启apache服务,并分别创建index.html页面: | mkdir \-p /usr/local/apache2/htdocs/{jf1,jf2}//usr/local/apache2/bin/apachectl restartecho "\<h1\> www.jf1\.com Pages\</h1\>" \>/usr/local/apache2/htdocs/jf1/index.htmlecho "\<h1\> www.jf2\.com Pages\</h1\>" \>/usr/local/apache2/htdocs/jf2/index.html | | --- | 1. Windows客户端设置Hosts映射,将[www.jf1\.com](http://www.jf1.com)、[www.jf2\.com与192\.168\.111\.131](http://www.jf2.com与192.168.111.131) IP进行映射绑定,映射的目的将域名跟IP进行绑定,在浏览器可以输入域名,不需要输入IP地址,绑定方法是在“C:\\Windows\\System32\\drivers\\etc”文件夹中,使用记事本编辑hosts文件,加入如下代码,如图10\-4所示: | 192\.168\.111\.131 www.jf1\.com192\.168\.111\.131 www.jf2\.com | | --- | ![](/media/202411/20241125143337006363.png)图10\-4 Windows主机Hosts配置 1. 浏览器访问www.jf1\.com、www.jf2\.com如图10\-5(a)、10\-5(b)所示,至此Apache基于多域名虚拟主机配置完毕,如果还需添加虚拟主机,直接拷贝其中一个虚拟主机配置、修改WEB发布目录即可: ![](/media/202411/20241125143337011918.png)图10\-5(a) [www.jf1\.com](http://www.jf1.com)网站返回内容 ![](/media/202411/20241125143337017619.png)图10\-5(b) [www.jf2\.com](http://www.jf2.com)网站返回内容 ## Apache常用目录学习 Apache可以基于源码安装、YUM安装,不同的安装方法,所属的路径特不同,如下为Apache常用路径的功能用途: | /usr/lib64/httpd/modules/ Apache模块存放路径;/var/www/html/ YUM安装Apache网站发布目录;/var/www/error/ 服务器设置错误信息,浏览器显示;var/www/icons/ Apache小图标文件存放目录;var/www/cgi\-bin/ 可执行的CGI程序存放目录。/var/log/httpd/ Apache日志目录;/usr/sbin/apachectl Apache启动脚本;/usr/sbin/httpd Apache二进制执行文件;/usr/bin/htpasswd 设置Apache目录密码访问;/usr/local/apache2/bin Apache命令目录;/usr/local/apache2/build Apache构建编译目录;/usr/local/apache2/htdocs/ 源码安装Apache网站发布目录;/usr/local/apache2/cgi\-bin 可执行的CGI程序存放目录;/usr/local/apache2/include Apache引用配置文件目录;/usr/local/apache2/logs Apache日志目录;/usr/local/apache2/man Apache帮助文档目录;/usr/local/apache2/manual Apache手册;/usr/local/apache2/modules Apache模块路径。 | | --- | ## Apache配置文件详解 Apache的配置文件是Apache WEB难点,读者需要掌握配置文件中每个参数的含义,才能理解并在日常运维中去解决Apache遇到的故障,如下为Apache配置文件详解: | ServerTokens OS 显示服务器的版本和操作系统内核版本;ServerRoot "/usr/local/apache2/" Apache主配置目录;PidFile run/httpd.pid PidFile进程文件;Timeout 60 不论接收或发送,当持续连接等待超过60秒则该次连接就中断;KeepAlive Off 关闭持续性的连接;MaxKeepAliveRequests 100 当KeepAlive设置为On的时候,该数值可以决定此次连接能够传输的最大传输数量;KeepAliveTimeout 65 当KeepAlive设置为On的时候,该连接在最后一次传输后等待延迟的秒数;\<IfModule prefork.c\> Prefork MPM引擎配置段;StartServers 8 默认启动Apache工作进程数;MinSpareServers 5 最小空闲进程数;MaxSpareServers 20 最大空闲进程数;ServerLimit 4096 Apache服务器最多进程数;MaxClients 4096 每秒支持的最大客户端并发;MaxRequestsPerChild 4000 每个进程能处理的最大请求数;\</IfModule\>\<IfModule worker.c\> Worker MPM引擎配置段;StartServers 8 默认启动Apache工作进程数;MaxClients 4000 每秒支持的最大客户端并发;MinSpareThreads 25 最小空闲线程数;MaxSpareThreads 75 最小空闲线程数;ThreadsPerChild 75 每个进程启动的线程数;MaxRequestsPerChild 0 每个进程能处理的最大请求数,0表示无限制;\</IfModule\>LoadModule mod\_version.so 静态加载apache相关模块;ServerAdmin support@jfedu.net 管理员邮箱,网站异常,错误信息会发生至该邮箱;DocumentRoot "/usr/local/apache2/htdocs/" Apache网站默认发布目录;\<Directory "/data/webapps/www1"\> 设置/data/webapps/www1目录权限; AllowOverride All Options \-Indexes FollowSymLinks Order allow,deny Allow from all\</Directory\>AllowOverride 设置为None时,目录中.htaccess 文件将被完全忽略,当指令设置为All时,.htaccess文件生效;Options \-Indexes FollowSymLinks 禁止浏览目录,去掉”\-“,表示浏览目录,常用于下载站点;Order allow,deny 默认情况下禁止所有客户机访问;Order deny,allow 默认情况下允许所有客户机访问;Allow from all 允许所有客户机访问。 | | --- | ## Apache Rewrite规则实战 Rewirte规则也称为规则重写,主要功能是实现浏览器访问HTTP URL的跳转,其正则表达式是基于Perl语言。通常而言,几乎所有的WEB服务器均可以支持URL重写。Rewrite URL规则重写的用途: * 对搜索引擎优化(Search Engine Optimization,SEO)友好,利于搜索引擎抓取网站页面; * 隐藏网站URL真实地址,浏览器显示更加美观; * 网站变更升级,可以基于Rewrite临时重定向到其他页面。 Apache WEB服务器如需要使用Rewrite功能,须添加Rewrite模块,基于源码安装是指定参数“\-\-enable\-rewrite”,还有一种方法可以动态添加模块,以DSO模式安装Apache,利用模块源码和Apache apxs工具完成Rewrite模块的添加。 使用Apache Rewrite,除了安装Rewrite模块之外,还需在httpd.conf中的全局配置段或者虚拟主机配置段设置如下指令来开启Rewrite功能: | RewriteEngine on | | --- | Apache Rewrite规则使用中有三个概念需要理解,分别是:Rewrite结尾标识符、Rewrite规则常用表达式、Apache Rewrite变量,如下为三个概念的详解: 1. Apache Rewrite结尾标识符,用于Rewrite规则末尾,表示规则的执行属性。 | R\[\=code](force redirect) 强制外部重定向;G(force URL to be gone) 强制URL为GONE,返回410HTTP状态码;P(force proxy) 强制使用代理转发;L(last rule) 匹配当前规则为最后一条匹配规则,停止匹配后续规则;N(next round) 重新从第一条规则开始匹配;C(chained with next rule) 与下一条规则关联;T\=MIME\-type(force MIME type) 强制MIME类型;NC(no case) 不区分大小写。 | | --- | 1. Apache Rewrite规则常用表达式,主要用于匹配参数、字符串及过滤设置。 | . 匹配任何单字符;\[word] 匹配字符串:word;\[^word] 不匹配字符串:word;jfedu\|jfteach 可选择的字符串:jfedu\|jfteach;? 匹配0到1个字符;\* 匹配0到多个字符;\+ 匹配1到多个字符;^ 字符串开始标志;$ 字符串结束标志;\\n 转义符标志。 | | --- | 1. Apache Rewrite变量,常用于匹配HTTP请求头信息、浏览器主机名、URL等。 | HTTP headers:HTTP\_USER\_AGENT, HTTP\_REFERER, HTTP\_COOKIE, HTTP\_HOST, HTTP\_ACCEPT;connection \& request: REMOTE\_ADDR, QUERY\_STRING;server internals: DOCUMENT\_ROOT, SERVER\_PORT, SERVER\_PROTOCOL;system stuff: TIME\_YEAR, TIME\_MON, TIME\_DAY。详解如下:HTTP\_USER\_AGENT 用户使用的代理,例如浏览器;HTTP\_REFERER 告知服务器,从哪个页面来访问的;HTTP\_COOKIE 客户端缓存,主要用于存储用户名和密码等信息;HTTP\_HOST 匹配服务器ServerName域名;HTTP\_ACCEPT 客户端的浏览器支持的MIME类型; REMOTE\_ADDR 客户端的IP地址QUERY\_STRING URL中访问的字符串;DOCUMENT\_ROOT 服务器发布目录;SERVER\_PORT 服务器端口;SERVER\_PROTOCOL 服务器端协议;TIME\_YEAR 年;TIME\_MON 月;TIME\_DAY 日; | | --- | 1. Rewrite规则实战案例,以下配置均配置在httpd.conf或者vhosts.conf中,企业中常用的Rewrite案例如下: 2. 将jfedu.net跳转至www.jfedu.net。 | RewriteEngine on 启用rewrite引擎;RewriteCond %{HTTP\_HOST} ^jfedu.net \[NC] 匹配以jfedu.net开头的域名,NC忽略大小写;RewriteRule ^/(.\*)$ [http://www.jfedu.net/$1](http://www.wugk1.com/$1) \[L] (.\*)表示任意字符串,$1表示引用(.\*)的中任意内容。 | | --- | 1. 将[www.jf1\.com](http://www.jf1.com) [www.jf2\.com](http://www.jf2.com) jfedu.net跳转至[www.jfedu.net](http://www.jfedu.net),OR含义表示或者。 | RewriteEngine on RewriteCond %{HTTP\_HOST} www.jf1\.com \[NC,OR]RewriteCond %{HTTP\_HOST} www.jf2\.com \[NC,OR]RewriteCond %{HTTP\_HOST} ^jfedu.net \[NC]RewriteRule ^/(.\*)$ <http://www.jfedu.net/$1> \[L] | | --- | 1. 访问[www.jfedu.net](http://www.jfedu.net)首页,跳转至[www.jfedu.net/newindex/](http://www.jfedu.net/newindex/),R\=301表示永久重定向。 | RewriteEngine onRewriteRule ^/$ <http://www.jfedu.net/newindex/> \[L,R\=301] | | --- | 1. 访问/newindex/plus/view.php?aid\=71跳转至http://www.jfedu.net/linux/。 | RewriteEngine onRewriteCond %{QUERY\_STRING} ^tid\=(.\+)$ \[NC]RewriteRule ^/forum\\.php$ /jfedu/thread\-new\-%1\.html? \[R\=301,L] | | --- | 1. 访问[www.jfedu.net](http://www.jfedu.net)首页,内容访问[www.jfedu.net/newindex/](http://www.jfedu.net/newindex/),但是浏览器URL地址不改变。 | RewriteEngine on RewriteCond %{HTTP\_HOST} ^www.jfedu.net \[NC]RewriteRule ^/$ /newindex/ \[L] | | --- | 1. 访问/forum.php?tid\=107258跳转至/jfedu/thread\-new\-107258\.html。 | RewriteEngine onRewriteCond %{QUERY\_STRING} ^tid\=(.\+)$ \[NC]RewriteRule ^/forum\\.php$ /jfedu/thread\-new\-%1\.html? \[R\=301,L] | | --- | 1. 访问/xxx/123456跳转至/xxx?id\=123456。 | RewriteEngine onrewriteRule ^/(.\+)/(\\d\+)$ /$1?id\=$2 \[L,R\=301] | | --- | 1. 判断是否使用移动端访问网站,移动端访问跳转至m.jfedu.net。 | RewriteEngine onRewriteCond %{HTTP\_USER\_AGENT} ^iPhone \[NC,OR]RewriteCond %{HTTP\_USER\_AGENT} ^Android \[NC,OR]RewriteCond %{HTTP\_USER\_AGENT} ^WAP \[NC]RewriteRule ^/$ http://m.jfedu.net/index.html \[L,R\=301]RewriteRule ^/(.\*)/$ http://m.jfedu.net/$1 \[L,R\=301] | | --- | 1. 访问/10690/jfedu/123跳转至/index.php?tid/10690/items\=123,\[0\-9]表示任意一个数字,\+表示多个,(.\+)表示任何多个字符。 | RewriteEngine onRewriteRule ^/(\[0\-9]\+)/jfedu/(.\+)$ /index.php?tid/$1/items\=$2 \[L,R\=301] | | --- | # MYSQL服务器企业实战 MySQL是一个[关系型数据库管理系统](http://baike.baidu.com/view/1450387.htm" \t "_blank),由瑞典 MySQL AB 公司开发,目前属于 [Oracle](http://baike.baidu.com/view/15020.htm" \t "_blank) 旗下公司。MySQL 最流行的[关系型数据库管理系统](http://baike.baidu.com/view/1450387.htm" \t "_blank),在 WEB 应用方面 MySQL 是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件之一。 本章向读者介绍关系型数据库特点、MySQL数据库引擎特点、数据库安装配置、SQL案例操作、数据库索引、慢查询、MySQL数据库集群实战等。 ## MYSQL数据库入门简介 MySQL 是一种关联[数据库管理系统](http://baike.baidu.com/view/68446.htm" \t "_blank),关联数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。MySQL 所使用的 SQL 语言是用于访问数据库的最常用标准化语言。 MySQL数据库主要用于存储各类信息数据,例如:员工姓名、身份证ID、商城订单及金额、销售业绩及报告,学生考试成绩、网站帖子、论坛用户信息、系统报表等等。 MySQL 软件采用了双授权政策,它分为社区版和商业版,由于其体积小、速度快、总体拥有成本低,尤其是[开放源码](http://baike.baidu.com/view/394804.htm" \t "_blank)这一特点,一般中小型网站的开发都选择 MySQL 作为网站数据库。由于其社区版的性能卓越,搭配 [PHP](http://baike.baidu.com/view/99.htm" \t "_blank) 和 [Apache](http://baike.baidu.com/view/28283.htm" \t "_blank) 可组成良好的开发环境。 关系数据库管理系统(Relational Database Management System,RDBMS),是将数据[组织](http://baike.baidu.com/subview/46944/5892743.htm" \t "_blank)为相关的行和列的[系统](http://baike.baidu.com/view/25302.htm" \t "_blank),而管理关系数据库的计算机软件就是关系数据库管理系统,常用的关系型[数据库](http://baike.baidu.com/view/1088.htm" \t "_blank)软件有MYSQL、Mariadb、[Oracle](http://baike.baidu.com/view/15020.htm" \t "_blank)、[SQL Server](http://baike.baidu.com/view/9644.htm" \t "_blank)、PostgreSQL、DB2等。) RDBMS数据库的特点如下: * 数据以表格的形式出现; * 每行记录数据的真实内容; * 每列记录数据真实内容的数据域; * 无数的行和列组成一张表; * 若干的表组成一个数据库; 目前主流架构LAMP(Linux\+Apache\+MySQL\+PHP),MySQL更是得到各位IT运维、DBA的青睐,虽然MySQL数据库已被Orcacle公司收购,不过好消息是原来MySQL创始人已独立出来自己重新开发了MariaDB数据库,开源免费,目前越来越多的人开始尝试使用。MariaDB数据库兼容MySQL数据库所有的功能和相关参数。 MySQL数据库运行在服务器前,需要选择启动的引擎,好比一辆轿车,性能好的发动机会提升轿车的性能,从而启动、运行更加的高效。同样MYSQL也有类似发动机引擎,这里称之为MYSQL引擎。 MYSQL引擎包括:ISAM、MyISAM、InnoDB 、MEMORY、CSV、BLACKHOLE、ARCHIVE、PERFORMANCE\_SCHEMA、Berkeley、Merge、Federated、Cluster/NDB等,其中MyISAM、InnoDB使用最为广泛,如下为Myisam BDB Memory InnoDB Archive引擎功能的对比: | **引擎特性** | **Myisam** | **BDB** | **Memory** | **InnoDB** | **Archive** | | --- | --- | --- | --- | --- | --- | | 批量插入的速度 | 高 | 高 | 高 | 中 | 非常高 | | 集群索引 | 不支持 | 不支持 | 不支持 | 支持 | 不支持 | | 数据缓存 | 不支持 | 不支持 | 支持 | 支持 | 不支持 | | 索引缓存 | 支持 | 不支持 | 支持 | 支持 | 不支持 | | 数据可压缩 | 支持 | 不支持 | 不支持 | 不支持 | 支持 | | 硬盘空间使用 | 低 | 低 | NULL | 高 | 非常低 | | 内存使用 | 低 | 低 | 中等 | 高 | 低 | | 外键支持 | 不支持 | 不支持 | 不支持 | 支持 | 不支持 | | 存储限制 | 没有 | 没有 | 有 | 64TB | 没有 | | 事务安全 | 不支持 | 支持 | 不支持 | 支持 | 不支持 | | 锁机制 | 表锁 | 页锁 | 表锁 | 行锁 | 行锁 | | B树索引 | 支持 | 支持 | 支持 | 支持 | 不支持 | | 哈希索引 | 不支持 | 不支持 | 支持 | 支持 | 不支持 | | 全文索引 | 支持 | 不支持 | 不支持 | 不支持 | 不支持 | 性能总结:[MyISAM](http://baike.baidu.com/view/1238940.htm" \t "_blank) MySQL 5\.0 之前的默认数据库引擎,最为常用。拥有较高的插入,查询速度,但不支持[事务](http://baike.baidu.com/view/121511.htm" \t "_blank); [InnoDB](http://baike.baidu.com/view/1238935.htm" \t "_blank)事务型数据库的首选引擎,支持ACID事务,ACID包括:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability),一个支持事务(Transaction)的数据库,必需要具有这四种[特性](http://baike.baidu.com/item/%E7%89%B9%E6%80%A7" \t "_blank),否则在执行事务过程无法保证数据的正确性。 MYSQL5\.5之后默认引擎为InnoDB,Innodb支持行级锁定, 支持事物、外键等功能。 [BDB](http://baike.baidu.com/view/1303712.htm" \t "_blank)源自 Berkeley DB,事务型数据库的另一种选择,支持Commit 和Rollback 等其他事务特性; Memory所有数据置于内存的存储引擎,拥有极高的插入,更新和查询效率。但是会占用和数据量成正比的内存空间。并且其内容会在 MySQL 重新启动时丢失; Mysql常用的两大引擎有MyISAM和innoDB,那他们有什么明显的区别呢,什么场合使用什么引擎呢? MyISAM类型的数据库表强调的是性能,其执行数度比InnoDB类型更快,但不提供事务支持,不支持外键,如果执行大量的SELECT(查询)操作,MyISAM是更好的选择,支持表锁。 InnoDB提供事务支持事务、外部键、行级锁等高级数据库功能,执行大量的INSERT或UPDATE,出于性能方面的考虑,可以考虑使用InnoDB引擎。 ## Mysql数据库安装方式 MySQL数据库安装方法有两种,一种是yum/rpm通过YUM源在线安装,另外一种是通过源码软件编译安装。 1. YUM方式安装MYSQL方法,执行命令: | yum install mysql\-server mysql\-devel mysql\-libs \-y CentOS6\.x YUM安装yum install mariadb\-server mariadb mariadb\-libs \-y CentOS7\.x YUM安装 | | --- | 1. 源码安装MYSQL5\.5\.20方法,通过cmake、make、make install三个步骤实现。 | wget [http://down1\.chinaunix.net/distfiles/mysql\-5\.5\.20\.tar.gz](http://down1.chinaunix.net/distfiles/mysql-5.5.20.tar.gz) yum \-y install gcc\-c\+\+ ncurses\-devel cmake make perl gcc autoconf automake zlib libxml2 libxml2\-devel libgcrypt libtool bisontar \-xzf mysql\-5\.5\.20\.tar.gzcd mysql\-5\.5\.20cmake . \-DCMAKE\_INSTALL\_PREFIX\=/usr/local/mysql56/ \\\-DMYSQL\_UNIX\_ADDR\=/tmp/mysql.sock \\\-DMYSQL\_DATADIR\=/data/mysql/ \\\-DSYSCONFDIR\=/etc \\\-DMYSQL\_USER\=mysql \\\-DMYSQL\_TCP\_PORT\=3306 \\\-DWITH\_XTRADB\_STORAGE\_ENGINE\=1 \\\-DWITH\_INNOBASE\_STORAGE\_ENGINE\=1 \\\-DWITH\_PARTITION\_STORAGE\_ENGINE\=1 \\\-DWITH\_BLACKHOLE\_STORAGE\_ENGINE\=1 \\\-DWITH\_MYISAM\_STORAGE\_ENGINE\=1 \\\-DWITH\_READLINE\=1 \\\-DENABLED\_LOCAL\_INFILE\=1 \\\-DWITH\_EXTRA\_CHARSETS\=1 \\\-DDEFAULT\_CHARSET\=utf8 \\\-DDEFAULT\_COLLATION\=utf8\_general\_ci \\\-DEXTRA\_CHARSETS\=all \\\-DWITH\_BIG\_TABLES\=1 \\\-DWITH\_DEBUG\=0makemake install | | --- | 1. 源码安装MYSQL5\.7\.20方法,通过cmake、make、make install三个步骤实现。 | wget [http://nchc.dl.sourceforge.net/project/boost/boost/1\.59\.0/boost\_1\_59\_0\.tar.gz](http://nchc.dl.sourceforge.net/project/boost/boost/1.59.0/boost_1_59_0.tar.gz) tar zxvf boost\_1\_59\_0\.tar.gz mv boost\_1\_59\_0 /usr/local/boostyum \-y install gcc\-c\+\+ ncurses\-devel cmake make perl gcc autoconf automake zlib libxml2 libxml2\-devel libgcrypt libtool bisoncmake . \-DCMAKE\_INSTALL\_PREFIX\=/usr/local/mysql5/ \\\-DMYSQL\_UNIX\_ADDR\=/tmp/mysql.sock \\\-DMYSQL\_DATADIR\=/data/mysql/ \\\-DSYSCONFDIR\=/etc \\\-DMYSQL\_USER\=mysql \\\-DMYSQL\_TCP\_PORT\=3306 \\\-DWITH\_XTRADB\_STORAGE\_ENGINE\=1 \\\-DWITH\_INNOBASE\_STORAGE\_ENGINE\=1 \\\-DWITH\_PARTITION\_STORAGE\_ENGINE\=1 \\\-DWITH\_BLACKHOLE\_STORAGE\_ENGINE\=1 \\\-DWITH\_MYISAM\_STORAGE\_ENGINE\=1 \\\-DWITH\_READLINE\=1 \\\-DENABLED\_LOCAL\_INFILE\=1 \\\-DWITH\_EXTRA\_CHARSETS\=1 \\\-DDEFAULT\_CHARSET\=utf8 \\\-DDEFAULT\_COLLATION\=utf8\_general\_ci \\\-DEXTRA\_CHARSETS\=all \\\-DWITH\_BIG\_TABLES\=1 \\\-DWITH\_DEBUG\=0 \\\-DDOWNLOAD\_BOOST\=1 \\\-DWITH\_BOOST\=/usr/local/boostmakemake install/usr/local/mysql5/bin/mysqld \-\-initialize \-\-user\=mysql \-\-basedir\=/usr/local/mysql5 \-\-datadir\=/data/mysql | | --- | 1. MYSQL源码安装参数详解 | cmake . \-DCMAKE\_INSTALL\_PREFIX\=/usr/local/mysql55 Cmake预编译;\-DMYSQL\_UNIX\_ADDR\=/tmp/mysql.sock MYSQL Socket通信文件位置;\-DMYSQL\_DATADIR\=/data/mysql MYSQL数据存放路径;\-DSYSCONFDIR\=/etc 配置文件路径; \-DMYSQL\_USER\=mysql MYSQL运行用户; \-DMYSQL\_TCP\_PORT\=3306 MYSQL监听端口;\-DWITH\_XTRADB\_STORAGE\_ENGINE\=1 开启xtradb引擎支持;\-DWITH\_INNOBASE\_STORAGE\_ENGINE\=1 开启innodb引擎支持;\-DWITH\_PARTITION\_STORAGE\_ENGINE\=1 开启partition引擎支持;\-DWITH\_BLACKHOLE\_STORAGE\_ENGINE\=1 开启blackhole引擎支持;\-DWITH\_MYISAM\_STORAGE\_ENGINE\=1 开启MyISAM引擎支持;\-DWITH\_READLINE\=1 启用快捷键功能; \-DENABLED\_LOCAL\_INFILE\=1 允许从本地导入数据;\-DWITH\_EXTRA\_CHARSETS\=1 支持额外的字符集; \-DDEFAULT\_CHARSET\=utf8 默认字符集UTF\-8; \-DDEFAULT\_COLLATION\=utf8\_general\_ci 检验字符; \-DEXTRA\_CHARSETS\=all 安装所有扩展字符集;\-DWITH\_BIG\_TABLES\=1 将临时表存储在磁盘上;\-DWITH\_DEBUG\=0 禁止调试模式支持; make 编译; make install 安装。 | | --- | 1. 将源码安装的Mysql数据库服务设置为系统服务,可以使用chkconfig管理,并启动MYSQL数据库,如图11\-1所示: | cd /usr/local/mysql55/ \\cp support\-files/my\-large.cnf /etc/my.cnf\\cp support\-files/mysql.server /etc/init.d/mysqld chkconfig \-\-add mysqld chkconfig \-\-level 35 mysqld onmkdir \-p /data/mysqluseradd mysql/usr/local/mysql55/scripts/mysql\_install\_db \-\-user\=mysql \-\-datadir\=/data/mysql/ \-\-basedir\=/usr/local/mysql55/ln \-s /usr/local/mysql55/bin/\* /usr/bin/service mysqld restart | | --- | ![](/media/202411/20241125143337059967.png) 图11\-1 查看MYSQL启动进程 1. 不设置为系统服务,也可以用源码启动方式。 | cd /usr/local/mysql55mkdir –p /data/mysqluseradd mysql/usr/local/mysql55/scripts/mysql\_install\_db \-\-user\=mysql \-\-datadir\=/data/mysql/ \-\-basedir\=/usr/local/mysql55/ln \-s /usr/local/mysql55/bin/\* /usr/bin//usr/local/mysql55/bin/mysqld\_safe \-\-user\=mysql \& | | --- | ## Mysql数据库必备命令操作 MySQL数据库安装完毕之后,对MYSQL数据库中各种指令的操作变得尤为重要,熟练掌握MYSQL必备命令是SA、DBA必备工作之一,如下为MYSQL数据库中操作必备命令,所有操作指令均在MYSQL命令行中操作,不能在Linux Shell解释器上直接运行: 直接在Shell终端执行命令:mysql或者/usr/local/mysql55/bin/mysql,按Enter键,进入MYSQL命令行界面如图11\-2所示: ![](/media/202411/20241125143337066127.png)图11\-2 MYSQL命令行界面 MYSQL命令行常用命令如下,操作结果如图11\-3(a)、11\-3(b)、11\-3(c)所示: | show databases; 查看所有的数据库;create database jfedu; 创建名为jfedu数据库;use jfedu; 进入jfedu数据库;show tables; 查看数据库里有多少张表;create table t1 (id varchar(20\),name varchar(20\)); 创建名为t1表,并创建两个字段,id、name,varchar表示设置数据长度,用字符来定义长度单位,其中1汉字\=2字符\=2Bytes;insert into t1 values ("1","jfedu"); 向表中插入数据;select \* from t1; 查看t1表数据内容;Select \* from t1 where id\=1 and age \=’jfedu’; id、age多个条件查询;desc t1; 查看t1表字段内容;alter table t1 modify column name varchar(20\); 修改name字段的长度;update t1 set name\='jfedu.net' where id\=1; 修改name字段的内容;flush privileges; 刷新权限;delete from t1 ; 清空表内容;drop table t1 ; 删除表;drop database jfedu; 删除jfedu数据库;show variables like '%char%'; 查看数据库字符集;show engines; 查看MySQL存储[引擎](http://wenwen.soso.com/z/Search.e?sp=S%E5%BC%95%E6%93%8E&ch=w.search.yjjlink&cid=w.search.yjjlink" \t "http://www.cnblogs.com/sopc-mc/archive/2011/11/01/_blank);show variables like '%storage\_engine%'; 查看MySQL默认的存储引擎;alter table t1 engine\=innodb; 修改MySQL t1表存储[引擎](http://wenwen.soso.com/z/Search.e?sp=S%E5%BC%95%E6%93%8E&ch=w.search.yjjlink&cid=w.search.yjjlink" \t "http://www.cnblogs.com/sopc-mc/archive/2011/11/01/_blank); | | --- | ![](/media/202411/20241125143337074679.png) 图11\-3(a) MYSQL命令操作 ![](/media/202411/20241125143337080700.png)图11\-3(b) MYSQL命令操作 ![](/media/202411/20241125143337086895.png)图11\-3(c) MYSQL命令操作 ## Mysql数据库字符集设置 计算机中储存的信息都是用二进制数方式来表示的,读者每天看到屏幕显示的英文、汉字等字符是二进制数转换之后的结果。通俗的说,将汉字按照某种字符集编码存储在计算机中,称为"编码"。将存储在计算机中的二进制数解析显示出来,称为"解码",在解码过程中,如果使用了错误的解码规则,会导致显示乱码。 MYSQL数据库在存储数据时,默认编码latin1,存储中文字符时,在显示或者WEB调用时会显示为乱码,为解决该乱码问题,需修改Mysql默认字符集为UTF\-8,有两种方法: 1. 编辑vim /etc/my.cnf配置文件,在相应段中加入相应的参数字符集修改完毕,重启MySQL服务即可。 | \[client]字段里加入: default\-character\-set\=utf8\[mysqld]字段里加入: character\-set\-server\=utf8\[mysql]字段里加入 : default\-character\-set\=utf8 | | --- | 1. MYSQL命令行中运行如下指令,如图11\-4所示: | show variables like '%char%';SET character\_set\_client \= utf8;SET character\_set\_results \= utf8;SET character\_set\_connection \= utf8; | | --- | ![](/media/202411/20241125143337096147.png)图11\-4 设置MYSQL数据库字符集 ## Mysql数据库密码管理 MYSQL数据库在使用过程中为了加强安全防范,需要设置密码访问,如何设置密码、及密码忘记如何破解呢,如下为设置密码授权、密码修改及密码破解的方法: 1. MYSQL创建用户及授权 | grant all on jfedu.\* to test@localhost identified by 'pas'; grant select,insert,update,delete on \*.\* to test@”%” identified by ‘pas’;grant all on jfedu.\* to test@’192\.168\.111\.118’ identified by 'pas'; | | --- | 如上三条grant语句授权参数详解如下: | 授权localhost主机通过test用户和pas密码访问本地的jfedu库的所有权限;授权所有主机通过test用户和pas密码访问本地的jfedu库的查询、插入、更新、删除权限;授权192\.168\.111\.118主机通过test用户和pas密码访问本地的jfedu库的所有权限; | | --- | 1. MYSQL密码破解方法 在使用MYSQL数据库中,偶尔会出现密码忘记,或者被其他人员修改掉数据库权限的,如果需要紧急修改密码,如何破解MYSQL密码呢,首先停止MYSQL数据库服务,以跳过权限方式启动,命令如下: | /etc/init.d/mysqld stop/usr/bin/mysqld\_safe \-\-user\=mysql \-\-skip\-grant\-tables \& | | --- | MYSQL跳过权限方式启动后,在Shell终端执行mysql命令并按Enter键,进入mysql命令行,如图11\-5所示: ![](/media/202411/20241125143337103064.png)图11\-5 跳过权限启动并登陆MYSQL 由于MYSQL用户及密码认证信息存放在mysql库中的user表,需进入mysql库,更新相应的密码字段即可,例如将MYSQL中root用户的密码均改为123456,如图11\-6所示: | use mysqlupdate user set password\=password(‘123456’) where user\=’root’; | | --- | ![](/media/202411/20241125143337108570.png)图11\-6 MYSQL密码破解方法 MYSQL root密码修改完,需停止以Mysql跳过权限表的启动进程,再以正常方式启动MYSQL,再次以新的密码登陆即可进入Mysql数据库,如图11\-7所示: ![](/media/202411/20241125143337113573.png)图11\-7 MYSQL正常方式启动 ## MySQL数据库索引案例 MySQL索引可以用来快速地寻找某些具有特定值的记录,所有MySQL索引都以B\-树的形式保存。例如MYSQL没有索引,执行select时MySQL必须从第一个记录开始扫描整个表的所有记录,直至找到符合要求的记录。如果表中数据有上亿条数据,查询一条数据花费的时间会非常长,索引的目的就类似电子书的目录及页码的对应关系。 如果在需搜索条件的列上创建了索引,MySQL无需扫描全表记录即可快速得到相应的记录行。如果该表有1000000条记录,通过索引查找记录至少要比全表顺序扫描快至少100倍,这就是索引在企业环境中带来的执行速度的提升。 MYSQL数据库常见索引类型包括:普通索引(normal)、唯一索引(unique)、全文索引(full text)、主键索引(primary key)、组合索引等,如下为每个索引的应用场景及区别: | 普通索引: normal,使用最广泛;唯一索引: unique,不允许重复的索引,允许有空值;全文索引: full text,只能用于MyISAM表,FULLTEXT主要用于大量的内容检索;主键索引: primary key又称为特殊的唯一索引,不允许有空值;组合索引: 为提高mysql效率可建立组合索引; | | --- | MYSQL数据库表创建各个索引命令,以t1表为案例,操作如下: | 主键索引 ALTER TABLE t1 ADD PRIMARY KEY ( \`column\` ); 唯一索引 ALTER TABLE t1 ADD UNIQUE (\`column\`);普通索引 ALTER TABLE t1 ADD INDEX index\_name ( \`column' );全文索引 ALTER TABLE t1 ADD FULLTEXT ( \`column\` );组合索引 ALTER TABLE t1 ADD INDEX index\_name ( \`column1\`, \`column2\`, \`column3\` ); | | --- | 如图11\-8所示,为t1表的id字段创建主键索引,查看索引是否被创建,然后插入相同的id,提示报错: ![](/media/202411/20241125143337120525.png) 图11\-8 MYSQL主键索引案例演示 MYSQL数据库表删除各个索引命令,以t1表为案例,操作如下: | DROP INDEX index\_name ON t1;ALTER TABLE t1 DROP INDEX index\_name;ALTER TABLE t1 DROP PRIMARY KEY; | | --- | MYSQL数据库查看表索引: | show index from t1;show keys from t1; | | --- | MYSQL数据库索引的缺点: * MYSQL数据库索引虽然能够提高数据库查询速度,但同时会降低更新、删除、插入表的速度,例如如对表进行INSERT、UPDATE、DELETE时,update表MySQL不仅要保存数据,还需保存更新索引; * 建立索引会占用磁盘空间,大表上创建了多种组合索引,索引文件的会占用大量的空间。 ## MySQL数据库集群实战 随着访问量的不断增加,单台MySQL数据库服务器压力不断增加,需要对MYSQL进行优化和架构改造,MYQSL优化如果不能明显改善压力情况,可以使用高可用、主从复制、读写分离来、拆分库、拆分表来进行优化。 MYSQL主从复制集群在中小企业、大型企业中被广泛使用,MYSQL主从复制的目的是实现数据库冗余备份,将Master数据库数据定时同步至Slave库中,一旦Master数据库宕机,可以将WEB应用数据库配置快速切换至Slave数据库,确保WEB应用较高的可用率,如图11\-12所示,为MYSQL主从复制结构图: ![1_conew1](/media/202411/20241125143337126339.png) 图11\-12 MYSQL主从原理架构图 Mysql主从复制集群至少需要2台数据库服务器,其中一台为Master库,另外一台为Slave库,MYSQL主从数据同步是一个异步复制的过程,要实现复制首先需要在master上开启bin\-log日志功能,bin\-log日志用于记录在Master库中执行的增、删、修改、更新操作的sql语句,整个过程需要开启3个线程,分别是Master开启IO线程,Slave开启IO线程和SQL线程,具体主从同步原理详解如下: * Slave上执行slave start,Slave IO线程会通过在Master创建的授权用户连接上至Master,并请求master从指定的文件和位置之后发送bin\-log日志内容; * Master接收到来自slave IO线程的请求后,master IO线程根据slave发送的指定bin\-log日志position点之后的内容,然后返回给slave的IO线程。 * 返回的信息中除了bin\-log日志内容外,还有master最新的binlog文件名以及在binlog中的下一个指定更新position点; * Slave IO线程接收到信息后,将接收到的日志内容依次添加到Slave端的relay\-log文件的最末端,并将读取到的Master端的 bin\-log的文件名和position点记录到master.info文件中,以便在下一次读取的时候能告知master从响应的bin\-log文件名及最后一个position点开始发起请求; * Slave Sql线程检测到relay\-log中内容有更新,会立刻解析relay\-log的内容成在Master真实执行时候的那些可执行的SQL语句,将解析的SQL语句并在Slave里执行,执行成功后,Master库与Slave库保持数据一致。 ## MySQL主从复制实战 MYSQL主从复制环境构建至少需2台服务器,可以配置1主多从,多主多从,如下为1主1从,MYSQL主从复制架构实战步骤: 1. 系统环境准备 Master:192\.168\.111\.128 Slave: 192\.168\.111\.129 1. Master安装及配置 Master端使用源码安装MySQL\-5\-5版本软件后,在/etc/my.cnf 配置文件\[mysqld]段中加入如下代码,然后重启MYSQL服务即可。如果在安装时cp my\-large.cnf /etc/my.cnf,则无需添加如下代码: | server\-id \= 1log\-bin \= mysql\-bin | | --- | Master端/etc/my.cnf完整配置代码如下: | \[client]port \= 3306socket \= /tmp/mysql.sock\[mysqld]port \= 3306socket \= /tmp/mysql.sockskip\-external\-lockingkey\_buffer\_size \= 256Mmax\_allowed\_packet \= 1Mtable\_open\_cache \= 256sort\_buffer\_size \= 1Mread\_buffer\_size \= 1Mread\_rnd\_buffer\_size \= 4Mmyisam\_sort\_buffer\_size \= 64Mthread\_cache\_size \= 8query\_cache\_size\= 16Mthread\_concurrency \= 8log\-bin\=mysql\-binbinlog\_format\=mixedserver\-id \= 1\[mysqldump]quickmax\_allowed\_packet \= 16M\[mysql]no\-auto\-rehash\[myisamchk]key\_buffer\_size \= 128Msort\_buffer\_size \= 128Mread\_buffer \= 2Mwrite\_buffer \= 2M\[mysqlhotcopy]interactive\-timeout | | --- | Master数据库服务器命令行中 创建tongbu用户及密码并设置权限,执行如下命令,查看bin\-log文件及position点,如图11\-13所示: | grant replication slave on \*.\* to 'tongbu'@'%' identified by '123456';show master status; | | --- | ![](/media/202411/20241125143337135991.png) 图11\-13 MYSQL Master授权用户 1. Slave安装及配置 Slave端使用源码安装MySQL\-5\-5版本软件后,在/etc/my.cnf 配置文件\[mysqld]段中加入如下代码,然后重启MYSQL服务即可。如果在安装时cp my\-large.cnf /etc/my.cnf,则需修改server\-id,MASTER与Slave端server\-id不能一样,Slave端也无需开启bin\-log功能: | server\-id \= 2 | | --- | Slave端/etc/my.cnf完整配置代码如下: | \[client]port \= 3306socket \= /tmp/mysql.sock\[mysqld]port \= 3306socket \= /tmp/mysql.sockskip\-external\-lockingkey\_buffer\_size \= 256Mmax\_allowed\_packet \= 1Mtable\_open\_cache \= 256sort\_buffer\_size \= 1Mread\_buffer\_size \= 1Mread\_rnd\_buffer\_size \= 4Mmyisam\_sort\_buffer\_size \= 64Mthread\_cache\_size \= 8query\_cache\_size\= 16Mthread\_concurrency \= 8server\-id \= 2\[mysqldump]quickmax\_allowed\_packet \= 16M\[mysql]no\-auto\-rehash\[myisamchk]key\_buffer\_size \= 128Msort\_buffer\_size \= 128Mread\_buffer \= 2Mwrite\_buffer \= 2M\[mysqlhotcopy]interactive\-timeout | | --- | Slave指定Master IP、用户名、密码、bin\-log文件名(mysql\-bin.000028)及position(257),代码如下: | change master to master\_host\='192\.168\.1\.115',master\_user\='tongbu',master\_password\='123456',master\_log\_file\='mysql\-bin.000001',master\_log\_pos\=297; | | --- | 在slave启动slave start,并执行show slave status\\G查看Mysql主从状态: | slave start;show slave status\\G | | --- | 查看Slave端IO线程、SQL线程状态均为YES,代表Slave已正常连接Master实现同步: | Slave\_IO\_Running: YesSlave\_SQL\_Running: Yes | | --- | 执行Show slave status\\G,常见参数含义解析: | Slave\_IO\_State I/O线程连接Master状态;Master\_User 用于连接Master的用户;Master\_Port Master端监听端口;Connect\_Retry 主从连接失败,重试时间间隔;Master\_Log\_File I/O线程读取的Master二进制日志文件的名称。Read\_Master\_Log\_Pos I/O线程已读取的Master二进制日志文件的位置;Relay\_Log\_File SQL线程读取和执行的中继日志文件的名称。Relay\_Log\_Pos SQL线程已读取和执行的中继日志文件的位置;Relay\_Master\_Log\_File SQL线程执行的Master二进制日志文件的名称;Slave\_IO\_Running I/O线程是否被启动并成功地连接到主服务器上;Slave\_SQL\_Running SQL线程是否被启动;Replicate\_Do\_DB 指定的同步的数据库列表;Skip\_Counter SQL\_SLAVE\_SKIP\_COUNTER设置的值;Seconds\_Behind\_Master Slave端SQL线程和I/O线程之间的时间差距,单位为秒,常被用于主从延迟检查方法之一。 | | --- | 在Master端创建mysql\_db\_test数据库和t0表,如图11\-14所示,命令如下: | create database mysql\_ab\_test charset\=utf8;show databases;use mysql\_ab\_test;create table t0 (id varchar(20\),name varchar(20\));show tables; | | --- | ![](/media/202411/20241125143337145454.png)图11\-14 MYSQL master创建数据库和表 Slave服务器查看是否有mysql\_ab\_test数据库和t0的表,如果存在则代表Slave从Master复制数据成功,证明MYSQL主从配置至此已经配置成功,如图11\-15所示: ![](/media/202411/20241125143337151280.png)图11\-15 MYSQL Slave自动同步数据 在Master服务器的t0表插入两条数据,在slave查看是否已同步,master上执行如下图11\-16所示: | insert into t0 values (“001”,”wugk1”);insert into t0 values (“002”,”wugk2”);select \* from t0; | | --- | ![](/media/202411/20241125143337159387.png) 图11\-16 MYSQL Master insert数据 Slave端执行查询命令,如图11\-17所示,表示在Master插入的数据已经同步到Slave端: ![](/media/202411/20241125143337164427.png)图11\-17 MYSQL Slave数据已同步 ## MySQL主从同步排错思路 Mysql主从同步集群在生成环境使用过程中,如果主从服务器之间网络通信条件差或者数据库数据量非常大,容易导致MYSQL主从同步延迟。 MYSQL主从产生延迟之后,一旦主库宕机,会导致部分数据没有及时同步至丛库,重新启动主库,会导致丛库与主库同步错误,如何快速恢复主从同步关系呢,如下有两种方法: 1. 忽略错误后,继续同步: 此种方法适用于主从库数据内容相差不大,或者要求数据可以不完全统一的情况,数据要求不严格的情况。 Master端执行如下命令,将数据库设置全局读锁,不允许写入新数据: | flush tables with read lock; | | --- | Slave端停止Slave I/O及sql线程,同时将同步错误的SQL跳过1次,跳过会导致数据不一致,最后启动start slave,同步状态恢复,命令如下: | stop slave;set global sql\_slave\_skip\_counter \=1;start slave; | | --- | 1. 重新做主从同步,完全同步: 此种方法适用于主从库数据内容相差很大,或者要求数据完全统一的情况,数据需完全保持一致。 Master端执行如下命令,将数据库设置全局读锁,不允许写入新数据: | flush tables with read lock; | | --- | Master端基于mysqldump、xtrabackup工具进行数据库将完整的数据库备份,也可以用shell脚本或python脚本实现定时备份,备份成功之后,将完整的数据导入至丛库,重新配置主从关系,当Slave端的IO线程、SQL线程均为YES之后,最后将Master端读锁解开即可,解锁命令如下: | unlock tables; | | --- | # LAMP架构企业实战 Linux下LAMP(Linux\+Apache\+MySQL/MariaDB\+Perl/PHP/Python)是一组用来搭建[动态网站](http://baike.baidu.com/view/863075.htm" \t "_blank)的[开源软件](http://baike.baidu.com/view/444964.htm" \t "_blank)架构,本身是各自独立的软件服务,放在一起使用,拥有了越来越高的兼容度,共同组成了一个强大的Web[应用程序](http://baike.baidu.com/view/330120.htm" \t "_blank)平台。 本章向读者介绍互联网主流企业架构LAMP应用案例、PHP解释性语言详解、LAMP组合通信原理、LAMP企业源码架设、LAMP拓展及使用Redis提升LAMP性能优化等。 ## LAMP企业架构简介 随着开源潮流的蓬勃发展,开放源[代码](http://baike.baidu.com/view/41.htm" \t "_blank)的LAMP已经与[J2EE](http://baike.baidu.com/view/1507.htm" \t "_blank)和[.Net](http://baike.baidu.com/view/4294.htm" \t "_blank)[商业软件](http://baike.baidu.com/view/194971.htm" \t "_blank)形成三足鼎立之势,并且该软件开发的项目在软件方面的投资成本较低,因此受到整个[IT](http://baike.baidu.com/view/30.htm" \t "_blank)界的关注。LAMP架构受到大多数中小企业的运维、DBA、程序员的青睐,Apache默认只能发布静态网页,而LAMP组合可以发布静态\+PHP动态页面。 静态页面通常指不与数据库发生交互的页面,是一种基于w3c规范的一种网页书写格式,是一种统一协议语言,所以称之为静态网页。静态页面被设计好之后,一般很少去修改,不随着浏览器参数改变而内容改变,需注意的是动态的图片也是属于静态文件。从SEO角度来讲,HTML页面更有利于搜索引擎的爬行和收录。常见的静态页面以.html、.gif、.jpg、.jpeg、.bmp、.png、.ico、.txt、.js、.css等结尾。 动态页面通常指与数据库发生交互的页面,内容展示丰富,功能非常强大,实用性广。从SEO角度来讲,搜索引擎很难全面的爬行和收录动态网页,因为动态网页会随着数据库的更新、参数的变更而发生改变,常见的动态页面以.jsp、.php、.do、.asp、.cgi、.apsx等结尾。 ## Apache与PHP工作原理 LAMP企业主流架构最重要的三个环节,一是Apache WEB服务器,二是PHP(PHP: Hypertext Preprocessor),三是MYSQL数据库。 Apache WEB服务器主要是基于多模块工作,依赖PHP SAPI处理方式中的PHP\_MODULE去解析PHP结尾的文件,如图12\-1所示: ![](/media/202411/20241125143337171632.png) ![](/media/202411/20241125143337177163.png) 图12\-1 Apache\+PHP mod工作原理 PHP是一种适用于web开发的动态语言,PHP语言内核基于C语言实现包含大量组件的软件框架,是一种功能强大的解释型脚本语言。PHP底层运行机制如图12\-2所示:![](/media/202411/20241125143337183365.png) 图12\-2 PHP底层处理机制 PHP底层工作原理包括4个部分: * Zend引擎,属于PHP内核部分,它负责将PHP代码解析为可执行opcode的处理并实现相应的处理方法、实现基本的数据结构、内存分配及管理、提供了相应的api方法供外部调用,是一切的核心,所有的外围功能均围绕Zend实现。 * Extensions,围绕着Zend引擎,Extensions通过组件的方式提供各种基础服务,各种内置函数、标准库等都是通过Extension来实现。 * Sapi,服务端应用编程接口(Server Application Programming Interface,Sapi),sapi通过一系列钩子函数,基于SAPI可以让PHP与外部进行数据交互。 * 常见的SAPI编程接口处理方法包括:apache2handler:以apache作为webserver,采用MOD\_PHP模式运行时候的处理方式;cgi:webserver和PHP直接的另一种交互方式,FastCGI协议;cli:命令行调用的应用模式。 * APP代码应用,又称之为PHP代码程序,基于sapi接口生成不同的应用模式,从而被PHP引擎解析。 当用户在浏览器地址中输入域名或者域名\+PHP页面,向HTTP WEB服务器Apache发起HTTP请求,WEB服务器接受该请求,并根据其后缀判断如果请求的页面是以.php结尾,WEB服务器从硬盘或者内存中取出该PHP文件,将其发送给PHP引擎程序。 PHP引擎程序将会对WEB服务器传送过来的文件进行扫描并根据命令从后台读取、处理数据、并动态地生成相应的HTML页面。然后PHP引擎程序将生成的HTML页面返回给WEB服务器,最终WEB服务器将HTML页面返回给客户端浏览器,浏览器基于MIME类型进行解析展示给用户页面。 ## LAMP企业安装配置 构建LAMP架构有两种方法,一是使用YUM在线安装,另外一种是基于LAMP源码编译安装,YUM在线安装方法如下: | yum install httpd httpd\-devel mysql mysql\-server mysql\-devel php php\-devel php\-mysql \-yservice httpd restartservice mysqld restart | | --- | YUM方式安装简单、快捷,但如果需要添加扩展的功能和模块,需使用源码包的方式来编译安装LAMP。如下为LAMP源码编译安装的步骤: 1. Apache WEB安装,先安装apr、apr\-utils库包。 | yum install apr\-devel apr\-util\-devel \-y;cd /usr/src ; wget [http://mirror.bit.edu.cn/apache/httpd/httpd\-2\.2\.31\.tar.gz](http://mirror.bit.edu.cn/apache/httpd/httpd-2.2.27.tar.gz) tar xzf httpd\-2\.2\.31\.tar.gzcd httpd\-2\.2\.31 ./configure \-\-prefix\=/usr/local/apache \-\-enable\-so \-\-enable\-rewritemake make install | | --- | 1. MYSQL数据库安装,基于MYSQL5\.5编译安装,通过cmake、make、make install三个步骤实现。 | wget [http://down1\.chinaunix.net/distfiles/mysql\-5\.5\.20\.tar.gz](http://down1.chinaunix.net/distfiles/mysql-5.5.20.tar.gz) yum install cmake make ncurses\-devel ncurses \-ycmake . \-DCMAKE\_INSTALL\_PREFIX\=/usr/local/mysql55 \\\-DMYSQL\_UNIX\_ADDR\=/tmp/mysql.sock \\\-DMYSQL\_DATADIR\=/data/mysql \\\-DSYSCONFDIR\=/etc \\\-DMYSQL\_USER\=mysql \\\-DMYSQL\_TCP\_PORT\=3306 \\\-DWITH\_XTRADB\_STORAGE\_ENGINE\=1 \\\-DWITH\_INNOBASE\_STORAGE\_ENGINE\=1 \\\-DWITH\_PARTITION\_STORAGE\_ENGINE\=1 \\\-DWITH\_BLACKHOLE\_STORAGE\_ENGINE\=1 \\\-DWITH\_MYISAM\_STORAGE\_ENGINE\=1 \\\-DWITH\_READLINE\=1 \\\-DENABLED\_LOCAL\_INFILE\=1 \\\-DWITH\_EXTRA\_CHARSETS\=1 \\\-DDEFAULT\_CHARSET\=utf8 \\\-DDEFAULT\_COLLATION\=utf8\_general\_ci \\\-DEXTRA\_CHARSETS\=all \\\-DWITH\_BIG\_TABLES\=1 \\\-DWITH\_DEBUG\=0makemake install | | --- | 将源码安装的Mysql数据库服务设置为系统服务,可以使用chkconfig管理,并启动MYSQL数据库: | cd /usr/local/mysql55/ \\cp support\-files/my\-large.cnf /etc/my.cnf\\cp support\-files/mysql.server /etc/init.d/mysqld chkconfig \-\-add mysqld chkconfig \-\-level 35 mysqld onmkdir \-p /data/mysqluseradd mysql/usr/local/mysql55/scripts/mysql\_install\_db \-\-user\=mysql \-\-datadir\=/data/mysql/ \-\-basedir\=/usr/local/mysql55/ln \-s /usr/local/mysql55/bin/\* /usr/bin/service mysqld restart | | --- | 1. PHP服务安装,PHP需与Apache、MySQL进行整合,如图12\-3所示,参数命令如下: | cd /usr/src wget [http://mirrors.sohu.com/php/php\-5\.3\.28\.tar.bz2](http://mirrors.sohu.com/php/php-5.3.28.tar.bz2) tar jxf php\-5\.3\.28\.tar.bz2 cd php\-5\.3\.28 ;./configure \-\-prefix\=/usr/local/php5 \-\-with\-config\-file\-path\=/usr/local/php5/etc \-\-with\-apxs2\=/usr/local/apache2/bin/apxs \-\-with\-mysql\=/usr/local/mysql55/makemake install | | --- | ![](/media/202411/20241125143337195079.png) 图12\-3 LAMP源码编译整合 1. Apache\+PHP源码整合 为了能让Apache发布PHP页面,需要将PHP安装完成后的libphp5\.so模块与Apache进行整合,vim httpd.conf编辑配置文件,加入如下代码: | LoadModule php5\_module modules/libphp5\.soAddType application/x\-httpd\-php .phpDirectoryIndex index.php index.html index.htm | | --- | 1. 测试Apache\+PHP环境 创建PHP测试页面,在/usr/local/apache/htdocs目录下创建index.php测试页面,执行如下命令自动创建: | cat \>/usr/local/apache/htdocs/index.php\<\<EOF \<?phpphpinfo();?\>EOF | | --- | 重新启动Apache服务,浏览器输入 Apache WEB的IP访问,如图12\-4所示,即代表LAMP源码环境整合成功。 ![](/media/202411/20241125143337200863.png)图12\-4 Apache\+PHP测试页面 1. Discuz PHP论坛安装 LAMP源码整合完毕之后,Dicuz官网下载Discuz开源PHP软件包,将软件包解压并发布在Apache Htdocs发布目录,代码如下: | cd /usr/src ;wget [http://download.comsenz.com/DiscuzX/3\.1/Discuz\_X3\.1\_SC\_UTF8\.zip](http://download.comsenz.com/DiscuzX/3.1/Discuz_X3.1_SC_UTF8.zip) unzip Discuz\_X3\.1\_SC\_UTF8\.zip \-d /usr/local/apache/htdocs/ cd /usr/local/apache/htdocs/;\\mv upload/\* .chmod 757 \-R data/ uc\_server/ config/ uc\_client/ | | --- | 通过浏览器访问Apache WEB IP,如图12\-5所示,选择“我同意” ![](/media/202411/20241125143337206102.png) 图12\-5 Discuz安装界面一 进入如图12\-6界面,数据库安装,如果不存在则需要新建数据库并授权。 ![](/media/202411/20241125143337211284.png) 图12\-6 Discuz安装界面二 MYSQL数据库命令行中创建PHP连接MYSQL的用户及密码,命令如下: | create database discuz charset\=utf8;grant all on discuz.\* to root@'localhost' identified by "123456"; | | --- | 单击下一步,直至安装完成,浏览器自动跳转至如图12\-7所示界面: ![](/media/202411/20241125143337216384.png) 图12\-7 Discuz安装界面三 ## LAMP企业架构拓展实战 如上LAMP服务均安装至单台服务器,随着用户访问量不断的增加,单台服务器压力逐渐增加,那如何优化LAMP架构,如何拆分LAMP架构呢,怎么把Apache和MySQL分开放在不同的机器呢。 LAMP架构拆分的目的在于缓解单台服务器的压力,可以将PHP、MYSQL单独安装至多台服务器,本节将实现LAP\+MySQL的架构,也即是把MYSQL单独拆分出去。部署方法有两种: 1. YUM安装LAMP多机方案 在Apache WEB服务器只需只需如下代码: | yum install httpd httpd\-devel php\-devel php php\-mysql \-y | | --- | 在MYSQL数据库服务器只需只需如下代码: | yum install mysql\-server mysql mysql\-devel mysql\-libs \-y | | --- | 1. 源码安装LAMP多机方案 源码安装LAMP多机方式,Apache WEB服务与MYSQL数据库服务分别部署在不同的服务器即可,PHP与Apache服务部署在一台服务器,PHP编译参数时加入如下代码进行LAMP的整合,mysqlnd为PHP远程连接MYSQL数据库服务器的一种方式: | ./configure \-\-prefix\=/usr/local/php5 \\\-\-with\-mysql\=mysqlnd \-\-with\-mysqli\=mysqlnd \-\-with\-pdo\-mysql\=mysqlnd \\\-\-with\-apxs2\=/usr/local/apache2/bin/apxs make make install | | --- | ## LAMP\+Redis企业实战 LAMP在企业生产环境中,除了将MYSQL单独部署在其他服务器、由于MYSQL数据库压力会很大,还会对MYSQL实现主从复制及读写分离,同时会对PHP网站进行调优,通常PHP的优化手段包括:PHP代码本身优化、PHP配置文件优化、为PHP添加缓存模块,将PHP网站数据存入缓存等。 ### Redis入门简介 Redis是一个开源的使用ANSI [C语言](http://baike.baidu.com/view/1219.htm" \t "_blank)编写、支持网络、可基于内存亦可持久化的日志型、Key\-Value[数据库](http://baike.baidu.com/view/1088.htm" \t "_blank),并提供多种语言的API。Redis是一个key\-value[存储系统](http://baike.baidu.com/view/51839.htm" \t "_blank)。 和Memcached缓存类似,Redis支持存储的value类型相对更多,包括string(字符串)、list([链表](http://baike.baidu.com/view/549479.htm" \t "_blank))、set(集合)、zset(有序集合)和hash(哈希类型)。 Redis是一种高级key\-value数据库,它跟memcached类似,不过Redis的数据可以持久化,而且支持的数据类型很丰富,有字符串,链表,集 合和有序集合。支持在服务器端计算集合的并,交和补集(difference)等,还支持多种排序功能。Redis也被看成是一个数据结构服务器。 Redis很大程度补偿了[memcached](http://baike.baidu.com/item/memcached" \t "_blank)这类key/value存储的不足,在部分场合可以对关系数据库起到很好的补充作用。Redis提供了Java,C/C\+\+,C\#,PHP,JavaScript,Perl,Object\-C,Python,Ruby,Erlang等客户端,方便易用,得到IT人的青睐。 Redis支持主从同步,数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制,由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录,同步对读取操作的可扩展性和数据冗余很有帮助。 目前使用Redis的互联网企业有:京东、百度、腾讯、阿里巴巴、新浪、图吧、研修网等等,如表12\-1所示,为目前主流数据库简单功能对比: | 名称 | 数据库类型 | 数据存储选项 | 操作类型 | 备注 | | --- | --- | --- | --- | --- | | Redis | 内存存储,Nosql数据库 | 支持字符串、列表、集合、散列表、有序集合 | 增、删、修改、更新 | 支持分布式集群、主从同步及高可用、单线程 | | Memcached | 内存缓存数据库,键值对 | 键值之间的映射 | 增、删、修改、更新 | 支持多线程 | | MySQL | 典型关系数据库,RDBMS | 数据库由多表主成,每张表包含多行 | 增、删、修改、更新 | 支持ACID性质 | | PostgreSQL | 典型关系数据库,RDBMS | 数据库由多表主成,每张表包含多行 | 增、删、修改、更新 | 支持ACID性质 | | MongoDB | 硬盘存储,Nosql数据库 | 数据库包含多个表 | 增、删、修改、更新 | 主从复制,分片,副本集、空间索引 | 表12\-1 常见数据库功能对比 ### LAMP\+Redis工作机制 LAMP\+Redis工作机制:用户通过浏览器访问LAMP网站,并以用户名和密码登录到网站,默认Redis缓存中没有该用户名和密码对应列表,PHP程序会读取MYSQL数据库中的用户名和密码,然后将用户名和密码缓存至Redis中,下次用户通过浏览器再次使用同样的用户名和密码登录网站,PHP无需从数据库中读取该用户和密码信息,而是直接优先从Redis缓存中读取并返回,从而减轻MYSQL数据库的压力。 Redis除了可以缓存用户名、密码,还可以换成PHP论坛各种数据,例如用户帖子、用户动态等等,如图12\-8所示: ![](/media/202411/20241125143337224349.jpeg)图12\-8 LAMP\+Redis架构流程图 要实现将LAMP PHP网站相关数据存入Redis,需要一台Redis服务器、PHP\-redis连接驱动、PHP代码连接修改等。 ### LAMP\+Redis操作案例 LAMP PHP连接Redis,首先需安装Redis服务器,安装连接驱动,然后修改PHP网站配置文件,具体操作步骤如下: 1. LAMP\+Redis实战环境配置 | LAMP服务器: 192\.168\.149\.128Redis主库: 192\.168\.149\.129Redis从库: 192\.168\.149\.130 | | --- | 1. 192\.168\.149\.129服务器安装部署Redis服务,代码如下 | wget http://download.redis.io/releases/redis\-2\.8\.13\.tar.gz tar zxf redis\-2\.8\.13\.tar.gzcd redis\-2\.8\.13make PREFIX\=/usr/local/redis installcp redis.conf /usr/local/redis/ | | --- | 将/usr/local/redis/bin/目录加入至环境变量配置文件/etc/profile末尾,然后Shell终端执行source /etc/profile让环境变量生效。 | export PATH\=/usr/local/redis/bin:$PATH | | --- | Nohup后台启动及停止Redis服务命令: | nohup /usr/local/redis/bin/redis\-server /usr/local/redis/redis.conf \&/usr/local/redis/bin/redis\-cli \-p 6379 shutdown | | --- | 1. 安装PHP\-Redis连接驱动 要确保PHP能够连接Redis缓存服务器,需添加PHP Redis扩展程序,也即是添加PHP安ext扩展模块,添加方法如下: | wget [https://github.com/phpredis/phpredis/archive/3\.1\.2\.tar.gz](https://github.com/phpredis/phpredis/archive/3.1.2.tar.gz) tar xzf 3\.1\.2\.tar.gz/usr/local/php5/bin/phpizecd phpredis\-3\.1\.2/./configure \-\-with\-php\-config\=/usr/local/php5/bin/php\-config \-\-enable\-redismakemake install | | --- | 修改vim /usr/local/php5/lib/php.ini配置文件,添加redis.so模块,代码如下: | extension\_dir \= "/usr/local/php5/lib/php/extensions/no\-debug\-zts\-20090626"extension\=redis.so | | --- | 重启Apache服务,写入phpinfo测试页面,通过浏览器访问,如图12\-9所示,检查到存在Redis模块即可: ![](/media/202411/20241125143337231624.png)图12\-9 PHP Redis模块添加 1. LAMP\+Redis缓存测试 登录192\.168\.149\.128 WEB服务器,修改Discuz PHP网站发布/usr/local/apache2/htdcos目录全局配置文件config\_global.php,查找CONFIG MEMORY段,将redis server后改为Redis主服务器的IP 192\.168\.149\.129即可,如图12\-10所示: ![](/media/202411/20241125143337236901.png)图12\-10 PHP Redis配置文件修改 通过浏览器访问Apache PHP论坛网站,同时登陆Redis服务器,执行命令redis\-cli进入Redis命令行,运行命令KEYS \*,如图12\-11所示,存在以IOKLAN开头的key,则证明Redis成功缓存LAMP\+Discuz网站信息数据。 ![](/media/202411/20241125143337241976.png)图12\-11 Redis缓存LAMP KEYS数据 1. 测试Redis缓存是否生效 访问LAMP\+Discuz网站,创建论坛测试用户jfedu666,密码jfedu666,此时用户数据第一次注册,用户名和密码会写入到MySQL数据库表中,同时会写入该数据也会写入到Redis缓存,如图12\-12(a)、12\-12(b)、12\-12(c)所示: ![](/media/202411/20241125143337247293.png)图12\-12(a) 创建论坛用户和密码 ![](/media/202411/20241125143337252606.png)图12\-12(b) MySQL数据库用户查询 ![](/media/202411/20241125143337261836.png)图12\-12(c) Redis缓存测试案例 将jfedu666从MySQL Discuz库pre\_common\_member中删除,通过该用户依然可以正常登录WEB网站,则证明此时数据读取的是Redis缓存服务器,如图12\-13(a)、12\-13(b)、12\-13(c)所示: ![](/media/202411/20241125143337267878.png)图12\-13(a) 删除数据库用户和密码 ![](/media/202411/20241125143337279851.png)图12\-13(b) 用户名和密码登录discuz论坛 ![](/media/202411/20241125143337285022.png)图12\-13(c) 用户名和密码登录discuz论坛 ## Redis配置文件详解 Redis是一个内存数据库,附Redis.conf常用参数的详解,后面章节会继续深入讲解。 | \# daemonize no Linux Shell终端运行redis,改为yes即后台运行Redis服务;daemonize yes\# 当运行多个 redis 服务时,需要指定不同的pid文件和端口pidfile /var/run/redis\_6379\.pid\# 指定redis运行的端口,默认是 6379port 6379\# 在高并发的环境中,为避免慢客户端的连接问题,需要设置一个高速后台日志tcp\-backlog 511\# 指定redis只接收来自于该 IP 地址的请求,如果不进行设置,那么将处理所有请求\# bind 192\.168\.1\.100 10\.0\.0\.1\# bind 127\.0\.0\.1\#设置客户端连接时的超时时间,单位为秒。当客户端在这段时间内没有发出任何指令,那么关闭该连接;timeout 0\# 在Linux 上,指定值(秒)用于发送 ACKs 的时间。注意关闭连接需要双倍的时间。默认为 0 。tcp\-keepalive 0\# Redis总共支持四个日志级别: debug 、 verbose 、 notice 、 warning ,默认为 verbose\# debug 记录很多信息,用于开发和测试\# varbose 有用的信息,不像 debug 会记录那么多\# notice 普通的 verbose ,常用于生产环境\# warning 只有非常重要或者严重的信息会记录到日志loglevel notice\#配置 log 文件地址\#默认值为 stdout ,标准输出,若后台模式会输出到 /dev/null 。logfile /var/log/redis/redis.log\#可用数据库数\#默认值为16 ,默认数据库为0,数据库范围在 0\- ( database\-1 )之间databases 16\#数据写入磁盘快照设置\#保存数据到磁盘,格式如下 :\#save \<seconds\> \<changes\>\#指出在多长时间内,有多少次更新操作,就将数据同步到数据文件 rdb 。\#相当于条件触发抓取快照,这个可以多个条件配合\#比如默认配置文件中的设置,就设置了三个条件\#save 900 1 900 秒内至少有 1 个 key 被改变\#save 300 10 300 秒内至少有 300 个 key 被改变\#save 60 10000 60 秒内至少有 10000 个 key 被改变\# save 900 1\# save 300 10\# save 60 10000\# 后台存储错误停止写。stop\-writes\-on\-bgsave\-error yes\# 存储至本地数据库时(持久化到 rdb 文件)是否压缩数据,默认为 yesrdbcompression yes\# 本地持久化数据库文件名,默认值为 dump.rdbdbfilename dump.rdb\# 工作目录\# 数据库镜像备份的文件放置的路径。\# 这里的路径跟文件名要分开配置是因为 redis 在进行备份时,先会将当前数据库的状态写入到一个临时文件中,等备份完成,\# 再把该该临时文件替换为上面所指定的文件,而这里的临时文件和上面所配置的备份文件都会放在这个指定的路径当中。\# AOF 文件也会存放在这个目录下面\# 注意这里必须制定一个目录而不是文件dir /var/lib/redis/\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\# 复制 \#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\# 主从复制 . 设置该数据库为其他数据库的从数据库 .\# 设置当本机为 slav 服务时,设置 master 服务的 IP 地址及端口,在 Redis 启动时,它会自动从 master 进行数据同步\# slaveof \<masterip\>\<masterport\>\# 当 master 服务设置了密码保护时 ( 用 requirepass 制定的密码 )\# slave 服务连接 master 的密码\# masterauth \<master\-password\>\# 当从库同主机失去连接或者复制正在进行,从机库有两种运行方式:\# 1\) 如果 slave\-serve\-stale\-data 设置为 yes( 默认设置 ) ,从库会继续响应客户端的请求\# 2\) 如果 slave\-serve\-stale\-data 是指为 no ,出去 INFO 和 SLAVOF 命令之外的任何请求都会返回一个\# 错误 "SYNC with master in progress"slave\-serve\-stale\-data yes\# 配置 slave 实例是否接受写。写 slave 对存储短暂数据(在同 master 数据同步后可以很容易地被删除)是有用的,但未配置的情况下,客户端写可能会发送问题。\# 从 Redis2\.6 后,默认 slave 为 read\-onlyslaveread\-only yes\# 从库会按照一个时间间隔向主库发送 PINGs. 可以通过 repl\-ping\-slave\-period 设置这个时间间隔,默认是 10 秒\# repl\-ping\-slave\-period 10\# repl\-timeout 设置主库批量数据传输时间或者 ping 回复时间间隔,默认值是 60 秒\# 一定要确保 repl\-timeout 大于 repl\-ping\-slave\-period\# repl\-timeout 60\# 在 slave socket 的 SYNC 后禁用 TCP\_NODELAY\# 如果选择“ yes ” ,Redis 将使用一个较小的数字 TCP 数据包和更少的带宽将数据发送到 slave , 但是这可能导致数据发送到 slave 端会有延迟 , 如果是 Linux kernel 的默认配置,会达到 40 毫秒 .\# 如果选择 "no" ,则发送数据到 slave 端的延迟会降低,但将使用更多的带宽用于复制 .repl\-disable\-tcp\-nodelay no\# 设置复制的后台日志大小。\# 复制的后台日志越大, slave 断开连接及后来可能执行部分复制花的时间就越长。\# 后台日志在至少有一个 slave 连接时,仅仅分配一次。\# repl\-backlog\-size 1mb\# 在 master 不再连接 slave 后,后台日志将被释放。下面的配置定义从最后一个 slave 断开连接后需要释放的时间(秒)。\# 0 意味着从不释放后台日志\# repl\-backlog\-ttl 3600\# 如果 master 不能再正常工作,那么会在多个 slave 中,选择优先值最小的一个 slave 提升为 master ,优先值为 0 表示不能提升为 master 。slave\-priority 100\# 如果少于 N 个 slave 连接,且延迟时间 \<\=M 秒,则 master 可配置停止接受写操作。\# 例如需要至少 3 个 slave 连接,且延迟 \<\=10 秒的配置:\# min\-slaves\-to\-write 3\# min\-slaves\-max\-lag 10\# 设置 0 为禁用\# 默认 min\-slaves\-to\-write 为 0 (禁用), min\-slaves\-max\-lag 为 10\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\# 安全 \#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\# 设置客户端连接后进行任何其他指定前需要使用的密码。\# 警告:因为 redis 速度相当快,所以在一台比较好的服务器下,一个外部的用户可以在一秒钟进行 150K 次的密码尝试,这意味着你需要指定非常非常强大的密码来防止暴力破解\# requirepass jfedu\# 命令重命名 .\# 在一个共享环境下可以重命名相对危险的命令。比如把 CONFIG 重名为一个不容易猜测的字符。\# 举例 :\# rename\-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52\# 如果想删除一个命令,直接把它重命名为一个空字符 "" 即可,如下:\# rename\-command CONFIG ""\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#约束\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#设置同一时间最大客户端连接数,默认无限制, \#Redis 可以同时打开的客户端连接数为 Redis 进程可以打开的最大文件描述符数,\#如果设置 maxclients 0 ,表示不作限制。\#当客户端连接数到达限制时, Redis 会关闭新的连接并向客户端返回 max number of clients reached 错误信息\# maxclients 10000\# 指定 Redis 最大内存限制, Redis 在启动时会把数据加载到内存中,达到最大内存后, Redis 会按照清除策略尝试清除已到期的 Key\# 如果 Redis 依照策略清除后无法提供足够空间,或者策略设置为 ”noeviction” ,则使用更多空间的命令将会报错,例如 SET, LPUSH 等。但仍然可以进行读取操作\# 注意: Redis 新的 vm 机制,会把 Key 存放内存, Value 会存放在 swap 区\# 该选项对 LRU 策略很有用。\# maxmemory 的设置比较适合于把 redis 当作于类似 memcached 的缓存来使用,而不适合当做一个真实的 DB 。\# 当把 Redis 当做一个真实的数据库使用的时候,内存使用将是一个很大的开销\# maxmemory \<bytes\>\# 当内存达到最大值的时候 Redis 会选择删除哪些数据?有五种方式可供选择\# volatile\-lru \-\> 利用 LRU 算法移除设置过过期时间的 key (LRU: 最近使用 Least RecentlyUsed )\# allkeys\-lru \-\> 利用 LRU 算法移除任何 key\# volatile\-random \-\> 移除设置过过期时间的随机 key\# allkeys\-\>random \-\> remove a randomkey, any key\# volatile\-ttl \-\> 移除即将过期的 key(minor TTL)\# noeviction \-\> 不移除任何可以,只是返回一个写错误\# 注意:对于上面的策略,如果没有合适的 key 可以移除,当写的时候 Redis 会返回一个错误\# 默认是 : volatile\-lru\# maxmemory\-policy volatile\-lru \# LRU 和 minimal TTL 算法都不是精准的算法,但是相对精确的算法 ( 为了节省内存 ) ,随意你可以选择样本大小进行检测。\# Redis 默认的灰选择 3 个样本进行检测,你可以通过 maxmemory\-samples 进行设置\# maxmemory\-samples 3\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\# AOF\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\# 默认情况下, redis 会在后台异步的把数据库镜像备份到磁盘,但是该备份是非常耗时的,而且备份也不能很频繁,如果发生诸如拉闸限电、拔插头等状况,那么将造成比较大范围的数据丢失。\# 所以 redis 提供了另外一种更加高效的数据库备份及灾难恢复方式。\# 开启 append only 模式之后, redis 会把所接收到的每一次写操作请求都追加到 appendonly.aof 文件中,当 redis 重新启动时,会从该文件恢复出之前的状态。\# 但是这样会造成 appendonly.aof 文件过大,所以 redis 还支持了 BGREWRITEAOF 指令,对 appendonly.aof 进行重新整理。\# 你可以同时开启 asynchronous dumps 和 AOFappendonly no\# AOF 文件名称 ( 默认 : "appendonly.aof")\# appendfilename appendonly.aof\# Redis 支持三种同步 AOF 文件的策略 :\# no: 不进行同步,系统去操作 . Faster.\# always: always 表示每次有写操作都进行同步 . Slow, Safest.\# everysec: 表示对写操作进行累积,每秒同步一次 . Compromise.\# 默认是 "everysec" ,按照速度和安全折中这是最好的。\# 如果想让 Redis 能更高效的运行,你也可以设置为 "no" ,让操作系统决定什么时候去执行\# 或者相反想让数据更安全你也可以设置为 "always"\# 如果不确定就用 "everysec".\# appendfsync alwaysappendfsync everysec\# appendfsync no\# AOF 策略设置为 always 或者 everysec 时,后台处理进程 ( 后台保存或者 AOF 日志重写 ) 会执行大量的 I/O 操作\# 在某些 Linux 配置中会阻止过长的 fsync() 请求。注意现在没有任何修复,即使 fsync 在另外一个线程进行处理\# 为了减缓这个问题,可以设置下面这个参数 no\-appendfsync\-on\-rewriteno\-appendfsync\-on\-rewrite no\# AOF 自动重写\# 当 AOF 文件增长到一定大小的时候 Redis 能够调用 BGREWRITEAOF 对日志文件进行重写\# 它是这样工作的: Redis 会记住上次进行些日志后文件的大小 ( 如果从开机以来还没进行过重写,那日子大小在开机的时候确定 )\# 基础大小会同现在的大小进行比较。如果现在的大小比基础大小大制定的百分比,重写功能将启动\# 同时需要指定一个最小大小用于 AOF 重写,这个用于阻止即使文件很小但是增长幅度很大也去重写 AOF 文件的情况\# 设置 percentage 为 0 就关闭这个特性auto\-aof\-rewrite\-percentage 100auto\-aof\-rewrite\-min\-size 64mb\#\#\#\#\#\#\#\# \# LUA SCRIPTING \#\#\#\#\#\#\#\#\#\# 一个 Lua 脚本最长的执行时间为 5000 毫秒( 5 秒),如果为 0 或负数表示无限执行时间。lua\-time\-limit 5000\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#LOW LOG\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\# Redis Slow Log 记录超过特定执行时间的命令。执行时间不包括 I/O 计算比如连接客户端,返回结果等,只是命令执行时间\# 可以通过两个参数设置 slow log :一个是告诉 Redis 执行超过多少时间被记录的参数 slowlog\-log\-slower\-than( 微妙 ) ,\# 另一个是 slow log 的长度。当一个新命令被记录的时候最早的命令将被从队列中移除\# 下面的时间以微妙为单位,因此 1000000 代表一秒。\# 注意指定一个负数将关闭慢日志,而设置为 0 将强制每个命令都会记录slowlog\-log\-slower\-than 10000\# 对日志长度没有限制,只是要注意它会消耗内存\# 可以通过 SLOWLOG RESET 回收被慢日志消耗的内存\# 推荐使用默认值 128 ,当慢日志超过 128 时,最先进入队列的记录会被踢出slowlog\-max\-len 128 | | --- | ## Redis常用配置 Redis缓存服务器命令行中常用命令如下: | Redis CONFIG 命令格式如下:redis 127\.0\.0\.1:6379\> CONFIG GET\|SET CONFIG\_SETTING\_NAMECONFIG GET \* 获取Redis服务器所有配置信息;CONFIG SET loglevel "notice" 设置Redis服务器日志级别;CONFIG SET requirepass "jfedu"AUTH jfeduredis\-cli \-h host \-p port \-a password 远程连接redis数据库;CLIENT GETNAME 获取连接的名称;CLIENT SETNAME 设置当前连接的名称;CLUSTER SLOTS 获取集群节点的映射数组;COMMAND 获取Redis命令详情数组;COMMAND COUNT 获取 Redis 命令总数;COMMAND GETKEYS 获取给定命令的所有键;TIME 返回当前服务器时间;CONFIG GET parameter 获取指定配置参数的值;CONFIG SET parameter value 修改redis 配置参数,无需重启;CONFIG RESETSTAT 重置 INFO 命令中的某些统计数据;DBSIZE 返回当前数据库的 key 的数量;DEBUG OBJECT key 获取 key 的调试信息;DEBUG SEGFAULT 让Redis服务崩溃;FLUSHALL 删除所有数据库的所有key;FLUSHDB 删除当前数据库的所有key;ROLE 返回主从实例所属的角色;SAVE 异步保存数据到硬盘;SHUTDOWN 异步保存数据到硬盘,并关闭服务器;SLOWLOG 管理 redis 的慢日志;SET keys values 设置key为jfedu,值为123;DEL jfedu 删除key及值;INFO CPU 查看服务器CPU占用信息;KEYS jfedu 查看是存在jfedu的key;KEYS \* 查看Redis所有的KEY;CONFIG REWRITE 启动 Redis时所指定的redis.conf 配置文件进行改写;INFO \[section] 获取Redis服务器的各种信息和统计数值;SYNC 用于复制功能(replication)的内部命令;SLAVEOF host port 指定服务器的从属服务器(slave server);MONITOR 实时打印出Redis服务器接收到的命令,调试用;LASTSAVE 返回最近一次Redis成功将数据保存到磁盘上的时间;;CLIENT PAUSE timeout 指定时间内终止运行来自客户端的命令;BGREWRITEAOF 异步执行一个 AOF(AppendOnly File) 文件重写操作;BGSAVE 后台异步保存当前数据库的数据到磁盘。 | | --- | ## Redis集群主从实战 为了提升redis高可用性,我们除了备份redis dump数据之外,还需要创建redis主从架构,可以利用从将数据库持久化(数据持久化通俗讲就是把数据保存到磁盘上,保证不会因为断电等因素丢失数据。 Redis需要经常将内存中的数据同步到磁盘来保证持久化。redis支持两种持久化方式,一种是 Snapshotting(快照)也是默认方式,另一种是Append\-only file(缩写aof)的方式。) Redis主从复制,当用户往Master端写入数据时,通过Redis Sync机制将数据文件发送至Slave,Slave也会执行相同的操作确保数据一致;且实现Redis的主从复制非常简单。同时slave上还可以开启二级slave,三级slave从库,跟MySQL的主从类似。 Redis主从配置非常简单,只需要在Redis丛库192\.168\.149\.130配置中设置如下指令,slaveof表示指定主库的IP,192168\.149\.129为master服务器,6379为master服务器Redis端口,配置方法如下: 1. 192\.168\.149\.129 Redis主库redis.conf配置文件如下: | daemonize nopidfile /var/run/redis.pidport 6379tcp\-backlog 511timeout 0tcp\-keepalive 0loglevel noticelogfile ""databases 16save 900 1save 300 10save 60 10000stop\-writes\-on\-bgsave\-error yesrdbcompression yesrdbchecksum yesdbfilename redis.rdbdir /data/redis/slave\-serve\-stale\-data yesslave\-read\-only yesrepl\-disable\-tcp\-nodelay noslave\-priority 100appendonly noappendfilename "appendonly.aof"appendfsync everysecno\-appendfsync\-on\-rewrite noauto\-aof\-rewrite\-percentage 100auto\-aof\-rewrite\-min\-size 64mblua\-time\-limit 5000slowlog\-log\-slower\-than 10000slowlog\-max\-len 128latency\-monitor\-threshold 0notify\-keyspace\-events ""hash\-max\-ziplist\-entries 512hash\-max\-ziplist\-value 64list\-max\-ziplist\-entries 512list\-max\-ziplist\-value 64set\-max\-intset\-entries 512zset\-max\-ziplist\-entries 128zset\-max\-ziplist\-value 64hll\-sparse\-max\-bytes 3000activerehashing yesclient\-output\-buffer\-limit normal 0 0 0client\-output\-buffer\-limit slave 256mb 64mb 60client\-output\-buffer\-limit pubsub 32mb 8mb 60hz 10aof\-rewrite\-incremental\-fsync yes | | --- | 1. 192168\.149\.130 Redis丛库redis.conf配置文件如下: | daemonize nopidfile /var/run/redis.pidport 6379slaveof 192\.168\.149\.129 6379tcp\-backlog 511timeout 0tcp\-keepalive 0loglevel noticelogfile ""databases 16save 900 1save 300 10save 60 10000stop\-writes\-on\-bgsave\-error yesrdbcompression yesrdbchecksum yesdbfilename redis.rdbdir /data/redis/slave\-serve\-stale\-data yesslave\-read\-only yesrepl\-disable\-tcp\-nodelay noslave\-priority 100appendonly noappendfilename "appendonly.aof"appendfsync everysecno\-appendfsync\-on\-rewrite noauto\-aof\-rewrite\-percentage 100auto\-aof\-rewrite\-min\-size 64mblua\-time\-limit 5000slowlog\-log\-slower\-than 10000slowlog\-max\-len 128latency\-monitor\-threshold 0notify\-keyspace\-events ""hash\-max\-ziplist\-entries 512hash\-max\-ziplist\-value 64list\-max\-ziplist\-entries 512list\-max\-ziplist\-value 64set\-max\-intset\-entries 512zset\-max\-ziplist\-entries 128zset\-max\-ziplist\-value 64hll\-sparse\-max\-bytes 3000activerehashing yesclient\-output\-buffer\-limit normal 0 0 0client\-output\-buffer\-limit slave 256mb 64mb 60client\-output\-buffer\-limit pubsub 32mb 8mb 60hz 10aof\-rewrite\-incremental\-fsync yes | | --- | 1. 重启Redis主库、丛库服务,在Redis主库创建key及values,登录Redis丛库查看,如图12\-14(a)、12\-14(b)所示: ![](/media/202411/20241125143337338177.png)图12\-14(a) Redis主库创建key ![](/media/202411/20241125143337343477.png)图12\-14(b) Redis从库获取key值 ## Redis数据备份与恢复 Redis所有数据都是保存在内存中,Redis数据备份可以定期的通过异步方式保存到磁盘上,该方式称为半持久化模式,如果每一次数据变化都写入aof文件里面,则称为全持久化模式。同时还可以基于Redis主从复制实现Redis备份与恢复。 ### Redis主从复制备份 通过持久化功能,Redis保证了即使在服务器重启的情况下也不会损失(或少量损失)数据。但是由于数据是存储在一台服务器上的,如果这台服务器的硬盘出现故障,也会导致数据丢失。 为了避免单点故障,我们希望将数据库复制多个副本以部署在不同的服务器上,即使只有一台服务器出现故障其他服务器依然可以继续提供服务,这就要求当一台服务器上的数据库更新后,可以自动将更新的数据同步到其他服务器上,Redis提供了复制(replication)功能可以自动实现同步的过程。通过配置文件在Redis从数据库中配置文件中加入slaveof master\-ip master\-port即可,主数据库无需配置。 Redis主从复制优点及应用场景, WEB应用程序可以基于主从同步实现读写分离以提高服务器的负载能力。在常见的场景中,读的频率一般比较大,当单机Redis无法应付大量的读请求时,可以通过复制功能建立多个从数据库,主数据库只进行写操作,而从数据库负责读操作,还可以基于LVS\+keepalived\+Redis对Redis实现均和高可用。 从数据库持久化持久化通常相对比较耗时,为了提高性能,可以通过复制功能建立一个(或若干个)从数据库,并在从数据库中启用持久化,同时在主数据库禁用持久化。 当从数据库崩溃时重启后主数据库会自动将数据同步过来,所以无需担心数据丢失。而当主数据库崩溃时,需要在从数据库中使用SLAVEOF NO ONE命令将从数据库提升成主数据库继续服务,并在原来的主数据库启动后使用SLAVE OF命令将其设置成新的主数据库的从数据库,即可将数据同步回来。 ## LAMP企业架构读写分离 LAMP\+Discuz\+Redis缓解了MYSQL的部分压力,但是如果访问量非常大,Redis缓存中第一次没有缓存数据,会导致MYSQL数据库压力增大,此时可以基于分库、分表、分布式集群、或者读写分离来分担MYSQL数据库的压力,以读写分离为案例,来实现分担MYSQL数据库的压力。 MYSQL读写分离的原理其实就是让Master数据库处理事务性增、删除、修改、更新操作(CREATE、INSERT、UPDATE、DELETE),而让Slave数据库处理SELECT操作,MYSQL读写分离前提是基于MYSQL主从复制,这样可以保证在Master上修改数据,Slave同步之后,WEB应用可以读取到Slave端的数据。 实现MYSQL读写分离可以基于第三方插件,也可以通过开发修改代码实现,具体实现的读写分离的常见方式有如下四种: * MySQL\-Proxy读写分离; * Amoeba读写分离; * Mycat读写分离; * **基于程序读写分离(效率很高,实施难度大,开发改代码)** Amoeba是以MySQL为底层数据存储,并对WEB、APP应用提供MySQL协议接口的proxy。它集中地响应WEB应用的请求,依据用户事先设置的规则,将SQL请求发送到特定的数据库上执行,基于此可以实现负载均衡、[读写分离](http://baike.baidu.com/view/3372624.htm" \t "http://baike.baidu.com/_blank)、高可用性等需求。 Amoeba相当于一个SQL请求的[路由器](http://baike.baidu.com/view/1360.htm" \t "http://baike.baidu.com/_blank),目的是为负载均衡、读写分离、高可用性提供机制,而不是完全实现它们。用户需要结合使用MySQL的 Replication等机制来实现副本同步等功能。 Mysql\-Proxy是MySQL官方提供的mysql中间件服务,支持无数客户端连接,同时后端可连接若干台Mysql\-Server服务器,MYSQL\-Proxy自身基于MySQL协议,连接MYSQL\-Proxy的客户端无需修改任何设置, 跟正常连接MYSQL Server没有区别,无需修改程序代码。 MySQL Proxy是App应用(客户端)与MYSQL Server之间的一个连接代理,MySQL Proxy负责将APP应用的SQL请求根据转发规则,转发至相应的后端数据库,基于lua脚本,可以实现复杂的连接控制和过滤,从而实现数据读写分离和负载均衡的需求。 Mysql\-Proxy允许用户指定Lua脚本对SQL请求进行拦截,对请求进行分析与修改,还允许用户指定Lua脚本对服务器的返回结果进行修改,加入一些结果集或者去除一些结果集,对SQL的请求通常为读请求、写请求,基于Lua脚本,可以实现将SQL读请求转发至后端Slave服务器,将SQL写请求转发至后端Master服务器。 如图12\-16所示,为MYSQL\-PROXY读写分离架构图,通过架构图可以清晰看到SQL请求整个流向的过程。 ![timg?image&quality=80&size=b9999_10000&sec=1495011244752&di=c4b62ae85985158fbf86dd23507d8704&imgtype=0&src=http%3A%2F%2Fs3](/media/202411/20241125143337349651.jpeg) 图12\-16 MYSQL\-Proxy读写分离流程 Mysql\-Proxy读写分离架构实战配置,如图12\-17所示,两台WEB通过MYSQL\-Proxy连接后端1\.14和1\.15 MYSQL服务器。 ![](/media/202411/20241125143337355005.png)图12\-17 MYSQL\-Proxy实施架构图 构建Mysql读写分离架构首先需要将两台MYSQL服务器配置为主从复制(前文已存在,此处省略配置),配置完毕后,在192\.168\.1\.16服务器上安装Mysql\-Proxy服务即可,配置步骤如下: 1. 下载MYSQL\-Proxy软件版本,解压并重命名至/usr/local/mysql\-proxy,命令如下: | wget [http://ftp.ntu.edu.tw/pub/MySQL/Downloads/MySQL\-Proxy/mysql\-proxy\-0\.8\.4\-linux\-el6\-x86\-64bit.tar.gz](http://ftp.ntu.edu.tw/pub/MySQL/Downloads/MySQL-Proxy/mysql-proxy-0.8.4-linux-el6-x86-64bit.tar.gz) useradd \-r mysql\-proxytar zxvf mysql\-proxy\-0\.8\.4\-linux\-el6\-x86\-64bit.tar.gz \-C /usr/localmv /usr/local/mysql\-proxy\-0\.8\.4\-linux\-el6\-x86\-64bit /usr/local/mysql\-proxy | | --- | 1. 环境变量配置文件/etc/profile中加入如下代码保存退出,然后执行source /etc/profile使环境变量配置生效即可: | export PATH\=$PATH:/usr/local/mysql\-proxy/bin/ | | --- | 1. 启动MYSQL\-Proxy中间件,命令如下: | mysql\-proxy \-\-daemon \-\-log\-level\=debug \-\-user\=mysql\-proxy \-\-keepalive \-\-log\-file\=/var/log/mysql\-proxy.log \-\-plugins\="proxy" \-\-proxy\-backend\-addresses\="192\.168\.1\.162:3306" \-\-proxy\-read\-only\-backend\-addresses\="192\.168\.1\.163:3306" \-\-proxy\-lua\-script\="/usr/local/mysql\-proxy/share/doc/mysql\-proxy/rw\-splitting.lua" \-\-plugins\=admin \-\-admin\-username\="admin" \-\-admin\-password\="admin" \-\-admin\-lua\-script\="/usr/local/mysql\-proxy/lib/mysql\-proxy/lua/admin.lua" | | --- | 1. Mysql\-Proxy的相关参数详解如下: | \-\-help\-all :获取全部帮助信息;\-\-proxy\-address\=host:port :代理服务监听的地址和端口,默认为4040;\-\-admin\-address\=host:port :管理模块监听的地址和端口,默认为4041;\-\-proxy\-backend\-addresses\=host:port :后端mysql服务器的地址和端口;\-\-proxy\-read\-only\-backend\-addresses\=host:port :后端只读mysql服务器的地址和端口;\-\-proxy\-lua\-script\=file\_name :完成mysql代理功能的Lua脚本;\-\-daemon :以守护进程模式启动mysql\-proxy;\-\-keepalive :在mysql\-proxy崩溃时尝试重启之;\-\-log\-file\=/path/to/log\_file\_name :日志文件名称;\-\-log\-level\=level :日志级别;\-\-log\-use\-syslog :基于syslog记录日志;\-\-plugins\=plugin :在mysql\-proxy启动时加载的插件;\-\-user\=user\_name :运行mysql\-proxy进程的用户;\-\-defaults\-file\=/path/to/conf\_file\_name :默认使用的配置文件路径,其配置段使用\[mysql\-proxy]标识;\-\-proxy\-skip\-profiling :禁用profile;\-\-pid\-file\=/path/to/pid\_file\_name :进程文件名; | | --- | 1. MYSQL\-Proxy启动后,在服务器端查看端口,其中4040为proxy代理端口用于WEB应用连接,4041位管理端口用于SA或者DBA管理,如图12\-48所示: ![](/media/202411/20241125143337362678.png) 图12\-48 MYSQL\-Proxy启动端口 1. 基于4041端口MySQL\-Proxy查看读写分离状态,登录4041管理端口,命令如下: | mysql \-h192\.168\.1\.16 \-uadmin \-p \-P 4041 | | --- | 1. 以4041管理口登录,然后执行select命令,如图12\-18所示state均为up状态,type类型为rw、ro,则证明读写分离状态成功。如果状态为unknown未知状态,可以4040端口登录执行:show databases;命令,直到state变成up状态为止。 | select \* from backends; | | --- | ![](/media/202411/20241125143337368709.png)图12\-18 MYSQL\-Proxy读写分离状态 1. 读写分离数据测试,以3306端口登录到从库,进行数据写入和测试,在丛库上创建jfedu\_test测试库,并写入内容,如图12\-19所示: ![](/media/202411/20241125143337373789.png) 图12\-19 MYSQL\-Proxy读写分离测试 1. 读写分离数据测试,以4040代理端口登录,执行如下命令,可以查看到数据即证明读写分离成功。 | mysql \-h192\.168\.1\.16 \-uroot \-p123456 \-P4040 \-e "select \* from jfedu\_test.t1;" | | --- | 1. 登录Apache WEB服务器,修改Discuz PHP网站发布/usr/local/apache2/htdcos目录全局配置文件config\_global.php,查找dbhost段,将192\.168\.1\.16 改成192\.168\.1\.16:40404,如图12\-20所示: ![](/media/202411/20241125143337379187.png) 图12\-20 MYSQL\-Proxy读写分离测试 # CentOS7实战Kickstart批量系统部署 ## Kickstart使用背景介绍 随着公司业务不断增加,经常需要采购新服务器,并要求安装Linux系统,并且要求Linux版本要一致,方便以后的维护和管理,每次人工安装linux系统会浪费掉更多时间,如果我们有办法能节省一次一次的时间岂不更好呢? 大中型互联网公司一次采购服务器上百台,如果采用人工手动一台一台的安装,一个人得搞坏N张光盘,得多少个加班加点才能完成这项”艰巨”的任务呢,我们可以看到全人工来完成这样的工作太浪费人力了,有没有自动化安装平台呢,通过一台已存在的系统然后克隆或者复制到新的服务器呢。Kickstart可以毫不费力的完成这项工作。 PXE(preboot execute environment,预启动执行环境)是由[Intel公司](http://baike.baidu.com/view/8364.htm" \t "_blank)开发的最新技术,工作于Client/Server的网络模式,支持[工作站](http://baike.baidu.com/view/7977.htm" \t "_blank)通过网络从远端服务器下载映像,并由此支持通过网络启动[操作系统](http://baike.baidu.com/view/880.htm" \t "_blank),在启动过程中,终端要求服务器分配[IP](http://baike.baidu.com/view/8370.htm" \t "_blank)地址,再用[TFTP](http://baike.baidu.com/view/23881.htm" \t "_blank)(trivial file transfer protocol)协议下载一个启动[软件](http://baike.baidu.com/view/37.htm" \t "_blank)包到本机内存中执行。 要使用Kickstart安装平台,包括的完整架构为:Kickstart\+DHCP\+NFS(HTTP)\+TFTP\+PXE,从架构可以看出,大致需要安装的服务,例如dhcp、tftp、httpd、kickstart/pxe等。 ## Kickstart企业实战配置 基于YUM安装DHCP、TFTP、HTTPD服务,指令如下: yum install httpd httpd\-devel tftp\-server xinetd dhcp\* \-y 配置tftp服务,开启tftp服务; | cat\>/etc/xinetd.d/tftp\<\<EOFservice tftp{disable \= nosocket\_type \= dgramprotocol \= udpwait \= yesuser \= rootserver \= /usr/sbin/in.tftpdserver\_args \= \-u nobody \-s /tftpbootper\_source \= 11cps \= 100 2flags \= IPv4}EOF | | --- | 只需要把disable \= yes改成disable \= no即可,基于sed命令也可以实现: sed \-i ‘/disable/s/yes/no/g’/etc/xinetd.d/tftp ## TFTP\+PXE配置 要实现远程安装系统,需要在TFTPBOOT目录指定相关PXE内核模块及相关参数,配置步骤如下: \#挂载本地光盘 mount /dev/cdrom /mnt \#安装syslinux必备文件 yum install syslinux syslinux\-devel \-y \#软链接至/根系统下; | ln \-s /var/lib/tftpboot /mkdir \-p /var/lib/tftpboot/pxelinux.cfg/\\cp /mnt/isolinux/isolinux.cfg /var/lib/tftpboot/pxelinux.cfg/default\\cp /usr/share/syslinux/vesamenu.c32 /var/lib/tftpboot/\\cp /mnt/images/pxeboot/vmlinuz /var/lib/tftpboot/\\cp /mnt/images/pxeboot/initrd.img /var/lib/tftpboot/\\cp /usr/share/syslinux/pxelinux.0 /var/lib/tftpboot/chmod 644 /var/lib/tftpboot/pxelinux.cfg/default | | --- | ## 配置TFTPBOOT引导案例 | cat\>/tftpboot/pxelinux.cfg/default\<\<EOFdefault vesamenu.c32timeout 10display boot.msgmenu clearmenu background splash.pngmenu title CentOS Linux 7label linux menu label ^Install CentOS Linux 7 menu default kernel vmlinuz append initrd\=initrd.img inst.repo\=http://192\.168\.0\.131/centos7 quiet ks\=http://192\.168\.0\.131/ks.cfglabel check menu label Test this ^media \& install CentOS Linux 7 kernel vmlinuz append initrd\=initrd.img inst.stage2\=hd:LABEL\=CentOS\\x207\\x20x86\_64 rd.live.check quietEOF | | --- | 配置文件详解: 192\.168\.0\.131是kickstart服务器,/centos7是HTTPD共享linux镜像的目录,即linux存放安装文件的路径: ks.cfg是kickstart主配置文件; 设置timeout 10 /\*超时时间为10S \*/; ksdevice\=ens33代表当我们有多块网卡的时候,要实现自动化需要设置从ens33安装。 TFTP配置完毕,由于是TFTP是非独立服务,需要依赖xinetd服务来启动,启动命令为: chkconfig tftp \-\-level 35 on \&\& service xinetd restart ## HTTPD\+KICKSTART配置 远程系统安装,客户端需要下载系统所需的软件包,所以需要使用NFS或者httpd把镜像文件共享出来。 mkdir \-p /var/www/html/centos7/ mount /dev/cdrom /var/www/html/centos7/ \#cp /dev/cdrom/\* /var/www/html/centos7/ (可选配置) 配置kickstart,可以使用system\-kickstart系统软件包来配置,ks.cfg配置文件内容如下: | cat\>/var/www/html/ks.cfg\<\<EOFinstalltextkeyboard 'us'rootpw www.jfedu.nettimezone Asia/Shanghai url \-\-url\=http://192\.168\.0\.131/centos7rebootlang zh\_CN firewall \-\-disabled network \-\-bootproto\=dhcp \-\-device\=ens33auth \-\-useshadow \-\-passalgo\=sha512firstboot \-\-disableselinux disabled bootloader \-\-location\=mbrclearpart \-\-all \-\-initlabelpart /boot \-\-fstype\="ext4" \-\-size\=300part / \-\-fstype\="ext4" \-\-growpart swap \-\-fstype\="swap" \-\-size\=512%packages@base@core%endEOF | | --- | ## DHCP服务配置演练 DHCP服务配置文件代码如下: | cat\>/etc/dhcp/dhcpd.conf\<\<EOFddns\-update\-style interim;ignore client\-updates;next\-server 192\.168\.0\.131;filename "pxelinux.0";allow booting;allow bootp;subnet 192\.168\.0\.0 netmask 255\.255\.255\.0 {\#default gatewayoption routers 192\.168\.0\.1;option subnet\-mask 255\.255\.255\.0;range dynamic\-bootp 192\.168\.0\.180 192\.168\.0\.200;host ns {hardware ethernet 00:1a:a0:2b:38:81;fixed\-address 192\.168\.0\.101;}}EOF | | --- | 重启各个服务,启动新的客户端验证测试: service httpd restart service dhcpd restart service xinetd restart ![](/media/202411/20241125143337390374.png) ## 开启新虚拟机,BIOS以网卡启动 ![](/media/202411/20241125143337396170.png) ![](/media/202411/20241125143337402498.png) ![](/media/202411/20241125143337407423.png) 如果安装时报错如下: ![](/media/202411/20241125143337412308.png) 需要调整客户端虚拟机的内存设置为2G\+; ![](/media/202411/20241125143337417416.png) ## Kickstart企业生产环境扩展 在真实环境中,通常我们会发现一台服务器好几块硬盘,做完raid,整个硬盘有等10T,如果来使用kickstart自动安装并分区呢;一般服务器硬盘超过2T,如何来使用kickstart安装配置呢?这里就不能使用MBR方式来分区,需要采用GPT格式来引导并分区。需要在ks.cfg末尾添加如下命令来实现需求: %pre parted \-s /dev/sdb mklabel gpt %end 为了实现kickstart安装完系统后,自动初始化系统等等工作,我们可以在系统安装完后,自动执行定制的脚本,需要在ks.cfg末尾加入如下配置: %post mount \-t nfs 192\.168\.0\.79:/centos/init /mnt cd /mnt/ ;/bin/sh auto\_init.sh %end KICKSTART所有配置就此告一段落,真实环境需要注意,新服务器跟kickstart最后独立在一个网络,不要跟办公环境或者服务器机房网络混在一起,如果别的机器以网卡就会把它的系统重装成Linux系统。 # Zabbix分布式监控企业实战 企业服务器对用户提供服务,作为运维工程师最重要的事情就是保证该网站正常稳定的运行,需要实时监控网站、服务器的运行状态,并且有故障及时去处理。 监控网站无需人工时刻去访问WEB网站或者登陆服务器去检查,可以借助开源监控软件例如Zabbix、Cacti、Nagios、Ganglia等来实现对网站的7x24小时的监控,并且做到有故障及时报警通知SA解决。 本章向读者介绍企业级分布式监控Zabbix入门、Zabbix监控原理、最新版本Zabbix安装实战、Zabbix批量监控客户端、监控MYSQL、WEB关键词及微信报警等。 ## Zabbix监控系统入门简介 Zabbix是一个基于WEB界面的提供分布式系统监控的企业级的开源解决方案,Zabbix能监视各种网络参数,保证服务器系统的安全稳定的运行,并提供灵活的通知机制以让SA快速定位并解决存在的各种问题。Zabbix分布式监控系统的优点如下: * 支持自动发现服务器和网络设备; * 支持底层自动发现; * 分布式的监控体系和集中式的WEB管理; * 支持主动监控和被动监控模式; * 服务器端支持多种操作系统:Linux, Solaris, HP\-UX, AIX, FreeBSD, OpenBSD, MAC等; * Agent客户端支持多种操作系统:Linux, Solaris, HP\-UX, AIX, FreeBSD,Windows等; * 基于SNMP、IPMI接口方式、Agent方式; * 安全的用户认证及权限配置; * 基于WEB的管理方法,支持自由的自定义事件和邮件、短信发送; * 高水平的业务视图监控资源,支持日志审计,资产管理等功能; * 支持高水平API二次开发、脚本监控、自Key定义、自动化运维整合调用。 ## Zabbix监控组件及流程 Zabbix监控组件如图13\-1所示,主要由三大组件,分别是Zabbix server端、Zabbix Proxy、Agent客户端,其中Zabbix Server端包括:WEB GUI、Database、Zabbix\_Server。 ![](/media/202411/20241125143340010165.png) 图13\-1 Zabbix监控组件 Zabbix监控系统具体监控系统流程如图13\-2所示: ![](/media/202411/20241125143342783287.png)图13\-2 Zabbix监控流程图 Zabbix监控完整流程包括:Agentd安装在被监控的主机上,Agent负责定期收集客户端本地各项数据,并发送到Zabbix Server端,Zabbix Server收到数据,将数据存储到数据库中,用户基于Zabbix WEB可以看到数据在前端展现图像。 当Zabbix监控某个具体的项目,该项目会设置一个触发器阀值,当被监控的指标超过该触发器设定的阀值,会进行一些必要的动作,动作包括:邮件、微信报警或者执行命令等操作。如下为Zabbix完整监控系统,各个部分负责的工作: * Zabbix Server:负责接收agent发送的报告信息的核心组件,所有配置,统计数据及操作数据均由其组织进行; * Database Storage:专用于存储所有配置信息,以及存储由Zabbix收集到的数据; * Web interface:Zabbix的GUI接口,通常与Server运行在同一台主机上; * Proxy:常用于分布监控环境中,代理Server收集部分被监控端的监控数据并统一发往Server端; * Zabbix Agent:部署在被监控主机上,负责收集本地数据并发往Server端或Proxy端; Zabbix监控部署在系统中,会包含常见的四个程序:zabbix\_server 、zabbix\_get、zabbix\_agentd 、zabbix\_proxy、zabbix\_sender等。四个程序启动后分别对应四个进程,如下为每个进程的功能: * Zabbix\_server:Zabbix服务端守护进程,其中zabbix\_agentd、zabbix\_get、zabbix\_sender、zabbix\_proxy的数据最终均是提交给Zabbix\_Server; * Zabbix\_Agentd:客户端守护进程,负责收集客户端数据,例如收集cpu负载、内存、硬盘使用情况等; * Zabbix\_get:Zabbix数据获取工具,单独使用的命令,通常在server或者proxy端执行获取远程客户端信息的命令; * Zabbix\_sender:zabbix数据发送工具,用于发送数据给server或者proxy,通常用于耗时比较长的检查。很多检查非常耗时间,导致zabbix超时。于是我们在脚本执行完毕之后,使用sender主动提交数据; * Zabbix\_proxy:zabbix分布式代理守护进程,分布式监控架构需要部署Zabbix\_Proxy。 ## Zabbix监控平台概念 Zabbix监控系统包括很多监控概念,掌握Zabbix监控概念能对Zabbix监控快速的理解,如下为Zabbix常用术语及解释。 | 主机(host): 被监控的网络设备,可以写IP或者DNS;主机组(host group): 主机组用于管理主机,可以批量设置权限;监控项(item): 具体监控项,items值由独立的keys进行识别;触发器(trigger): 为某个items设置触发器,达到触发器会执行action动作;事件(event): 例如达到某个触发器,称之为一个事件;动作(action): 对于特定事件事先定义的处理方法,默认可以发送信息及发送命令;报警升级(escalation): 发送警报或执行远程命令的自定义方案,如隔5分钟发送一次警报,共发送5次等。媒介(media): 发送通知的方式,可以支持Mail、SMS、Scripts等;通知(notification): 通过设置的媒介向用户发送的有关某事件的信息;远程命令 达到触发器,可以在被监控端执行命令;模板(template): 可以快速监控被监控端,模块包含:item、trigger、graph、screen、application;web场景(web scennario)用于检测web站点可用性,监控HTTP关键词;web前端(frontend): Zabbix的web接口;图形(graph) 监控图像;屏幕(screens) 屏幕显示;幻灯(slide show) 幻灯显示。 | | --- | ## Zabbix监控平台部署 | 1. Zabbix Server端和Zabbix Agent执行如下代码: Zabbix监控平台部署,至少需要安装四个组件,分别是Zabbix\_Server、Zabbix\_Web、Databases、Zabbix\_Agent,如下为Zabbix监控平台安装配置详细步骤: 1. 系统环境 Server端:192\.168\.149\.128Agent端:192\.168\.149\.1291. 下载zabbix版本,各个版本之间安装方法相差不大,可以根据实际情况选择安装版本,本文版本为Zabbix\-3\.2\.6\.tar.gz。 wget [https://jaist.dl.sourceforge.net/project/zabbix/ZABBIX%20Latest%20Stable/3\.2\.6/zabbix\-3\.2\.6\.tar.gz](https://jaist.dl.sourceforge.net/project/zabbix/ZABBIX%20Latest%20Stable/3.2.6/zabbix-3.2.6.tar.gz) yum \-y install curl curl\-devel net\-snmp net\-snmp\-devel perl\-DBIgroupadd zabbixuseradd \-g zabbix zabbixusermod \-s /sbin/nologin zabbix | | --- | 1. Zabbix Server端配置 创建zabbix数据库,执行授权命令: | create database zabbix charset\=utf8;grant all on zabbix.\* to zabbix@localhost identified by '123456';flush privileges; | | --- | 解压zabbix软件包并将Zabbix基础SQL文件导入数据至Zabbix数据库: | tar zxvf zabbix\-3\.2\.6\.tar.gzcd zabbix\-3\.2\.6mysql \-uzabbix \-p123456 zabbix \<database/mysql/schema.sqlmysql \-uzabbix \-p123456 zabbix \<database/mysql/images.sqlmysql \-uzabbix \-p123456 zabbix \< database/mysql/data.sql | | --- | 切换至Zabbix解压目录,执行如下代码,安装Zabbix\_server: | ./configure \-\-prefix\=/usr/local/zabbix/ \-\-enable\-server \-\-with\-mysql \-\-enable\-ipv6 \-\-with\-net\-snmp \-\-with\-libcurlmakemake installln \-s /usr/local/zabbix/sbin/zabbix\_\* /usr/local/sbin/ | | --- | Zabbix server安装完毕,cd /usr/local/zabbix/etc/目录,如图13\-3所示: ![](/media/202411/20241125143342832703.png)图13\-3 Zabbix监控流程图 备份Zabbix server配置文件,代码如下: | cp zabbix\_server.conf zabbix\_server.conf.bak | | --- | 将zabbix\_server.conf配置文件中代码设置为如下: | LogFile\=/tmp/zabbix\_server.logDBHost\=localhostDBName\=zabbixDBUser\=zabbixDBPassword\=123456 | | --- | 同时cp zabbix\_server启动脚本至/etc/init.d/目录,启动zabbix\_server, Zabbix\_server默认监听端口为10051。 | cd zabbix\-3\.2\.6cp misc/init.d/tru64/zabbix\_server /etc/init.d/zabbix\_serverchmod o\+x /etc/init.d/zabbix\_server | | --- | 配置Zabbix interface Web页面,安装HTTP WEB服务器,将Zabbix WEB代码发布至Apache默认发布目录,由于Zabbix3\.2\+ PHP版本需要使用PHP5\.4\.0版本,请将本机PHP版本升级至5\.4\.0\+,PHP5\.3升级至PHP5\.6,代码如下: | rpm \-Uvh [http://repo.webtatic.com/yum/el6/latest.rpm](http://mirror.webtatic.com/yum/el6/latest.rpm)yum remove php\*yum install php56w.x86\_64 php56w\-cli.x86\_64 php56w\-common.x86\_64 php56w\-gd.x86\_64 php56w\-ldap.x86\_64 php56w\-mbstring.x86\_64 php56w\-mcrypt.x86\_64 php56w\-mysql.x86\_64 php56w\-pdo.x86\_64 \-yyum install httpd httpd\-devel httpd\-tools \-ycp \-a /root/zabbix\-3\.2\.6/frontends/php/\* /var/www/html/sed \-i '/date.timezone/i date.timezone \= PRC' /etc/php.ini | | --- | 重新启动Zabbix Server、HTTP、MYSQL服务,代码如下: | /etc/init.d/zabbix\_server restart/etc/init.d/httpd restart /etc/init.d/mysqld restart | | --- | 1. Zabbix WEB GUI安装配置 通过浏览器Zabbix\_WEB验证,通过浏览器访问[http://192\.168\.149\.128/](http://192.168.149.128/),如图13\-4所示: ![](/media/202411/20241125143342839843.png)图13\-4 Zabbix WEB安装界面 单击下一步,出现如图13\-5所示,如果有错误提示,需要把错误依赖解决完,方可进行下一步操作。 ![](/media/202411/20241125143342845174.png)图13\-5 Zabbix WEB安装错误提示 如上异常错误解决方法代码如下,安装缺失的软包,并修改php.ini对应参数的值即可,如图13\-6所示: | yum install php\-mbstring php\-bcmath php\-gd php\-xml \-yyum install gd gd\-devel \-ysed \-i '/post\_max\_size/s/8/16/g;/max\_execution\_time/s/30/300/g;/max\_input\_time/s/60/300/g;s/\\;date.timezone.\*/date.timezone \\\= PRC/g;s/\\;always\_populate\_raw\_post\_data/always\_populate\_raw\_post\_data/g' /etc/php.iniservice httpd restart | | --- | ![](/media/202411/20241125143342850697.png)图13\-6 Zabbix WEB测试安装环境 单击下一步,如图13\-7所示,配置数据库连接,输入数据库名、用户、密码,单击Test connection,显示OK,单击下一步即可。 ![](/media/202411/20241125143342855711.png)图13\-7 Zabbix WEB数据库配置 继续单击下一步出现如图13\-8所示,填写Zabbix Title显示,可以为空,可以输入自定义的名称。 ![](/media/202411/20241125143342860626.png)图13\-8 Zabbix WEB详细信息 单击下一步,如图13\-9所示,需修创建zabbix.conf.php文件,执行如下命令,或者单击“[Download the configuration file](http://192.168.149.128/setup.php?save_config=1)”下载zabbix.conf.php文件,并将该文件上传至/var/www/html/conf/,并设置可写权限,刷新WEB页面,zabbix.conf.php内容代码如下,最后单击Finish即可: | \<?php// Zabbix GUI configuration file.global $DB;$DB\['TYPE'] \= 'MYSQL';$DB\['SERVER'] \= 'localhost';$DB\['PORT'] \= '0';$DB\['DATABASE'] \= 'zabbix';$DB\['USER'] \= 'zabbix';$DB\['PASSWORD'] \= '123456';// Schema name. Used for IBM DB2 and PostgreSQL.$DB\['SCHEMA'] \= '';$ZBX\_SERVER \= 'localhost';$ZBX\_SERVER\_PORT \= '10051';$ZBX\_SERVER\_NAME \= '京峰教育\-分布式监控系统';$IMAGE\_FORMAT\_DEFAULT \= IMAGE\_FORMAT\_PNG; | | --- | ![](/media/202411/20241125143342866695.png)图13\-9 Zabbix WEB配置文件测试 登录Zabbix WEB界面,默认用户名和密码为:admin/zabbix,如图13\-10(a)、13\-10(b)所示: ![](/media/202411/20241125143342871913.png)图13\-10(a) Zabbix WEB登录界面 ![](/media/202411/20241125143342877124.png) 图13\-10(b) Zabbix WEB后台界面 1. Agent客户端安装配置 解压zabbix\-3\.2\.6\.tar.gz源码文件,切换至解压目录,编译安装Zabbix,命令如下: | ./configure \-\-prefix\=/usr/local/zabbix \-\-enable\-agentmakemake installln \-s /usr/local/zabbix/sbin/zabbix\_\* /usr/local/sbin/ | | --- | 修改zabbix\_agentd.conf客户端配置文件,执行如下命令,zabbix\_agentd.conf内容,指定server IP,同时设置本地Hostname为本地IP地址或者DNS名称: CPU、内存、负载、网卡、磁盘、IO、应用服务、端口、登录用户、 | LogFile\=/tmp/zabbix\_agentd.logServer\=192\.168\.149\.128ServerActive\=192\.168\.149\.128Hostname \= 192\.168\.149\.129 | | --- | 同时cp zabbix\_agentd启动脚本至/etc/init.d/目录,启动zabbix\_agentd服务即可, Zabbix\_agentd默认监听端口为10050。 | cd zabbix\-3\.2\.6cp misc/init.d/tru64/zabbix\_agentd /etc/init.d/zabbix\_agentdchmod o\+x /etc/init.d/zabbix\_agentd/etc/init.d/zabbix\_agentd start | | --- | 1. Zabbix监控客户端 Zabbix服务端和客户端安装完毕之后,需通过Zabbix Server添加客户端监控,Zabbix WEB界面添加客户端监控的操作步骤如下,如图13\-11所示: | Zabbix\-WEB 🡪configuration 🡪hosts 🡪Create host 🡪Host name和Agent interfaces,同时选择添加templates模板🡪选择Add 🡪勾选Template OS Linux\-选择Add提交;注\*此处Host name名称与Agentd.conf配置文件中Hostname保持一致,否则会报错。 | | --- | ![](/media/202411/20241125143342884075.png) 图13\-11 Zabbix 添加客户端监控 将客户端主机链接至“Template OS Linux”,启用模板完成主机默认监控,单击Add ,继续单击Update即可,如图13\-12所示: ![](/media/202411/20241125143342917688.png) 图13\-12 Zabbix 为客户端监控添加模板 单击Zabbix WEB🡪Monitoring🡪Graphs🡪Group🡪Host🡪Graph,监控图像如图13\-13(a)、13\-13(b)所示: ![](/media/202411/20241125143342923240.png) 图13\-13(a) Zabbix客户端监控图像 ![](/media/202411/20241125143342928233.png) 图13\-13(b) Zabbix客户端监控图像 如果无法监控到客户端,可以在Zabbix Server端,执行命令获取Agent的items KEY值是否有返回,例如system.uname为返回客户端的uname信息,监测命令如下: | /usr/local/zabbix/bin/zabbix\_get \-s 192\.168\.149\.130 \-k system.uname | | --- | ## Zabbix配置文件优化实战 Zabbix监控系统组件分为Server、Proxy、Agentd端,对参数的详细了解,能够更加深入理解Zabbix监控功能,及对Zabbix进行调优,如下为三个组件常用参数详解: 1. Zabbix\_server.conf配置文件参数详解: | DBHost 数据库主机地址;DBName 数据库名称;DBPassword 数据库密码;DBPort 数据库端口,默认为3306;AlertScriptsPath 告警脚本存放路径;CacheSize 存储监控数据的缓存;CacheUpdateFrequency 更新一次缓存时间;DebugLevel 日志级别;LogFile 日志文件;LogFileSize 日志文件大小,超过自动切割;LogSlowQueries 数据库慢查询记录,单位毫秒;PidFile PID文件;ProxyConfigFrequency Proxy被动模式下,Server多少秒同步配置文件至proxy;ProxyDataFrequency 被动模式下,Server间隔多少秒向proxy请求历史数据;StartDiscoverers 发现规则线程数;Timeout 连接Agent超时时间;TrendCacheSize 历史数据缓存大小;User Zabbix运行的用户;HistoryCacheSize 历史记录缓存大小;ListenIP 监听本机的IP地址;ListenPort 监听端口;LoadModule 模块名称;LoadModulePath 模块路径。 | | --- | 1. Zabbix\_Proxy.conf配置文件参数详解: | ProxyMode Proxy工作模式,默认为主动模式,主动发送数据至Server;Server 指定Server端地址;ServerPort Server端PORT;Hostname Proxy端主机名;ListenPort Proxy端监听端口;LogFile Proxy代理端日志路径;PidFile PID文件的路径;DBHost Proxy端数据库主机名;DBName Proxy端数据库名称;DBUser Proxy端数据库用户;DBPassword Proxy端数据库密码;DBSocket Proxy数据库SOCKET路径;DBPort Proxy数据库端口号;DataSenderFrequency Proxy向Server发送数据的时间间隔;StartPollers Proxy程池数量;StartDiscoverers Proxy端自动发现主机的线程数量;CacheSize 内存缓存配置;StartDBSyncers 同步数据线程数;HistoryCacheSize 历史数据缓存大小;LogSlowQueries 慢查询日志记录,单位为毫秒;Timeout 超时时间。 | | --- | 1. Zabbix\_agentd.conf配置文件参数详解: | EnableRemoteCommands 运行服务端远程至客户端执行命令或者脚本;Hostname 客户端主机名;ListenIP 监听的IP地址;ListenPort 客户端监听端口;LoadModulePath 模块路径;LogFile 日志文件路径;PidFile PID文件名;Server 指定Server IP地址;ServerActive Zabbix主动监控server的ip地址;StartAgents Agent启动进程,如果设置为0,表示禁用被动监控;Timeout 超时时间User 运行Zabbix的用户;UserParameter 用户自定义key;BufferSize 缓冲区大小;DebugLevel Zabbix日志级别。 | | --- | ## Zabbix自动发现及注册 熟练通过Zabbix监控平台监控单台客户端之后,企业中有成千上万台服务器,如果手工添加会非常耗时间,造成大量的人力成本的浪费,有没有什么好的自动化添加客户端的方法呢? Zabbix自动发现就是为了解决批量监控而设计的功能之一,什么是自动发现呢,简单来说就是Zabbix Server端可以基于设定的规则,自动批量的去发现局域网若干服务器,并自动把服务器添加至Zabbix监控平台,省去人工手动频繁的添加,节省大量的人力成本。 Zabbix相对于Nagios、Cacti监控来说,如果要想批量监控,Nagios、Cacti需要手动单个添加设备、分组、项目、图像,也可以使用脚本,但是不能实现自发方式添加。 Zabbix最大的特点之一就是可以批量自动主机并监控,利用发现(Discovery)模块,实现自动发现主机、自动将主机添加到主机组、自动加载模板、自动创建项目(Items)、自动创建监控图像,操作步骤如下: 1. Configuration🡪discovery 🡪 Create discovery rule,如图13\-14所示: ![](/media/202411/20241125143342942726.png) 图13\-14 创建客户端发现规则 | Name: 规则名称;Discovery by proxy : 通过代理探索;IP range : zabbix\_server 探索区域的IP范围;Delay : 搜索一次的时间间隔;Checks : 检测方式,如用ping方式去发现主机,zabbix\_server需安装fping,此处使用Agent方式发现;Device uniqueness criteria: 以IP地址作为被发现主机的标识。 | | --- | 1. Zabbix客户端安装Agent 由于发现规则里选择checks方式为Agent,所以需在所有被监控的服务器安装zabbix Agent,安装的方法可以手动安装,也可以使用Shell脚本,附Zabbix客户端安装脚本,脚本运行方法:sh auto\_install\_zabbix.sh。 | \#!/bin/bash\#auto install zabbix\#by jfedu.net 2022\#\#\#\#\#\#\#\#\#\#\#\#\#ZABBIX\_SOFT\="zabbix\-3\.2\.6\.tar.gz"INSTALL\_DIR\="/usr/local/zabbix/"SERVER\_IP\="192\.168\.149\.128"IP\=\`ifconfig\|grep Bcast\|awk '{print $2}'\|sed 's/addr://g'\`AGENT\_INSTALL(){yum \-y install curl curl\-devel net\-snmp net\-snmp\-devel perl\-DBIgroupadd zabbix ;useradd \-g zabbix zabbix;usermod \-s /sbin/nologin zabbixtar \-xzf $ZABBIX\_SOFT;cd \`echo $ZABBIX\_SOFT\|sed 's/.tar.\*//g'\`./configure \-\-prefix\=/usr/local/zabbix \-\-enable\-agent\&\&make installif \[ $? \-eq 0 ];then ln \-s /usr/local/zabbix/sbin/zabbix\_\* /usr/local/sbin/ficd \- ;cd zabbix\-3\.2\.6cp misc/init.d/tru64/zabbix\_agentd /etc/init.d/zabbix\_agentd ;chmod o\+x /etc/init.d/zabbix\_agentd\#config zabbix agentdcat \>$INSTALL\_DIR/etc/zabbix\_agentd.conf\<\<EOFLogFile\=/tmp/zabbix\_agentd.logServer\=$SERVER\_IPServerActive\=$SERVER\_IPHostname \= $IP EOF\#start zabbix agentd/etc/init.d/zabbix\_agentd restart/etc/init.d/iptables stopsetenforce 0}AGENT\_INSTALL | | --- | 1. 创建发现Action Zabbix发现规则创建完毕,客户端Agent安装完后,被发现的IP主机不会自动添加至Zabbix监控列表,需要添加发现动作,添加方法如下: | Configuration🡪 Actions 🡪 Event source(选择Discovery) 🡪 Create action | | --- | 添加规则时,系统默认存在一条发现规则,可以新建规则,也可以编辑默认规则,如图13\-15(a)、13\-15(b)、13\-15(c)所示,编辑默认发现规则,单击Operations设置发现操作,分别设置Add host、Add to host groups、Link to templates,最后启用规则即可: ![](/media/202411/20241125143342950517.png) 图13\-15(a) 创建客户端发现动作 ![](/media/202411/20241125143342955661.png) 图13\-15(b) 客户端发现自动添加至Zabbix ![](/media/202411/20241125143342960903.png) 图13\-15(c) 客户端发现自动添加至Zabbix Montoring🡪Discovery,查看通过发现规则找到的服务器IP列表,如图13\-16所示: ![](/media/202411/20241125143342967263.png) 图13\-16 被发现的客户端列表 Configuration🡪Hosts,查看4台主机是否被自动监控至Zabbix监控平台,如图13\-17所示: ![](/media/202411/20241125143342972700.png) 图13\-17 自动发现的主机被添加至Hosts列表 Monitoring🡪Graphs,监控图像查看,如图13\-18(a)、13\-18(b)所示,可以选择Host、Graph分别查看各种的监控图像:![](/media/202411/20241125143342979615.png) 图13\-18(a) 客户端监控图像 ![](/media/202411/20241125143342985469.png) 图13\-18(b) 客户端监控图像 ## Zabbix监控邮件报警实战 Zabbix监控服务端、客户端都已经部署完成,被监控主机已经添加,Zabiix监控运行正常,通过查看Zabbix监控服务器,可以了解服务器的运行状态是否正常,运维人员不会时刻登录Zabbix监控平台刷新,查看服务器的状态。 可以在Zabbix服务端设置邮件报警,当被监控主机宕机或者达到设定的触发器预设值时,不管任何时候,会自动发送报警邮件、微信信息到指定的人员,运维人员收到信息有利于第一时间解决故障。Zabbix邮件报警设置步骤如下: 1. 设置邮件模板及邮件服务器 Administration🡪Media types🡪Create media type,填写邮件服务器信息,根据提示设置完毕,如图13\-19(a)、13\-19(b)所示: ![](/media/202411/20241125143342992084.png) 图13\-19(a) Zabbix邮件报警邮箱设置 ![](/media/202411/20241125143342997410.png) 图13\-19(b) Zabbix邮件报警邮箱设置 1. 配置接收报警的邮箱 Administration\-user\-Admin (Zabbix Administrator)\-user\-admin,选择Media,单击Add添加发送邮件的类型“Email”,同时指定接收邮箱地址:wgkgood@163\.com,根据实际需求改成自己的接收人,如图13\-20所示: ![](/media/202411/20241125143343003088.png) 图13\-20 Zabbix邮件报警添加接收人 1. 添加报警触发器 Configuration🡪Actions🡪Action🡪 Event source🡪Triggers\-Create Action,如图13\-21(a)、13\-21(b)、13\-21(c)所示,分别设置Action、Operations、Recovery operations。 * Action🡪New condition选择“Trigger serverity\>\=Warning”; * Operations🡪设置报警间隔为60s,自定义报警信息,报警信息发送至administrators组; * Recovery operations 🡪自定义恢复信息,恢复信息发送至administrators组。 ![](/media/202411/20241125143343008850.png) 图13\-21(a) 邮件报警Action设置 ![](/media/202411/20241125143343014177.png) 图13\-21(b) 邮件报警Operations设置 ![](/media/202411/20241125143343020491.png) 图13\-21(c) 邮件报警Recovery Operations设置 报警邮件标题可以使用默认信息,亦可使用如下中文报警内容: | 名称:Action\-Email默认标题:故障{TRIGGER.STATUS},服务器:{HOSTNAME1}发生: {TRIGGER.NAME}故障!默认信息:告警主机:{HOSTNAME1}告警时间:{EVENT.DATE} {EVENT.TIME}告警等级:{TRIGGER.SEVERITY}告警信息: {TRIGGER.NAME}告警项目:{TRIGGER.KEY1}问题详情:{ITEM.NAME}:{ITEM.VALUE}当前状态:{TRIGGER.STATUS}:{ITEM.VALUE1}事件ID:{EVENT.ID} | | --- | 恢复邮件标题可以使用默认信息,亦可使用如下中文报警恢复内容: | 恢复标题:恢复{TRIGGER.STATUS}, 服务器:{HOSTNAME1}: {TRIGGER.NAME}已恢复!恢复信息:告警主机:{HOSTNAME1}告警时间:{EVENT.DATE} {EVENT.TIME}告警等级:{TRIGGER.SEVERITY}告警信息: {TRIGGER.NAME}告警项目:{TRIGGER.KEY1}问题详情:{ITEM.NAME}:{ITEM.VALUE}当前状态:{TRIGGER.STATUS}:{ITEM.VALUE1}事件ID:{EVENT.ID} | | --- | Monitoring🡪Problems,检查有问题的Action事件,单击Time下方时间,如图13\-22(a)、13\-22(b)所示,可以看到邮件是否执行成功或者失败: ![](/media/202411/20241125143343029132.png) 图13\-22(a) Zabbix查看有问题的事件 ![](/media/202411/20241125143343034382.png) 图13\-22(b) Zabbix有问题的事件执行任务 Zabbix邮件发送失败,报错Support for SMTP authentication was not compiled in,原因是由于Zabbix CURL版本要求至少是7\.20\+版本,升级CURL,升级方法: 创建repo源,vim /etc/yum.repos.d/city\-fan.repo,并且写入如下的语句: | cat\>/etc/yum.repos.d/city\-fan.repo\<\<EOF\[CityFan] name\=City Fan Repo baseurl\=http://www.city\-fan.org/ftp/contrib/yum\-repo/rhel5/x86\_64/ enabled\=1 gpgcheck\=0EOFyum clean allyum install curl | | --- | ![](/media/202411/20241125143343040046.png) curl \-V ![](/media/202411/20241125143343046733.png) CURL升级完毕之后,测试邮件发送,还是报同样的错误,原因是因为需要重新将Zabbix\_Server服务通过源码编译安装一遍,安装完zabbx\_server,重启服务,乱码问题是由于数据库字符集需改成UTF\-8格式,同时将数Zabbix库导出,然后修改latin1为utf8,再将SQL导入,重启Zabbix即可,最终如图13\-23(a)、13\-23(b)、13\-23(c)所示: ![](/media/202411/20241125143343051941.png) 图13\-23(a) Zabbix事情发送邮件进程 ![](/media/202411/20241125143343057343.png) 图13\-23(b) Zabbix监控故障item发送报警邮件 ![](/media/202411/20241125143343063025.png) 图13\-23(c) Zabbix监控故障item恢复发送邮件 ## Zabbix监控MYSQL主从实战 Zabbix监控除了可以使用Agent监控客户端服务器状态、CPU、内存、硬盘、网卡流量,同时Zabbix还可以监控MySQL主从用、监控LAMP、Nginx WEB服务器等等,如下为Zabbix监控MYSQL 主从复制的步骤: 1. 在Zabbix Agent端/data/sh目录创建Shell脚本:mysql\_ab\_check.sh,写入如下代码: | \#!/bin/bash/usr/local/mysql/bin/mysql \-uroot \-e 'show slave status\\G' \|grep \-E "Slave\_IO\_Running\|Slave\_SQL\_Running"\|awk '{print $2}'\|grep \-c Yes | | --- | 1. 在客户端Zabbix\_agentd.conf配置文件中加入如下代码: | UserParameter\=mysql.replication,sh /data/sh/mysql\_ab\_check.sh | | --- | 1. Zabbix服务器端获取监控数据,如果返回值为2,则证明丛库I/O、SQL线程均为YES,表示主从同步成功: | /usr/local/zabbix/bin/zabbix\_get \-s 192\.168\.149\.129 \-k mysql.replication | | --- | 1. Zabbix WEB平台,在192\.168\.149\.129 hosts中创建item监控项,如图13\-24(a)、13\-24(b)所示,单击右上角create item,Key填写Zabbix Agentd配置文件中的mysql.replication即可: ![](/media/202411/20241125143343071341.png) 图13\-24(a) Zabbix添加MYSQL主从item ![](/media/202411/20241125143343076498.png) 图13\-24(b) Zabbix添加MYSQL主从item MYSQL主从监控项创建Graph图像,如图13\-25(a)、13\-25(b)所示: ![](/media/202411/20241125143343081959.png) 图13\-25(a) 创建MYSQL主从监控图像 ![](/media/202411/20241125143343087954.png)图13\-25(b) 创建MYSQL主从监控图像 MYSQL主从监控项创建触发器,如图13\-26(a)、13\-26(b)所示,MYSQL主从状态监控,设置触发器条件为key值不等于2即可,不等于2即表示MYSQL主从同步状态异常,匹配触发器,执行Actions:![](/media/202411/20241125143343093155.png) 图13\-26(a) 创建MYSQL主从监控触发器 ![](/media/202411/20241125143343098462.png) 图13\-26(b) 创建MYSQL主从监控触发器 如果主从同步状态异常,Key值不等于2,会触发邮件报警,报警信息如图13\-27所示: ![](/media/202411/20241125143343104097.png) 图13\-27 MYSQL主从监控报警邮件 ## Zabbix日常问题汇总 Zabbix 可以设置中文汉化,如果出现乱码解决办法,如果访问zabbix出现如下历史记录乱码, WEB界面乱码,原因是因为数据库导入前不是UTF\-8字符集,需要修改为UTF\-8模式,如图13\-28所示: ![](/media/202411/20241125143343109491.png)图13\-28 数据库原字符集latin1 MYSQL数据库修改字符集方法,vim /etc/my.cnf在配置段加入如下代码: | \[mysqld]character\-set\-server\= utf8\[client]default\-character\-set \= utf8\[mysql]default\-character\-set \= utf8 | | --- | 备份zabbix数据库,并删除原数据库,重新创建,再导入备份的数据库,修改导入的zabbix.sql文件里面的latin1为utf8,然后再导入到zabbix库,乱码问题解决。 | sed \-i 's/latin1/utf8/g' zabbix.sql | | --- | 如果在查看graphs监控图像界面的时候时候出现乱码,如图13\-29所示: ![](/media/202411/20241125143343115166.png) 图13\-29 Graphs图像乱码 从windows下控制面板\-\>字体\-\>选择一种中文字库,例如“楷体”,如图13\-30所示: ![](/media/202411/20241125143343120290.png) 图13\-30 上传Windows简体中文字体 将字体文件cp至zabbix服务dauntfonts目录下,/var/www/html/zabbix/fonts,并且将STKAITI.TTF重命名为DejaVuSans.ttf,最好刷新Graph图像,乱码问题解决,如图13\-31(a)、13\-31(b)所示: ![](/media/202411/20241125143343126028.png) 图13\-31(a) 上传Windows简体中文字体 ![](/media/202411/20241125143343131131.png) 图13\-31(b) Graph图像乱码问题解决 ## Zabbix触发命令及脚本 Zabbix监控在对服务或者设备进行监控的时候,如果被监控客户端服务异常,满足触发器,默认可以发送邮件报警、短信报警及微信报警。Zabbix还可以远程执行命令或者脚本对部分故障实现自动修复。具体可以执行的任务包括: * 重启应用程序,例如Apache、Nginx、MySQL、Tomcat服务等; * 通过IPMI接口重启服务器; * 删除服务器磁盘空间及数据; * 执行脚本及资源调度管理; * 远程命令最大长度为255字符; * 同时支持多个远程命令; * Zabbix代理不支持远程命令。 使用Zabbix远程执行命令,首先需在zabbix客户端配置文件开启对远程命令的支持,在zabbix\_agentd.conf行尾加入如下代码,并重启服务,如图13\-32所示: | EnableRemoteCommands \= 1 | | --- | ![](/media/202411/20241125143343136749.png) 图13\-32 客户端配置远程命令支持 创建Action,Configuration🡪Actions🡪Triggers,如图13\-33(a)、13\-33(b)所示,类型选择“Remote Command”,steps表示执行命令1\-3次, step duration设置每次命令间隔时间的5秒执行一次,执行命令方式选择Zabbix agent,基于sudo执行命令即可: ![](/media/202411/20241125143343142161.png) 图13\-33(a) 客户端触发器满足条件 ![](/media/202411/20241125143343147263.png) 图13\-33(b) Operations类型选择Remote Command Zabbix客户端Sudoer配置文件中添加zabbix用户拥有执行权限且无需密码登录: | Defaults:zabbix !requirettyzabbix ALL\=(ALL) NOPASSWD: ALL | | --- | Zabbix客户端/data/sh/,创建auto\_clean\_disk.sh,脚本代码如下: | \#!/bin/bash\#auto clean disk space\#2022年6月21日10:12:18\#by author jfedu.netrm \-rf /boot/test.imgfind /boot/ \-name "\*.log" \-size \+100M \-exec rm \-rf {} \\; | | --- | 将192\.168\.149\.129服务器/boot目录,临时写满,然后满足触发器,实现远程命令执行,查看问题事件命令执行结果,如图13\-34(a)、13\-34(b)所示: ![](/media/202411/20241125143343153593.png) 图13\-34(a) Remote Command执行成功 ![](/media/202411/20241125143343158565.png) 图13\-34(b) Remote Command执行磁盘清理成功 如果Zabbix客户端脚本或者命令没有执行成功,http服务没有停止,可以在Zabbix server端执行如下命令,如图13\-35所示: | /usr/local/zabbix/bin/zabbix\_get \-s 192\.168\.149\.129 \-k "system.run\[sudo /etc/init.d/httpd restart]" | | --- | ![](/media/202411/20241125143343163840.png) 图13\-35 测试Remote Command命令 ## Zabbix分布式监控实战 Zabbix是一个分布式监控系统,它可以以一个中心点、多个分节点的模式运行,使用Proxy能大大的降低Zabbix Server的压力,Zabbix Proxy可以运行在独立的服务器上,如图13\-36所示: ![](/media/202411/20241125143345825416.png) 图13\-36 Zabbix Proxy网络拓扑图 安装Zabbix Proxy,基于Zabbix\-3\.2\.6\.tar.gz软件包,同时需要导入zabbix基本框架库,具体实现方法如下: 1. 下载Zabbix软件包,代码如下: | wget [http://sourceforge.net/projects/zabbix/files/ZABBIX%20Latest%20Stable/3\.2\.6/zabbix\-3\.2\.6\.tar.gz/download](http://sourceforge.net/projects/zabbix/files/ZABBIX%20Latest%20Stable/3.2.6/zabbix-3.2.6.tar.gz/download) | | --- | 1. Zabbix Proxy上执行如下代码: | yum \-y install curl curl\-devel net\-snmp net\-snmp\-devel perl\-DBIgroupadd zabbix ;useradd \-g zabbix zabbix;usermod \-s /sbin/nologin zabbix | | --- | 1. Zabbix Proxy端配置 创建zabbix数据库,执行授权命令: | create database zabbix\_proxy charset\=utf8;grant all on zabbix\_proxy.\* to zabbix@localhost identified by '123456';flush privileges; | | --- | 解压zabbix软件包并将Zabbix基础SQL文件导入数据至Zabbix数据库: | tar zxvf zabbix\-3\.2\.6\.tar.gzcd zabbix\-3\.2\.6mysql \-uzabbix \-p123456 zabbix\_proxy \<database/mysql/schema.sqlmysql \-uzabbix \-p123456 zabbix\_proxy \<database/mysql/images.sql | | --- | 切换至Zabbix解压目录,执行如下代码,安装Zabbix\_server: | ./configure \-\-prefix\=/usr/local/zabbix/ \-\-enable\-proxy \-\-enable\-agent \-\-with\-mysql \-\-enable\-ipv6 \-\-with\-net\-snmp \-\-with\-libcurlmakemake installln \-s /usr/local/zabbix/sbin/zabbix\_\* /usr/local/sbin/ | | --- | Zabbix Proxy安装完毕,cd /usr/local/zabbix/etc/目录,如图13\-37所示: ![](/media/202411/20241125143345832764.png)图13\-37 Zabbix Proxy安装目录 1. 备份Zabbix Proxy配置文件,代码如下: | cp zabbix\_proxy.conf zabbix\_proxy.conf.bak | | --- | 1. 将zabbix\_proxy.conf配置文件中代码设置为如下: | Server\=192\.168\.149\.128Hostname\=192\.168\.149\.130LogFile\=/tmp/zabbix\_proxy.logDBName\=zabbix\_proxyDBUser\=zabbixDBPassword\=123456Timeout\=4LogSlowQueries\=3000DataSenderFrequency\=30HistoryCacheSize\=128MCacheSize\=128M | | --- | 1. Zabbix客户端安装Agent,同时配置Agent端Server设置为Proxy服务器的IP地址或者主机名,zabbix\_agentd.conf配置文件代码: | LogFile\=/tmp/zabbix\_agentd.logServer\=192\.168\.149\.130ServerActive\=192\.168\.149\.130Hostname \= 192\.168\.149\.131 | | --- | 1. Zabbix Server WEB端添加Proxy,实现集中管理和分布式添加监控,如图13\-38(a)、13\-38(b)、13\-38(c)所示: ![](/media/202411/20241125143345840234.png) 图13\-38(a) Zabbix Proxy WEB添加 ![](/media/202411/20241125143345845525.png) 图13\-38(b) Zabbix Proxy监控客户端 ![](/media/202411/20241125143345850786.png) 图13\-38(c) Zabbix Proxy监控客户端图像 ## Zabbix监控微信报警实战 Zabbix除了可以使用邮件报警之外,还可以通过多种方式把告警信息发送到指定人,例如短信报警方式,越来越多的企业开始使用Zabbix结合微信作为主要的告警方式,因为每个人每天都在使用微信,这样可以及时有效的把告警信息推送到接收人,方便告警的及时处理。Zabbix微信报警怎么设置呢,设置的步骤有哪些呢,方法步骤如下: 1. 微信企业号注册 企业号注册地址:https://qy.weixin.qq.com/填写企业注册信息,等待审核完,并且微信扫描登录企业公众号,如图13\-39(a)、13\-39(b)所示: ![](/media/202411/20241125143345856057.png) 图13\-39(a) 微信企业公众号注册 ![](/media/202411/20241125143345862427.png)图13\-39(b) 微信企业公众号登录 1. 通讯录添加运维部门及人员 登录新建的企业号,通过提前把企业成员信息添加到组织或者部门,需要填写手机号、微信号或邮箱,通过这样方式让别人扫码关注企业公众号,为了后面企业号推送消息给企业成员,如图13\-40(a)、13\-40(b)所示: ![](/media/202411/20241125143345869130.png)图13\-40(a) 微信企业公众号通讯录![](/media/202411/20241125143345874222.png)图13\-40(b) 微信企业公众号通讯录 1. 企业应用\-创建应用 除了对个人添加微信报警之外,还可以添加不同管理组,接受同一个应用推送的消息, 成员账号,组织部门ID,应用Agent ID,CorpID和Secret,调用API接口需要用到这些信息,如图13\-41(a)、13\-41(b)、13\-41(c)所示: ![](/media/202411/20241125143345879404.png)图13\-41(a) 微信企业公众号创建应用![](/media/202411/20241125143345884622.png)图13\-41(b) 微信企业公众号创建应用![](/media/202411/20241125143345889788.png)图13\-41(c) 微信企业公众号创建应用 1. 获取企业CorpID,单击企业公众号首页“我的企业”,即可看到,如图13\-42所示: ![](/media/202411/20241125143345895212.png) 图13\-42 微信企业公众号CorpID 1. 微信接口调试,调用微信接口需要一个调用接口的凭证:Access\_token通过CorpID和Secret可以获得Access\_token,微信企业号接口调试地址: http://qydev.weixin.qq.com/debug,如图 13\-43(a)、13\-43(b)所示: ![](/media/202411/20241125143345900719.png) 图13\-43(a) 微信企业公众号调试 ![](/media/202411/20241125143345906058.png) 图13\-43(b) 微信企业公众号调试 1. 获取微信报警工具 | mkdir \-p /usr/local/zabbix/alertscriptscd /usr/local/zabbix/alertscriptswget http://dl.cactifans.org/tools/zabbix\_weixin.x86\_64\.tar.gztar zxvf zabbix\_weixin.x86\_64\.tar.gzmv zabbix\_weixin/weixin .chmod o\+x weixinmv zabbix\_weixin/weixincfg.json /etc/rm \-rf zxvf zabbix\_weixin.x86\_64\.tar.gzrm \-rf zabbix\_weixin/ | | --- | 修改/etc/ weixincfg.json配置文件中corpid、secret、agentid,并测试脚本发送信息,如图13\-44(a)、13\-44(b)所示: | cd /usr/local/zabbix/alertscripts./weixin wuguangke 京峰教育报警测试 Zabbix故障报警./weixin contact subject body标准信息格式:Contact,为你的微信账号,注意不是微信号,不是微信昵称,可以把用户账号设置成微信号或微信昵称,Subject 告警主题,Body 告警详情。 | | --- | ![](/media/202411/20241125143345912741.png) 图13\-44(a) Zabbix Server端微信配置文件 ![](/media/202411/20241125143345918271.png) 图13\-44(b) Zabbix Server端微信配置文件 1. 脚本调用设置 Zabbix\_Server端设置脚本执行路径,编辑zabbix\_server.conf文件,添加如下内容: | AlertScriptsPath\=/usr/local/zabbix/alertscripts | | --- | 1. Zabbix WEB端配置,设置Actions动作,并设置触发微信报警,如图13\-45(a)、13\-45(b)、13\-45(c)所示: ![](/media/202411/20241125143345924204.png) 图13\-45(a) Zabbix Server Action动作配置 ![](/media/202411/20241125143345929337.png)图13\-45(b) Zabbix Server Action动作配置 ![](/media/202411/20241125143345936112.png)图13\-45(c) Zabbix Server Action动作配置 1. 配置Media Type 微信脚本,Administration🡪Media Types🡪Create Media Type如图13\-46所示,脚本加入三个参数:{ALERT.SENDTO}、{ALERT.SUBJECT}、{ALERT.MESSAGE}: ![](/media/202411/20241125143345950148.png) 图13\-46 Zabbix Server Media Types配置 1. 配置接收微信信息的用户,Administration🡪Users🡪Admin🡪Media如图13\-47所示: ![](/media/202411/20241125143345956189.png) 图13\-47 Zabbix Server Users Media 1. 微信报警信息测试,磁盘容量剩余不足20%,会触发微信报警,如图13\-48(a)、13\-48(b)、13\-48(c)所示: ![](/media/202411/20241125143345961574.png) 图13\-48(a)Zabbix 微信报警信息 ![](/media/202411/20241125143345967147.png)图13\-48(b)Zabbix 微信报警故障信息 ![](/media/202411/20241125143345974810.png) 图13\-48(c)Zabbix 微信报警恢复信息 # Nginx WEB服务器企业实战 万维网 (WORLD WIDE WEB,WWW)服务器,也称之为WEB服务器,主要[功能](http://baike.baidu.com/view/587727.htm" \t "http://baike.baidu.com/_blank)是提供网上[信息](http://baike.baidu.com/view/1527.htm" \t "http://baike.baidu.com/_blank)浏览服务。目前主流的WEB服务器软件包括:Apache、Nginx、Lighttpd、IIS、Resin、Tomcat、WebLogic、Jetty。 本章向读者介绍Nginx高性能WEB服务器、Nginx工作原理、安装配置及升级、Nginx配置文件深入剖析、Nginx虚拟主机、Location案例演示、Nginx Rewirte企业案例实战、HTTPS安全WEB服务器及Nginx高性能集群实战等。 ## Nginx WEB入门简介 Nginx ("engine x") 是一个高性能HTTP 和 [反向代理](http://baike.baidu.com/view/1165595.htm" \t "http://baike.baidu.com/_blank) 服务器、IMAP、POP3、SMTP [服务器](http://baike.baidu.com/view/751.htm" \t "http://baike.baidu.com/_blank)。 Nginx 是由 Igor Sysoev 为[俄罗斯](http://baike.baidu.com/view/2403.htm" \t "http://baike.baidu.com/_blank)访问量第二的 Rambler.ru 站点开发的,第一个公开版本0\.1\.0发布于2004年10月4日。其将[源代码](http://baike.baidu.com/view/60376.htm" \t "http://baike.baidu.com/_blank)以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低[系统资源](http://baike.baidu.com/view/53557.htm" \t "http://baike.baidu.com/_blank)的消耗而闻名。 由于Nginx的高性能、轻量级,目前越来越多的互联网企业开始使用Nginx WEB服务器。据Netcraft统计,在2022年4月份,[世界上最繁忙的网站中有28\.72 %](http://news.netcraft.com/archives/2012/08/02/august-2012-web-server-survey.html)使用Nginx作为其服务器或者代理服务器。 | nginx \[engine x] is an HTTP and reverse proxy server, a mail proxy server, and a generic TCP/UDP proxy server, originally written by [Igor Sysoev](http://sysoev.ru/en/). For a long time, it has been running on many heavily loaded Russian sites including [Yandex](http://www.yandex.ru/), [Mail.Ru](http://mail.ru/), [VK](http://vk.com/), and [Rambler](http://www.rambler.ru/). According to Netcraft, nginx served or proxied [28\.72% busiest sites in April 2022](https://news.netcraft.com/archives/2017/04/21/april-2017-web-server-survey.html). Here are some of the success stories: [Netflix](https://openconnect.itp.netflix.com/software/),[Wordpress.com](https://www.nginx.com/case-studies/nginx-wordpress-com/), [FastMail.FM](http://blog.fastmail.fm/2007/01/04/webimappop-frontend-proxies-changed-to-nginx/).The sources and documentation are distributed under the [2\-clause BSD\-like license](http://nginx.org/LICENSE).Commercial support is available from [Nginx, Inc.](https://www.nginx.com/) | | --- | 它已经在众多流量很大的俄罗斯网站上使用了很长时间,这些网站包括[Yandex](http://www.yandex.ru/)、[Mail.Ru](http://www.mail.ru/)、[VKontakte](http://www.vkontakte.ru/),以及[Rambler](http://www.rambler.ru/)。目前互联网主流公司京东、360、百度、新浪、腾讯、阿里都在使用Nginx作为自己的WEB服务器。 Nginx特点是占有[内存](http://baike.baidu.com/view/1082.htm" \t "http://baike.baidu.com/_blank)少,[并发](http://baike.baidu.com/view/684757.htm" \t "http://baike.baidu.com/_blank)能力强,事实上Nginx的并发能力确实在同类型的网页服务器中表现较好。 Nginx相对于Apache优点如下: * 高并发响应性能非常好,官方Nginx处理静态文件并发5w/s; * 负载均衡及反向代理性能非常强; * 系统内存和CPU占用率低; * 可对后端服务进行健康检查; * 支持PHP cgi方式和FastCGI方式; * 可以作为缓存服务器、邮件代理服务器; * 配置代码简洁且容易上手。 ## Nginx工作原理 Nginx WEB服务器最主要就是各种模块的工作,模块从结构上分为核心模块、基础模块和第三方模块,其中三类模块分别如下: * 核心模块:HTTP模块、EVENT模块和MAIL模块等; * 基础模块:HTTP Access模块、HTTP FastCGI模块、HTTP Proxy模块和HTTP Rewrite模块; * 第三方模块:HTTP Upstream Request Hash模块、Notice模块和HTTP Access Key模块、Limit\_req模块等; Nginx的模块从功能上分为如下三类。 * Handlers(处理器模块):此类模块直接处理请求,并进行输出内容和修改headers信息等操作,Handlers处理器模块一般只能有一个; * Filters (过滤器模块):此类模块主要对其他处理器模块输出的内容进行修改操作,最后由Nginx输出; * Proxies (代理类模块):此类模块是Nginx的HTTP Upstream之类的模块,这些模块主要与后端一些服务比如FastCGI等进行交互,实现服务代理和负载均衡等功能。 Nginx由内核和模块组成,其中内核的设计非常微小和简洁,完成的工作也非常简单,仅仅通过查找配置文件将客户端的请求映射到一个location block,而location是Nginx配置中的一个指令,用于访问的URL匹配,而在这个location中所配置的每个指令将会启动不同的模块去完成相应的工作,如图14\-1所示: ![](/media/202411/20241125143345985439.png)图14\-1 Nginx WEB工作流程图 Nginx的高并发得益于其采用了epoll模型,与传统的服务器程序架构不同,epoll是Linux内核2\.6以后才出现的,Nginx采用epoll模型,异步非阻塞,而apache采用的是select模型: Select特点:select 选择句柄的时候,是遍历所有句柄,也就是说句柄有事件响应时,select需要遍历所有句柄才能获取到哪些句柄有事件通知,因此效率是非常低。 epoll的特点:epoll对于句柄事件的选择不是遍历的,是事件响应的,就是句柄上事件来就马上选择出来,不需要遍历整个句柄链表,因此效率非常高。 Nginx默认以80端口监听在服务器上,并且启动一个master进程,同时有master进程生成多个工作进程,当浏览器发起一个HTTP连接请求,每个进程都有可能处理这个连接,怎么做到的呢?怎么保证同一时刻一个HTTP请求被一个工作进程处理呢。 首先每个worker进程都是从Master进程fork出来,在Master进程里面,建立好需要listen的socket(listenfd)之后,会fork出多个worker进程。 所有worker进程的listenfd会在新连接到来时变得可读,为保证只有一个进程处理该连接,所有worker进程在注册listenfd读事件前抢accept\_mutex,抢到互斥锁的那个进程注册listenfd读事件,在读事件里调用accept接受该连接。 当一个worker进程在accept这个连接之后,就开始读取请求、解析请求、处理请求,产生数据后,再返回给客户端,最后才断开连接,这样形成一个完整的请求流程。如图14\-2所示: ![20160401103647146](/media/202411/20241125143345990952.jpeg)图14\-2 Nginx Worker进程工作原理 ## Nginx安装配置 Nginx WEB安装时可以指定很多的模块,默认需要安装Rewrite模块,也即是需要系统有PCRE库,安装Pcre支持Rewrite功能。如下为安装Nginx WEB服务器方法: 源码的路径,而不是编译后的路径,否则会报错。 | \#安装PCRE库支持yum install pcre\-devel pcre \-y\#下载Nginx源码包cd /usr/src wget \-c [http://nginx.org/download/nginx\-1\.12\.0\.tar.gz](http://nginx.org/download/nginx-1.4.2.tar.gz) \#解压Nginx源码包tar \-xzf nginx\-1\.12\.0\.tar.gz\#进入解压目录,然后sed修改Nginx版本信息为JWScd nginx\-1\.12\.0 ; sed \-i \-e 's/1\.12\.0//g' \-e 's/nginx\\//JWS/g' \-e 's/"NGINX"/"JWS"/g' src/core/nginx.h\#预编译Nginxuseradd www ;./configure \-\-user\=www \-\-group\=www \-\-prefix\=/usr/local/nginx \-\-with\-http\_stub\_status\_module \-\-with\-http\_ssl\_module\#.configure预编译成功后,执行make命令进行编译make\#make执行成功后,执行make install 正式安装make install\#至此Nginx WEB服务器安装完毕。 | | --- | 测试Nginx服务安装是否正确,同时启动Nginx WEB 服务,代码命令如下: | /usr/local/nginx/sbin/nginx \-t 检查nginx配置文件是否正确,返回OK即正确。\[root@localhost \~]\# /usr/local/nginx/sbin/nginx \-tnginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is oknginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful\[root@localhost \~]\#然后启动nginx,/usr/local/nginx/sbin/nginx 回车即可。查看进程是否已启动:\[root@localhost \~]\# ps \-ef \|grep nginxnobody 5381 30285 0 May16 ? 09:04:31 nginx: worker process root 30285 1 0 2022 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginxroot 32260 32220 0 12:34 pts/0 00:00:00 grep nginx\[root@localhost \~]\# | | --- | 通过浏览器访问Nginx默认测试页面,如图14\-3所示: ![](/media/202411/20241125143345997696.png)图14\-3 Nginx WEB浏览器访问 ## Nginx管理及升级 Nginx WEB服务器安装完毕,可以执行如下命令对其进管理和维护,命令如下: | \#查看nginx进程ps \-ef\|grep nginx\#平滑启动nginx kill \-HUP \`cat /var/run/nginx.pid\` 或者nginx \-s reload其中进程文件路径在配置文件nginx.conf中可以找到。平滑启动的意思是在不停止nginx的情况下,重启nginx,重新加载配置文件,启动新的工作线程,完美停止旧的工作线程。\#完美停止nginx kill \-QUIT \`cat /var/run/nginx.pid\`\#快速停止nginx kill \-TERM \`cat /var/run/nginx.pid\`或者kill \-INT \`cat /var/run/nginx.pid\`\#完美停止工作进程(主要用于平滑升级) kill \-WINCH \`cat /var/run/nginx.pid\`\#强制停止nginx pkill \-9 nginx\#检查对nginx.conf文件的修改是否正确 nginx \-t \-c /etc/nginx/nginx.conf 或者 nginx \-t\#停止nginx的命令nginx \-s stop或者pkill nginx\#查看nginx的版本信息nginx \-v\#查看完整的nginx的配置信息 nginx \-V | | --- | Nginx WEB服务器定期更新,如果需要将低版本升级或者将高版本降级,升级或者降级方法如下,分为四个步骤,包括软件下载、预编译、编译、配置,具体方法如下: | wget [http://www.nginx.org/download/nginx\-1\.4\.2\.tar.gz](http://www.nginx.org/download/nginx-1.4.2.tar.gz) 获取旧版本nginx的configure选项/usr/local/nginx/sbin/nginx \-V 编译新版本的Nginxtar \-xvf nginx\-1\.4\.2\.tar.gz cd nginx\-1\.4\.2 ./configure \-\-prefix\=/usr/local/nginx \-\-user\=www \-\-group\=www \-\-with\-http\_stub\_status\_module \-\-with\-http\_ssl\_module make 备份旧版本的nginx可执行文件,复制新版本的nginx这行文件mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old cp objs/nginx /usr/local/nginx/sbin/测试新版本nginx是否正常/usr/local/nginx/sbin/nginx \-t平滑重启升级nginxkill –QUIT \`cat /usr/local/nginx/log/nginx.oldbin\` \#\#关闭旧版nginx 验证nginx是否升级成功/usr/local/nginx/sbin/nginx \-V显示最新编译的版本信息即可。 | | --- | ## Nginx虚拟主机实战 在真实的企业服务器环境中,为了充分利用服务器的资源,单台Nginx WEB服务器同时会配置N个网站,也可称之为配置N个虚拟域名的主机,即多个域名对应同一个80端口。 在Nginx.conf中加入server代码,Nginx虚拟主机完整代码如下: | worker\_processes 1;events { worker\_connections 1024;}http { include mime.types; default\_type application/octet\-stream; sendfile on; keepalive\_timeout 65;\#virtual hosts config 2022/5/18server { listen 80; server\_name www.jf1\.com; access\_log logs/jf1\.access.log; location / { root html/jf1; index index.html index.htm; }}server { listen 80; server\_name www.jf2\.com; access\_log logs/jf2\.access.log; location / { root html/jf2; index index.html index.htm; } }} | | --- | 创建两个不同的目录mkdir –p /usr/local/nginx/html/{jf1,jf2},然后分别在两个目录创建两个不同的index.html网站页面即可。通过Windows客户端配置hosts绑定IP与两个域名的对应关系,在IE浏览器访问测试效果,如图14\-4(a)、14\-4(b)所示: ![](/media/202411/20241125143346006722.png) 图14\-4(a) Nginx 虚拟主机www.jf1\.com ![](/media/202411/20241125143346012233.png) 图14\-4(b) Nginx 虚拟主机www.jf2\.com ## Nginx Location深入剖析 Nginx由内核和模块组成,其中内核的设计非常微小和简洁,完成的工作也非常简单,仅仅通过查找配置文件将客户端的请求映射到一个location block,而location是Nginx配置中的一个指令,用于访问的URL匹配,而在这个location中所配置的每个指令将会启动不同的模块去完成相应的工作。 默认Nginx.conf配置文件中至少存在一个location /,即表示客户端浏览器请求的URL为:域名\+/,如果location /newindex/,则表示客户端浏览器请求的URL为:域名\+/newindex/。常见Location匹配URL的方式如下: | \= 字面精确匹配;^\~ 最大前缀匹配;/ 不带任何前缀:最大前缀匹配;\~ 大小写相关的正则匹配;\~\* 大小写无关的正则匹配;@ location内部重定向的变量。 | | --- | 其中Location \=、^\~、/属于普通字符串匹配,Location \~、\~\*属于正则表达式匹配,Location优先级与其在Nginx.conf配置文件中的先后顺序无关。 Location \= 精确匹配会第一个被处理,如果发现精确匹配,Nginx则停止搜索其他任何Location的匹配。 普通字符匹配,正则表达式规则和完整URL规则将被优先和查询匹配,^\~为最大前缀匹配,如果匹配到该规则,Nginx则停止搜索其他任何Location的匹配,否则nginx会继续处理其他location指令。 正则匹配"\~"和"\~\*",如果找到相应的匹配,则Nginx停止搜索其他任何Location的匹配;当没有正则表达式或者没有正则表达式被匹配的情况下,那么匹配程度最高的逐字匹配指令会被使用。 Location规则匹配优先级总结如下: | (location \=) \> (location 完整路径) \> (location ^\~ 路径) \> (location \~\|\~\* 正则顺序) \> (location 部分起始路径) \> (/) | | --- | 如下为Nginx Location规则案例演示: | location \= / { \[ configuration L1 ] \#只会匹配/,优先级比Location /低。}location \= /index.html { \[ configuration L2 ] \#只会匹配/index.html,优先级最高。}location / { \[ configuration L3 ] \#匹配任何请求,因为所有请求都是以"/"开始; \#但是更长字符匹配或者正则表达式匹配会优先匹配,优先级最低。}location \= /images/ { \[ configuration L4 ] \#匹配任何以/images/开始的请求,并停止匹配其它location;}location \~\* \\.(html\|txt\|gif\|jpg\|jpeg)$ { \[ configuration L5] \# 匹配以html、txt、gif、jpg、jpeg结尾的URL文件请求; \# 但是所有/images/目录的请求将由 \[Configuration L4]处理。}浏览器发起HTTP Request URI案例与Location规则案例匹配如下:* / \-\>匹配configuration L3; * /index.html匹配configuration L2; * /images/匹配configuration L4; * /images/logo.png匹配configuration L4; * /img/test.jpg匹配configuration L5。 | | --- | 企业生产环境中无需在Nginx.conf配置文件中同时添加五种规则匹配,如下为企业生产环境Nginx Location部分配置代码: | location /{ root /var/www/html/; expires 60d;}location \~ .\*\\.(gif\|jpg\|jpeg\|bmp\|png\|ico\|txt\|js\|css)${ root /var/www/html/; expires 60d; }location \~ .\*\\.(jsp\|php\|cgi\|do)${ root /var/www/html/; proxy\_pass http://linux\_web; proxy\_http\_version 1\.1; proxy\_set\_header Connection ""; proxy\_set\_header Host $host; proxy\_set\_header X\-Real\-IP $remote\_addr; proxy\_set\_header X\-Forwarded\-For $proxy\_add\_x\_forwarded\_for; }location \=/newindex.html{ root /var/www/newwww/; expires 60d;} | | --- | ## 企业实战Nginx动静分离架构 Nginx动静分离简单来说就是把动态跟静态请求分开,不能理解成只是单纯的把动态页面和静态页面物理分离。严格意义上说应该是动态请求跟静态请求分开,可以理解成使用Nginx处理静态页面,Tomcat、Resin、PHP、ASP处理动态页面。 动静分离从目前实现角度来讲大致分为两种,一种是纯粹的把静态文件独立成单独的域名,放在独立的服务器上,也是目前主流推崇的方案;另外一种方法就是动态跟静态文件混合在一起发布,通过Nginx来分开。 Nginx线上WEB服务器动静分离及Nginx.conf完整配置文件代码如下: | user www www;worker\_processes 8;worker\_cpu\_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;pid /usr/local/nginx/nginx.pid;worker\_rlimit\_nofile 102400;events{use epoll;worker\_connections 102400;}http{ include mime.types; default\_type application/octet\-stream; FastCGI\_intercept\_errors on; charset utf\-8; server\_names\_hash\_bucket\_size 128; client\_header\_buffer\_size 4k; large\_client\_header\_buffers 4 32k; client\_max\_body\_size 300m; sendfile on; tcp\_nopush on; keepalive\_timeout 60; tcp\_nodelay on; client\_body\_buffer\_size 512k; proxy\_connect\_timeout 5; proxy\_read\_timeout 60; proxy\_send\_timeout 5; proxy\_buffer\_size 16k; proxy\_buffers 4 64k; proxy\_busy\_buffers\_size 128k; proxy\_temp\_file\_write\_size 128k; gzip on; gzip\_min\_length 1k; gzip\_buffers 4 16k; gzip\_http\_version 1\.1; gzip\_comp\_level 2; gzip\_types text/plain application/x\-javascript text/css application/xml; gzip\_vary on;log\_format main '$remote\_addr \- $remote\_user \[$time\_local] "$request" ' '$status $body\_bytes\_sent "$http\_referer" ' '"$http\_user\_agent" $request\_time';upstream jvm\_web1 { server 192\.168\.149\.130:8080 weight\=1 max\_fails\=2 fail\_timeout\=30s; server 192\.168\.149\.130:8081 weight\=1 max\_fails\=2 fail\_timeout\=30s;}include vhosts.conf;} | | --- | 如下为vhosts.conf配置文件中内容: | server { listen 80; server\_name www.jf1\.com; index index.jsp index.html index.htm; root /data/webapps/www1; location / { proxy\_next\_upstream http\_502 http\_504 error timeout invalid\_header; proxy\_set\_header Host $host; proxy\_set\_header X\-Real\-IP $remote\_addr; proxy\_set\_header X\-Forwarded\-For $proxy\_add\_x\_forwarded\_for; proxy\_pass http://jvm\_web1; } location \~ .\*\\.(php\|jsp\|cgi\|shtml)?$ { proxy\_set\_header Host $host; proxy\_set\_header X\-Real\-IP $remote\_addr; proxy\_set\_header X\-Forwarded\-For $proxy\_add\_x\_forwarded\_for; proxy\_pass http://jvm\_web1; } location \~ .\*\\.(html\|htm\|gif\|jpg\|jpeg\|bmp\|png\|ico\|txt\|js\|css)$ { root /data/webapps/www1; expires 30d; } access\_log /data/logs/jvm\_web1/access.log main; error\_log /data/logs/jvm\_web1/error.log crit;} | | --- | 配置文件代码中:location \~ .\*\\.(php\|jsp\|cgi\|shtml)表示匹配动态页面请求,然后将请求proxy\_pass到后端服务器,而location \~ .\*\\.(html\|htm\|gif\|jpg\|jpeg \|ico\|txt\|js\|css)表示匹配静态页面请求本地返回。 检查Nginx配置是否正确即可,然后测试动静分离是否成功,在192\.168\.149\.130服务器启动8080、8081 Tomcat服务或者LAMP服务,删除后端Tomcat或者LAMP服务器上的某个静态文件,测试是否能访问该文件,如果可以访问说明静态资源Nginx直接返回了,如果不能访问,则证明动静分离不成功。 ## 企业实战LNMP高性能服务器 公共网关接口”(Common Gateway Interface,CGI),是HTTP服务器与本机或者其它机器上的程序进行通信的一种工具,其程序须运行在网络服务器上。CGI可以用任何一种语言编写,只要这种语言具有标准输入、输出和环境变量,如php、perl、tcl等。 Fast\-CGI是从CGI发展改进而来的。传统CGI接口方式的主要缺点是性能很差,因为每次HTTP服务器遇到动态程序时都需要重新启动脚本解析器来执行解析,然后将结果返回给HTTP服务器。这在处理高并发访问时几乎是不可用的。另外传统的CGI接口方式安全性也很差,现在已经很少使用。 FastCGI接口方式采用C/S结构,可以将HTTP服务器和脚本解析服务器分开,同时在脚本解析服务器上启动一个或者多个脚本解析守护进程。当HTTP服务器每次遇到动态程序时,可以将其直接交付给Fast\-CGI进程来执行,然后将得到的结果返回给浏览器。这种方式可以让HTTP服务器专一地处理静态请求或者将动态脚本服务器的结果返回给客户端,这在很大程度上提高了整个应用系统的性能。 FastCGI是语言无关的、可伸缩架构的CGI开放扩展,将CGI解释器进程保持在内存中,以此获得较高的性能。FastCGI是一个协议,php\-fpm实现了这个协议,php\-fpm的FastCGI协议需要有进程池,php\-fpm实现的FastCGI进程叫php\-cgi,所以php\-fpm其实是他自身的FastCGI或php\-cgi进程管理器。 LNMP WEB架构中,Nginx为一款高性能Web服务器,本身是不能处理PHP的,当接收到客户端浏览器发送HTTP Request请求时,Nginx服务器响应并处理web请求,静态资源CSS、图片、视频、TXT等静态文件请求,Nginx服务器可以直接处理并回应。 但是PHP动态页面请求Nginx不能直接处理,Nginx服务器会将PHP网页脚本通过接口传输协议(网关协议)PHP\-FCGI(Fast\-CGI)传输给PHP\-FPM(进程管理程序),PHP\-FPM不做处理,然后PHP\-FPM调用PHP解析器进程,PHP解析器解析PHP脚本信息。PHP解析器进程可以启动多个,可以实现多进行并发执行。 PHP解释器将解析后的脚本返回到PHP\-FPM,PHP\-FPM再通过Fast\-CGI的形式将脚本信息传送给Nginx,Nginx服务器再通过Http Response的形式传送给浏览器,浏览器再进行解析与渲染然后进行呈现。 如图14\-5所示: ![](/media/202411/20241125143346026397.png) ![1009724-20170725130531818-280167792](/media/202411/20241125143346034377.png) ![IMG_256](/media/202411/20241125143346044573.png)图14\-5 Nginx\+FastCGI通信原理图 CGI、FAST\-CGI、PHP\-CGI、PHP\-FPM概念总结: * CGI:Common gateway interface 通用网关接口; * FastCGI:Fast common gateway interface 快速通用网关接口; * PHP\-FPM:PHP\-Fast CGI Process Manager CGI,是FastCGII协议的实现并且带进程管理器; * PHP\-CGI是解析PHP代码的程序,属于PHP程序解释器,只负责解析请求,不负责进程管理; * PHP\-FPM是PHP\-CGI进程管理器,可以有效控制内存和进程、可以平滑重载PHP配置。 企业级LNMP(Nginx\+PHP(FastCGI)\+MySQL)主流架构配置方法如下,分别安装Nginx、MYSQL、PHP服务,步骤如下: 1. Nginx安装配置 | wget \-c http://nginx.org/download/nginx\-1\.12\.0\.tar.gz tar \-xzf nginx\-1\.12\.0\.tar.gzcd nginx\-1\.12\.0useradd www ;./configure \-\-user\=www \-\-group\=www \-\-prefix\=/usr/local/nginx \-\-with\-http\_stub\_status\_module \-\-with\-http\_ssl\_modulemakemake install | | --- | 1. MYSQL安装配置 | yum install cmake ncurses\-devel ncurses –ywget http://down1\.chinaunix.net/distfiles/mysql\-5\.5\.20\.tar.gztar \-xzf mysql\-5\.5\.20\.tar.gzcd mysql\-5\-5\.20cmake . \-DCMAKE\_INSTALL\_PREFIX\=/usr/local/mysql55 \\\-DMYSQL\_UNIX\_ADDR\=/tmp/mysql.sock \\\-DMYSQL\_DATADIR\=/data/mysql \\\-DSYSCONFDIR\=/etc \\\-DMYSQL\_USER\=mysql \\\-DMYSQL\_TCP\_PORT\=3306 \\\-DWITH\_XTRADB\_STORAGE\_ENGINE\=1 \\\-DWITH\_INNOBASE\_STORAGE\_ENGINE\=1 \\\-DWITH\_PARTITION\_STORAGE\_ENGINE\=1 \\\-DWITH\_BLACKHOLE\_STORAGE\_ENGINE\=1 \\\-DWITH\_MYISAM\_STORAGE\_ENGINE\=1 \\\-DWITH\_READLINE\=1 \\\-DENABLED\_LOCAL\_INFILE\=1 \\\-DWITH\_EXTRA\_CHARSETS\=1 \\\-DDEFAULT\_CHARSET\=utf8 \\\-DDEFAULT\_COLLATION\=utf8\_general\_ci \\\-DEXTRA\_CHARSETS\=all \\\-DWITH\_BIG\_TABLES\=1 \\\-DWITH\_DEBUG\=0makemake install | | --- | 1. PHP安装配置 | wget [http://museum.php.net/php5/php\-5\.3\.10\.tar.g](http://museum.php.net/php5/php-5.2.17.tar.bz2)z yum \-y install gd curl curl\-devel libjpeg libjpeg\-devel libpng libpng\-devel freetype freetype\-devel libxml2 libxml2\-devel cd php\-5\.3\.10./configure \-\-prefix\=/usr/local/php5 \-\-enable\-fpm \-\-enable\-debug \-\-with\-gd \-\-with\-jpeg\-dir \-\-with\-png\-dir \-\-with\-freetype\-dir \-\-enable\-mbstring \-\-with\-curl \-\-with\-mysql\=/usr/local/mysql55/ \-\-with\-mysqli\=/usr/local/mysql55/bin/mysql\_config \-\-with\-config\-file\-path\=/usr/local/php5/etcmakemake installcp php.ini\-development /usr/local/php5/etc/php.inicp /usr/local/php5/etc/php\-fpm.conf.default /usr/local/php5/etc/php\-fpm.conf/usr/local/php5/sbin/php\-fpm cp sapi/fpm/init.d.php\-fpm /etc/init.d/php\-fpm | | --- | 1. Nginx配置文件配置 | server { include port.conf; server\_name www.jfedu.net jfedu.net; location / { index index.html index.php; root /usr/local/nginx/html; } location \~ \\.php$ { root html; FastCGI\_pass 127\.0\.0\.1:9000; FastCGI\_index index.php; FastCGI\_param SCRIPT\_FILENAME html$FastCGI\_script\_name; include FastCGI\_params; } } | | --- | 1. 测试LNMP架构测试,创建index.php测试页面,如图14\-6所示: ![](/media/202411/20241125143346054240.png)图14\-6 LNMP企业实战测试页面 ## Nginx Rewrite规则详解一 Rewirte规则也称为规则重写,主要功能是实现浏览器访问HTTP URL的跳转,其正则表达式是基于Perl语言。通常而言,几乎所有的WEB服务器均可以支持URL重写。Rewrite URL规则重写的用途: * 对搜索引擎优化(Search Engine Optimization,SEO)友好,利于搜索引擎抓取网站页面; * 隐藏网站URL真实地址,浏览器显示更加美观; * 网站变更升级,可以基于Rewrite临时重定向到其他页面。 Nginx Rewrite规则使用中有三个概念需要理解,分别是:Rewrite结尾标识符、Rewrite规则常用表达式、Nginx Rewrite变量,如下为三个概念的详解: 1. Nginx Rewrite结尾标识符,用于Rewrite规则末尾,表示规则的执行属性。 | last :相当于Apache里的(L)标记,表示完成rewrite匹配;break:本条规则匹配完成后,终止匹配,不再匹配后面的规则。 redirect:返回302临时重定向,浏览器地址会显示跳转后的URL地址。 permanent:返回301永久重定向,浏览器地址栏会显示跳转后的URL地址。 其中last和break用来实现URL重写时,浏览器地址栏URL地址不变。 | | --- | 1. Nginx Rewrite规则常用表达式,主要用于匹配参数、字符串及过滤设置。 | . 匹配任何单字符;\[word] 匹配字符串:word;\[^word] 不匹配字符串:word;jfedu\|jfteach 可选择的字符串:jfedu\|jfteach;? 匹配0到1个字符;\* 匹配0到多个字符;\+ 匹配1到多个字符;^ 字符串开始标志;$ 字符串结束标志;\\n 转义符标志。 | | --- | 1. Nginx Rewrite变量,常用于匹配HTTP请求头信息、浏览器主机名、URL等。 | HTTP headers:HTTP\_USER\_AGENT, HTTP\_REFERER, HTTP\_COOKIE, HTTP\_HOST, HTTP\_ACCEPT;connection \& request: REMOTE\_ADDR, QUERY\_STRING;server internals: DOCUMENT\_ROOT, SERVER\_PORT, SERVER\_PROTOCOL;system stuff: TIME\_YEAR, TIME\_MON, TIME\_DAY。详解如下:HTTP\_USER\_AGENT 用户使用的代理,例如浏览器;HTTP\_REFERER 告知服务器,从哪个页面来访问的;HTTP\_COOKIE 客户端缓存,主要用于存储用户名和密码等信息;HTTP\_HOST 匹配服务器ServerName域名;HTTP\_ACCEPT 客户端的浏览器支持的MIME类型; REMOTE\_ADDR 客户端的IP地址QUERY\_STRING URL中访问的字符串;DOCUMENT\_ROOT 服务器发布目录;SERVER\_PORT 服务器端口;SERVER\_PROTOCOL 服务器端协议;TIME\_YEAR 年;TIME\_MON 月;TIME\_DAY 日; | | --- | 1. Nginx Rewrite以下配置均配置在nginx.conf或者vhosts.conf中,企业中常用的Nginx Rewrite案例如下: 2. 将jfedu.net跳转至www.jfedu.net。 | if ($host \= 'jfedu.net' ) { rewrite ^/(.\*)$ <http://www.jfedu.net/$1> permanent;} | | --- | 1. 访问www.jfedu.net跳转[www.test.com/new.index.html](http://www.test.com/new.index.html)。 | rewrite ^/$ http://www.test.com/index01\.html permanent; | | --- | 1. 访问/jfedu/test01/跳转至/newindex.html,浏览器地址不变。 | rewrite ^/jfedu/test01/$ /newindex.html last; | | --- | 1. 多域名跳转到www.jfedu.net。 | if ($host !\= ‘www.jfedu.net’ ) {rewrite ^/(.\*)$ <http://www.jfedu.net/$1> permanent;} | | --- | 1. 访问文件和目录不存在跳转至index.php。 | if ( !\-e $request\_filename ){rewrite ^/(.\*)$ /index.php last;} | | --- | 1. 目录对换 /xxxx/123456 \=\=\=\=\> /xxxx?id\=123456。 | rewrite ^/(.\+)/(\\d\+) /$1?id\=$2 last; | | --- | 1. 判断浏览器User Agent跳转。 | if( $http\_user\_agent \~ MSIE){rewrite ^(.\*)$ /ie/$1 break;} | | --- | 1. 禁止访问以.sh,.flv,.mp3为文件后缀名的文件。 | location \~ .\*\\.(sh\|flv\|mp3\)${ return 403;} | | --- | 1. 将移动用户访问跳转至移动端。 | if ( $http\_user\_agent \~\* "(Android)\|(iPhone)\|(Mobile)\|(WAP)\|(UCWEB)" ){rewrite ^/$ <http://m.jfedu.net/> permanent;} | | --- | 1. 匹配URL访问字符串跳转。 | if ($args \~\* tid\=13\){ return 404;} | | --- | 1. 访问/10690/jfedu/123跳转至/index.php?tid/10690/items\=123,\[0\-9]表示任意一个数字,\+表示多个,(.\+)表示任何多个字符。 | rewrite ^/(\[0\-9]\+)/jfedu/(.\+)$ /index.php?tid/$1/items\=$2 last; | | --- | ## Nginx日志切割案例 Nginx WEB服务器每天会产生大量的访问日志,而且不会自动地进行切割,如果持续天数访问,将会导致该access.log日志文件容量非常大,不便于SA查看相关的网站异常日志。 可以基于Shell 脚本结合Crontab计划任务对Nginx日志进行自动、快速的切割,其切割的方法使用mv命令即可,如图14\-8所示。 | \#!/bin/bash\#auto mv nginx log shell\#by author jfedu.netS\_LOG\=/usr/local/nginx/logs/access.logD\_LOG\=/data/backup/\`date \+%Y%m%d\`echo \-e "\\033\[32mPlease wait start cut shell scripts...\\033\[1m"sleep 2if \[ ! \-d $D\_LOG ];then mkdir \-p $D\_LOGfimv $S\_LOG $D\_LOGkill \-USR1 \`cat /usr/local/nginx/logs/nginx.pid\`echo "\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-"echo "The Nginx log Cutting Successfully!"echo "You can access backup nginx log $D\_LOG/access.log files." | | --- | ![](/media/202411/20241125143346066980.png) 图14\-8 Nginx日志切割 将如上脚本内容写入auto\_nginx\_log.sh文件,crontab /var/spool/cron/root文件中添加如下代码,每天凌晨自动切割日志: | 0 0 \* \* \* /bin/sh /data/sh/auto\_nginx\_log.sh \>\>/tmp/nginx\_cut.log 2\>\&1 | | --- | ## Nginx防盗链配置案例配置 防盗链的含义是网站内容本身不在自己公司的服务器上,而通过技术手段,直接在调用其他公司的服务器网站数据,而向最终用户提供此内容。一些小网站盗链高访问量网站的音乐、图片、软件的链接,然后放置在自己的网站中,通过这种方法盗取高访问量网站的空间和流量。 网站每天访问量很大,而且占用了很多不必要的带宽,浪费资源,所以必须采取一些限制措施。防盗链其实就是采用服务器端编程技术,通过URL过滤、主机名等实现的防止盗链的软件。 例如<http://www.jfedu.net/linux/>页面,如果没有配置防盗链,别人就能轻而易举的在其的网站上引用该页面。Nginx防盗链配置代码如下: | server { listen 80; server\_name jfedu.net www.jfedu.net; location / { root html/b; index index.html index.htm; } location \~\* \\.(gif\|jpg\|png\|swf\|flv)$ { valid\_referers none blocked jfedu.net \*.jfedu.net; root html/b; if ($invalid\_referer) { \#rewrite ^/ http://www.jfedu.net/403\.html; return 403; } }} | | --- | Nginx防盗链参数详解: | valid\_referers表示可用的referers设置none 表示没有referers,直接通过浏览器或者其他工具访问。blocked表示有referers,但是被代理服务器或者防火墙隐藏;jfedu.net 表示通过jfedu.net访问的referers;\*.jfedu.net 表示通过\*.jfedu.net访问的referers,\*表示任意host主机。 | | --- | 除了以上方法,按照如下方法设置也可以实现防盗链: | location \~\* \\.(gif\|jpg\|png\|swf\|flv)$if ($host !\=’\*.jfedu.net’) {return 403;} | | --- | 防盗链测试,找另外一台测试服务器,基于Nginx发布如下test.html页面,代码如下,去调用www.jfedu.net官网的test.png图片,由于[www.jfedu.net](http://www.jfedu.net)官网设置了防盗链,所以无法访问该图片。 | \<html\>\<h1\>TEST Nginx PNG\</h1\>\<img src\="http://www.jfedu.net/test.png"\>\</html\> | | --- | 默认没有配置Nginx防盗链,网站正常调用[www.jfedu.net的logo](http://www.jfedu.net的logo)图片,访问如图14\-9所示: ![](/media/202411/20241125143346074650.png) 图14\-9 Nginx无防盗链正常调用图片 配置Nginx防盗链,网站无法正常调用[www.jfedu.net的logo](http://www.jfedu.net的logo)图片,访问如图14\-10所示: ![](/media/202411/20241125143346080446.png) 图14\-10 Nginx防盗链403禁止访问 # 大数据备份企业实战 随着互联网不断的发展,企业对运维人员的能力要求也越来越高,尤其是要求运维人员能处理各种故障、专研自动化运维技术、云计算机、虚拟化等,满足公司业务的快速发展。 本章向读者介绍数据库备份方法、数量量2T及以上级别数据库备份方案、xtrabackup企业工具案例演示、数据库备份及恢复实战等。 ## 企业级数据库备份实战 在日常的运维工作中,数据是公司非常重要的资源,尤其是数据库的相关信息,如果数据丢了,少则损失几千元,高则损失上千万。所以在运维工作中要及时注意网站数据的备份,尤其要及时对数据库进行备份。 企业中如果数据量上T级别,维护和管理是非常复杂的,尤其是对数据库进行备份操作。 ## 数据库备份方法及策略 企业中MySQL数据库备份最常用的方法如下: * 直接cp备份 * Sqlhotcopy * 主从同步复制 * Mysqldump备份 * Xtrabackup备份 Mysqldump和Xtrabackup均可以备份MYSQL数据,如下为Mysqldump工具使用方法: 通常小于100G的MYSQL数据库可以使用默认Mysqldump备份工具进行备份,如果超过100G的大数据,由于Mysqldump备份方式是采用的逻辑备份,最大的缺陷是备份和恢复速度较慢。 基于Mysqldump备份耗时会非常长,而且备份期间会锁表,锁表直接导致数据库只能访问Select,不能执行Insert、Update等操作,进而导致部分WEB应用无法写入新数据。 如果是Myisam引擎表,当然也可以执行参数\-\-lock\-tables\=false禁用锁表,但是有可能造成数据信息不一致。 如果是支持事务的表,例如InnoDB和BDB,\-\-single\-transaction参数是一个更好的选择,因为它不锁定表。 | mysqldump \-uroot \-p123456 \-\-all\-databases \-\-opt \-\-single\-transaction \> 2022all.sql | | --- | 其中\-\-opt快捷选项,等同于添加\-\-add\-drop\-tables \-\-add\-locking \-\-create\-option \-\-disable\-keys \-\-extended\-insert \-\-lock\-tables \-\-quick \-\-set\-charset选项。 本选项能让 Mysqldump 很快的导出数据,并且导出的数据能很快导回。该选项默认开启,但可以用\-\-skip\-opt 禁用。 如果运行 Mysqldump没有指定\-\-quick 或 \-\-opt 选项,则会将整个结果集放在内存中。如果导出大数据库的话可能会导致内存溢出而异常退出。 ## Xtrabackup企业实战 Mysql冷备、Mysqldump、Mysql热拷贝均不能实现对数据库进行增量备份,在实际环境中增量备份非常的实用,如果数据量小于100G,存储空间足够,可以每天进行完整备份,如果每天产生的数据量大,需要定制数据备份策略例如:每周日使用完整备份,周一到周六使用增量备份,或者每周六完整备份,周日到周五使用增量备份。 Percona\-xtrabackup是为实现增量备份而生一款主流备份工具,Xtrabackup有两个主要的工具,分别为:xtrabackup、innobackupex。 [Percona XtraBackup](https://www.percona.com/software/mysql-database/percona-xtrabackup" \t "_blank" \o "Percona XtraBackup 官网)是 Percona 公司开发的一个用于 MySQL 数据库物理热备的备份工具,支持 MySQl、Percona Server及MariaDB,开源免费,是目前互联网数据库备份最主流的工具之一。 Xtrabackup只能备份InnoDB和XtraDB两种数据引擎的表,而不能备份MyISAM数据表,Innobackupex\-1\.5\.1则封装了Xtrabackup,是一个封装好的脚本,使用该脚本能同时备份处理innodb和Myisam,但在处理Myisam时需要加一个读锁。 XtraBackup备份原理,Innobackupex在后台线程不断追踪InnoDB的日志文件,然后复制InnoDB的数据文件。数据文件复制完成之后,日志的复制线程也会结束。这样就得到了不在同一时间点的数据副本和开始备份以后的事务日志。完成上面的步骤之后,就可以使用InnoDB崩溃恢复代码执行事务日志(Redo log),以达到数据的一致性。其备份优点如下: * 备份速度快,物理备份更加可靠; * 备份过程不会打断正在执行的事务,无需锁表; * 能够基于压缩等功能节约磁盘空间和流量; * 自动备份校验; * 还原速度快; * 可以流传将备份传输到另外一台机器上; * 节约磁盘空间和网络带宽。 Innobackupex工具的备份过程原理,如图16\-1所示: ![QQ图片20170527083149](/media/202411/20241125143346087206.png) 图16\-1 Innobackupex备份过程 Innobackupex备份过程中首先启动Xtrabackup\_log后台检测的进程,实时检测Mysql redo的变化,一旦发现Redo有新的日志写入,立刻将日志写入到日志文件Xtrabackup\_log中,并复制Innodb的数据文件和系统表空间文件idbdata1到备份目录。 Innode引擎表备份完之后,执行Flush table with read lock操作进行MyIsam表备份。拷贝.frm .myd .myi文件,并且在这一时刻获得binary log的位置,将表进行解锁unlock tables,停止Xtrabackup\_log进程,完整整个数据库的备份。 ## Percona\-xtrabackup备份实战 基于Percona\-xtrabackup备份,需要如下几个步骤: 1. 官网下载Percona\-Xtrabackup | Percona官方wiki使用帮助:[http://www.percona.com/docs/wiki/percona\-xtrabackup:start](http://www.percona.com/docs/wiki/percona-xtrabackup:start)wget [http://www.percona.com/redir/downloads/XtraBackup/XtraBackup\-2\.0\.0/binary/Linux/x86\_64/percona\-xtrabackup\-2\.0\.0\.tar.gz](http://www.percona.com/redir/downloads/XtraBackup/XtraBackup-2.0.0/binary/Linux/x86_64/percona-xtrabackup-2.0.0.tar.gz) | | --- | 1. Percona\-xtrabackup软件安装方法,cp innobackupex、xtrabackup、xtrabackup\_51 xtrabackup\_55工具到/usr/bin目录下,代码如下: | tar zxvf percona\-xtrabackup\-2\.0\.0\.tar.gzcp percona\-xtrabackup\-2\.0\.0/bin/innobackupex /usr/bin/innobackupexcp percona\-xtrabackup\-2\.0\.0/bin/xtrabackup /usr/bin/xtrabackupcp percona\-xtrabackup\-2\.0\.0/bin/xtrabackup\_51 /usr/bin/xtrabackup\_51cp percona\-xtrabackup\-2\.0\.0/bin/xtrabackup\_55 /usr/bin/xtrabackup\_55 | | --- | Percona\-xtrabackup 1. MYSQL数据库全备份,如图16\-2(a)、16\-2(b)所示: | innobackupex \-\-user\=root \-\-password\=123456 /data/backup/mysql/ | | --- | ![](/media/202411/20241125143346093390.png) 图16\-2(a) Innobackupex完整备份 ![](/media/202411/20241125143346098456.png) 图16\-2(b) Innobackupex完整备份 1. Innobackupex数据库恢复,恢复前先保证数据一致性,执行如下命令,如图16\-3所示: | innobackupex \-\-defaults\-file\=/etc/my.cnf \-\-user\=root \-\-password\=123456 \-\-apply\-log /data/backup/mysql/2014\-12\-20\_00\-10\-24 | | --- | ![](/media/202411/20241125143346103912.png) 图16\-3 Innobackupex apply\-log恢复 通常数据库备份完成后,数据尚不能直接用于恢复操作,因为备份的数据时是一个过程,在备份过程中,有任务会写入数据,可能会包含尚未提交的事务或已经提交但尚未同步至数据文件中的事务。 因此此时数据文件仍处理不一致状态,基于\-\-apply\-log可以通过回滚未提交的事务及同步已经提交的事务至数据文件使数据文件处于一致性状态,方可进行恢复数据。 Apply\-log过程可以在任何机器上运行,没有强制在线上或者备份库上运行,可以把备份复制在闲置的服务器上去运行,以此来降低备份库的压力,必须保证backup和apply\-log所使用的mysqlbackup的版本要一致。 1. 删除原数据目录/var/lib/mysql数据,使用参数\-\-copy\-back恢复完整数据,授权mysql用户给所有的数据库文件,如图16\-4所示: | rm \-rf /var/lib/mysql/\*innobackupex \-\-defaults\-file\=/etc/my.cnf \-\-user\=mysql \-\-password\=123456 \-\-copy\-back /data/backup/mysql/2014\-12\-20\_00\-10\-24/ chown –R mysql:mysql /var/lib/mysql/ | | --- | ![](/media/202411/20241125143346109197.png) 图16\-4 Innobackupex 数据恢复 查看数据库恢复信息,数据完全恢复,如图16\-5所示: ![](/media/202411/20241125143346114475.png) 图16\-5 Innobackupex 数据恢复 ## Innobackupex增量备份 增量备份仅能应用于InnoDB或XtraDB表,对于MyISAM表而言,执行增量备份时其实进行的是完全备份。 1. 增量备份之前必须执行完全备份,如图16\-6所示: | innobackupex \-\-user\=root \-\-password\=123456 \-\-databases\=wugk01 /data/backup/mysql/ | | --- | ![](/media/202411/20241125143346119748.png) 图16\-6 Innobackupex 完整备份 1. 执行第一次增量备份: | innobackupex \-\-defaults\-file\=/etc/my.cnf \-\-user\=root \-\-password\=123456 \-\-databases\=wugk01 \-\-incremental /data/backup/mysql/ \-\-incremental\-basedir\=/data/backup/mysql/2014\-12\-20\_13\-01\-43/ | | --- | 增量备份完后,会在/data/backup/mysql/目录下生成新的备份目录,如图16\-7所示: ![](/media/202411/20241125143346125035.png) 图16\-7 Innobackupex 增量备份 1. 数据库插入新数据,如图16\-8所示: ![](/media/202411/20241125143346130213.png) 图16\-8 数据库insert into新数据 1. 执行第二次增量备份,备份命令如下,如图16\-9(a)、16\-9(b): | innobackupex \-\-defaults\-file\=/etc/my.cnf \-\-user\=root \-\-password\=123456 \-\-databases\=wugk01 \-\-incremental /data/backup/mysql/ \-\-incremental\-basedir\=/data/backup/mysql/2014\-12\-20\_13\-07\-31/ | | --- | ![](/media/202411/20241125143346136361.png) 图16\-9(a)数据库增量备份 ![](/media/202411/20241125143346145228.png) 图16\-9(b)数据库增量备份 ## Mysql增量备份恢复 删除原数据库中表及数据记录信息,如图16\-10所示: ![](/media/202411/20241125143346150760.png) 图16\-10 删除数据库表信息 MYSQL增量备份数据恢复方法如下步骤: 1. 基于Apply\-log确保数据一致性: | innobackupex \-\-defaults\-file\=/etc/my.cnf \-\-user\=root \-\-password\=123456 \-\-apply\-log \-\-redo\-only /data/backup/mysql/2014\-12\-20\_13\-01\-43/ | | --- | 1. 执行第一次增量数据恢复: | innobackupex \-\-defaults\-file\=/etc/my.cnf \-\-user\=root \-\-password\=123456 \-\-apply\-log \-\-redo\-only /data/backup/mysql/2014\-12\-20\_13\-01\-43/ \-\-incremental\-dir\=/data/backup/mysql/2014\-12\-20\_13\-07\-31/ | | --- | 1. 执行第二次增量数据恢复: | innobackupex \-\-defaults\-file\=/etc/my.cnf \-\-user\=root \-\-password\=123456 \-\-apply\-log \-\-redo\-only /data/backup/mysql/2014\-12\-20\_13\-01\-43/ \-\-incremental\-dir\=/data/backup/mysql/2014\-12\-20\_13\-11\-20/ | | --- | 1. 执行完整数据恢复: | innobackupex \-\-defaults\-file\=/etc/my.cnf \-\-user\=root \-\-password\=123456 \-\-copy\-back /data/backup/mysql/2014\-12\-20\_13\-01\-43/ | | --- | 1. 测试数据库已完全恢复,如图16\-11所示: ![](/media/202411/20241125143346156758.png) 图16\-11 数据库表信息完整恢复 # Shell企业编程基础 说到Shell编程,很多从事Linux运维工作的朋友都不陌生,都对Shell有基本的了解,读者可能刚开始接触Shell的时候,有各种想法,感觉编程非常困难,SHELL编程是所有编程语言中最容易上手,最容易学习的编程脚本语言。 本章向读者介绍Shell编程入门、Shell编程变量、If、While、For、Case、Select基本语句案例演练及Shell编程四剑客Find、Grep、Awk、Sed深度剖析等。 ## SHELL编程入门简介 曾经有人说过,学习Linux不知道Shell编程,那就是不懂Linux,现在细细品味确实是这样。Shell是[操作系统](http://baike.baidu.com/view/880.htm" \t "_blank)的最外层,Shell可以合并编程语言以控制进程和文件,以及启动和控制其它程序。 Shell 通过提示您输入,向[操作系统](http://baike.baidu.com/view/880.htm" \t "_blank)解释该输入,然后处理来自操作系统的任何结果输出,简单来说Shell就是一个用户跟操作系统之间的一个命令解释器。 Shell是用户与Linux操作系统之间沟通的桥梁,用户可以输入命令执行,又可以利用 Shell脚本编程去运行,如图17\-1所示: ![](/media/202411/20241125143346162706.png)图17\-1 Shell、用户及Kernel位置关系 ![](/media/202411/20241125143346168025.png) Linux Shell种类非常多,常见的SHELL如下: * Bourne Shell(/usr/bin/sh或/bin/sh) * **Bourne Again Shell(/bin/bash)** * C Shell(/usr/bin/csh) * K Shell(/usr/bin/ksh) * Shell for Root(/sbin/sh) 不同的Shell语言的语法有所不同,一般不能交换使用,最常用的shell是Bash,也就是Bourne Again Shell。Bash由于易用和免费,在日常工作中被广泛使用,也是大多数Linux操作系统默认的Shell环境。 Shell、Shell编程、Shell脚本、Shell命令之间都有什么区别呢?简单来说Shell是一个整体的概念,Shell编程与Shell脚本统称为Shell编程,Shell命令是Shell编程底层具体的语句和实现方法。 ## SHELL脚本及Hello World 要熟练掌握Shell编程语言,需要大量的练习,初学者可以用Shell打印“Hello World”字符,寓意着开始新的启程! Shell脚本编程需要如下几个事项: * Shell脚本名称命名一般为英文、大写、小写; * 不能使用特殊符号、空格来命名; * Shell脚本后缀以.sh结尾; * 不建议Shell命名为纯数字,一般以脚本功能命名。 * Shell脚本内容首行需以\#!/bin/bash开头; * Shell脚本中变量名称尽量使用大写字母,字母间不能使用“\-”,可以使用“\_”; * Shell脚本变量名称不能以数字、特殊符号开头。 如下为第一个Shell编程脚本,脚本名称为:first\_shell.sh,代码内容如下: | \#!/bin/bash\#This is my First shell\#By author jfedu.net 2022echo “Hello World ” | | --- | First\_shell.sh脚本内容详解如下: | \#!/bin/bash 固定格式,定义该脚本所使用的Shell类型;\#This is my First shell \#号表示注释,没有任何的意义,SHELL不会解析它;\#By author jfedu.net 2022 表示脚本创建人,\#号表示注解;echo “Hello World !” Shell脚本主命令,执行该脚本呈现的内容。 | | --- | Shell脚本编写完毕,如果运行该脚本,运行用户需要有执行权限,可以使用chmod o\+x first\_shell.sh赋予可执行权限。然后./first\_shell.sh执行即可,还可以直接使用命令执行: /bin/sh first\_shell.sh直接运行脚本,不需要执行权限,最终脚本执行显示效果一样。 初学者学习Shell编程,可以将在Shell终端运行的各种命令依次写入到脚本内容中,可以把Shell脚本当成是Shell命令的堆积。 ## Shell编程之变量详解 Shell是非类型的解释型语言,不像C\+\+、JAVA语言编程时需要事先声明变量,Shell给一个变量赋值,实际上就是定义了变量,在Linux支持的所有shell中,都可以用赋值符号(\=)为变量赋值,Shell变量为弱类型,定义变量不需要声明类型,但在使用时需要明确变量的类型,可以使用Declare指定类型,Declare常见参数有: | \+/\- "\-"可用来指定变量的属性,"\+"为取消变量所设的属性;\-f 仅显示函数;r 将变量设置为只读;x 指定的变量会成为环境变量,可供shell以外的程序来使用;i 指定类型为数值,字符串或运算式。 | | --- | Shell编程中变量分为三种,分别是系统变量、环境变量和用户变量,Shell变量名在定义时,首个字符必须为字母(a\-z,A\-Z),不能以数字开头,中间不能有空格,可以使用下划线(\_),不能使用(\-),也不能使用标点符号等。 例如定义变量A\=jfedu.net,定义这样一个变量,A为变量名,jfedu.net是变量的值,变量名有格式规范,变量的值可以随意指定。变量定义完成,如需要引用变量,可以使用$A。 如下脚本var.sh脚本内容如下: | \#!/bin/bash\#By author jfedu.net 2022A\=123echo “Printf variables is $A.” | | --- | 执行该Shell脚本,结果将会显示:Printf variables is jfedu.net。 ## Shell编程之系统变量 Shell常见的变量之一系统变量,主要是用于对参数判断和命令返回值判断时使用,系统变量详解如下: | $0 当前脚本的名称;$n 当前脚本的第n个参数,n\=1,2,…9;$\* 当前脚本的所有参数(不包括程序本身);$\# 当前脚本的参数个数(不包括程序本身);$? 命令或程序执行完后的状态,返回0表示执行成功;$$ 程序本身的PID号。 | | --- | ## Shell编程之环境变量 Shell常见的变量之二环境变量,主要是在程序运行时需要设置,环境变量详解如下: | PATH 命令所示路径,以冒号为分割;HOME 打印用户家目录;SHELL 显示当前Shell类型;USER 打印当前用户名;ID 打印当前用户id信息;PWD 显示当前所在路径;TERM 打印当前终端类型;HOSTNAME 显示当前主机名。 | | --- | ## Shell编程之用户变量 Shell常见的变量之三用户变量,用户变量又称为局部变量,主要用在Shell脚本内部或者临时局部使用,系统变量详解如下: | A\=jfedu.net 自定义变量A;N\_SOFT\=nginx\-1\.12\.0\.tar.gz 自定义变量N\_SOFT;BACK\_DIR\=/data/backup/ 自定义变量BACK\_DIR;IP1\=192\.168\.1\.11 自定义变量IP1;IP2\=192\.168\.1\.12 自定义变量IP2。 | | --- | 创建Echo打印菜单Shell脚本,脚本代码如下: | \#!/bin/bash\#auto install httpd \#By author jfedu.net 2022echo \-e '\\033\[32m\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\\033\[0m'FILE\=httpd\-2\.2\.31\.tar.bz2URL\=http://mirrors.cnnic.cn/apache/httpd/PREFIX\=/usr/local/apache2/echo \-e "\\033\[36mPlease Select Install Menu:\\033\[0m"echoecho "1\)官方下载Httpd文件包."echo "2\)解压apache源码包."echo "3\)编译安装Httpd服务器."echo "4\)启动HTTPD服务器."echo \-e '\\033\[32m\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\\033\[0m'sleep 20 | | --- | 运行脚本,执行结果如图17\-2所示: ![](/media/202411/20241125143346180261.png) 图17\-2 Echo打印菜单脚本 ## If条件语句实战 Linux Shell编程中,if、for、while、case等条件流程控制语句用的非常多,熟练掌握以上流程控制语句及语法的实验,对编写Shel脚本有非常大的益处。 If条件判断语句,通常以if开头,fi结尾。也可加入else或者elif进行多条件的判断,if表达式如下: | if (表达式) 语句1else语句2fi | | --- | If语句Shell脚本编程案例如下: 1. 比较两个整数大小。 | \#!/bin/bash\#By author jfedu.net 2022NUM\=100if (( $NUM \> 4 )) ;then echo “The Num $NUM more than 4\.”elseecho “The Num $NUM less than 4\.”fi | | --- | 1. 判断系统目录是否存在。 | \#!/bin/bash\#judge DIR or Files\#By author jfedu.net 2022if \[ ! \-d /data/20140515 \-a ! \-d /tmp/2022/ ];then mkdir \-p /data/20140515fi | | --- | If常见判断逻辑运算符详解: | \-f 判断文件是否存在 eg: if \[ \-f filename ];\-d 判断目录是否存在 eg: if \[ \-d dir ];\-eq 等于,应用于整型比较 equal;\-ne 不等于,应用于整型比较 not equal;\-lt 小于,应用于整型比较 letter;\-gt 大于,应用于整型比较 greater;\-le 小于或等于,应用于整型比较;\-ge 大于或等于,应用于整型比较;\-a 双方都成立(and) 逻辑表达式 –a 逻辑表达式;\-o 单方成立(or) 逻辑表达式 –o 逻辑表达式;\-z 空字符串;\|\| 单方成立;\&\& 双方都成立表达式。 | | --- | 1. if多个条件测试分数判断。 | \#!/bin/bash\#By author jfedu.net 2022scores\=$1if \[\[ $scores \-eq 100 ]]; then echo "very good!";elif \[\[ $scores \-gt 85 ]]; then echo "good!";elif \[\[ $scores \-gt 60 ]]; then echo "pass!";elif \[\[ $scores \-lt 60 ]]; then echo "no pass!"fi | | --- | ## MySQL数据库备份脚本 MySQL数据库备份是运维工程师的工作之一,如下为自动备份Mysql数据库脚本。 | \#!/bin/bash \#auto backup mysql\#By author jfedu.net 2022\#Define PATH定义变量BAK\_DIR\=/data/backup/mysql/\`date \+%Y\-%m\-%d\`MYSQLDB\=webappMYSQLPW\=backupMYSQLUSR\=backup\#must use root user run scripts 必须使用root用户运行,$UID为系统变量if \[ $UID \-ne 0 ];then echo This script must use the root user ! ! ! sleep 2 exit 0fi\#Define DIR and mkdir DIR 判断目录是否存在,不存在则新建if \[ ! \-d $BAKDIR ];then mkdir \-p $BAKDIRfi\#Use mysqldump backup Databases/usr/bin/mysqldump \-u$MYSQLUSR \-p$MYSQLPW \-d $MYSQLDB \>$BAKDIR/webapp\_db.sqlecho "The mysql backup successfully " | | --- | ## LAMP一键自动化安装脚本 通过前面章节对if语句和变量的学习,现基于所学知识,编写一键源码安装LAMP脚本, 编写脚本可以养成先分解脚本的各个功能的习惯,有利于快速写出脚本,写出更高效的脚本。 一键源码安装LAMP脚本,可以拆分为如下功能: 1. LAMP打印菜单: * 安装apache WEB服务器; * 安装Mysql DB服务器; * 安装PHP 服务器; * 整合LAMP架构 * 启动LAMP服务; 1. Apache服务器安装部署: Apache官网下载httpd\-2\.2\.31\.tar.gz版本,解压,进入安装目录,configure、make 、make install。 1. Mysql服务器的安装: Mysql官网下载mysql\-5\.5\.20\.tar.gz版本,解压,进入安装目录,configure、make 、make install。 1. PHP服务器安装: PHP官网下载php\-5\.3\.8\.tar.gz版本,解压,进入安装目录,configure、make 、make install。 1. LAMP整合及服务启动: | vi /usr/local/apache2/htdocs/index.php\<?phpphpinfo();?\>/usr/local/apache2/bin/apachectl restartservice mysqld restart | | --- | 一键源码安装LAMP脚本,auto\_install\_lamp.sh内容如下: | \#!/bin/bash\#auto install LAMP \#By author jfedu.net 2022\#Httpd define path variableH\_FILES\=httpd\-2\.2\.31\.tar.bz2H\_FILES\_DIR\=httpd\-2\.2\.31H\_URL\=http://mirrors.cnnic.cn/apache/httpd/httpd\-2\.2\.31\.tar.bz2H\_PREFIX\=/usr/local/apache2/\#MySQL define path variableM\_FILES\=mysql\-5\.5\.20\.tar.gzM\_FILES\_DIR\=mysql\-5\.5\.20M\_URL\=http://down1\.chinaunix.net/distfiles/ mysql\-5\.5\.20\.tar.gzM\_PREFIX\=/usr/local/mysql/\#PHP define path variableP\_FILES\=php\-5\.3\.28\.tar.bz2P\_FILES\_DIR\=php\-5\.3\.28P\_URL\=http://mirrors.sohu.com/php/P\_PREFIX\=/usr/local/php5/echo \-e '\\033\[32m\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\\033\[0m'echoif \[ \-z "$1" ];then echo \-e "\\033\[36mPlease Select Install Menu follow:\\033\[0m" echo \-e "\\033\[32m1\)编译安装Apache服务器\\033\[1m" echo "2\)编译安装MySQL服务器" echo "3\)编译安装PHP服务器" echo "4\)配置index.php并启动LAMP服务" echo \-e "\\033\[31mUsage: { /bin/sh $0 1\|2\|3\|4\|help}\\033\[0m" exitfiif \[\[ "$1" \-eq "help" ]];then echo \-e "\\033\[36mPlease Select Install Menu follow:\\033\[0m" echo \-e "\\033\[32m1\)编译安装Apache服务器\\033\[1m" echo "2\)编译安装MySQL服务器" echo "3\)编译安装PHP服务器" echo "4\)配置index.php并启动LAMP服务" echo \-e "\\033\[31mUsage: { /bin/sh $0 1\|2\|3\|4\|help}\\033\[0m" exitfi\#Install httpd web server if \[\[ "$1" \-eq "1" ]];then wget \-c $H\_URL/$H\_FILES \&\& tar \-jxvf $H\_FILES \&\& cd $H\_FILES\_DIR \&\&./configure \-\-prefix\=$H\_PREFIX if \[ $? \-lt 0 ];then make \&\& make install fifi\#Install Mysql DB server if \[\[ "$1" \-eq "2" ]];thenwget \-c $M\_URL/$M\_FILES \&\& tar \-xzvf $M\_FILES \&\& cd $M\_FILES\_DIR \&\&yum install cmake \-y ;cmake . \-DCMAKE\_INSTALL\_PREFIX\=$M\_PREFIX \\\-DMYSQL\_UNIX\_ADDR\=/tmp/mysql.sock \\\-DMYSQL\_DATADIR\=/data/mysql \\\-DSYSCONFDIR\=/etc \\\-DMYSQL\_USER\=mysql \\\-DMYSQL\_TCP\_PORT\=3306 \\\-DWITH\_XTRADB\_STORAGE\_ENGINE\=1 \\\-DWITH\_INNOBASE\_STORAGE\_ENGINE\=1 \\\-DWITH\_PARTITION\_STORAGE\_ENGINE\=1 \\\-DWITH\_BLACKHOLE\_STORAGE\_ENGINE\=1 \\\-DWITH\_MYISAM\_STORAGE\_ENGINE\=1 \\\-DWITH\_READLINE\=1 \\\-DENABLED\_LOCAL\_INFILE\=1 \\\-DWITH\_EXTRA\_CHARSETS\=1 \\\-DDEFAULT\_CHARSET\=utf8 \\\-DDEFAULT\_COLLATION\=utf8\_general\_ci \\\-DEXTRA\_CHARSETS\=all \\\-DWITH\_BIG\_TABLES\=1 \\\-DWITH\_DEBUG\=0make \&\& make install/bin/cp support\-files/my\-small.cnf /etc/my.cnf/bin/cp support\-files/mysql.server /etc/init.d/mysqldchmod \+x /etc/init.d/mysqldchkconfig \-\-add mysqldchkconfig mysqld onif \[ $? \-eq 0 ];then make \&\& make install echo \-e "\\n\\033\[32m\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\\033\[0m" echo \-e "\\033\[32mThe $M\_FILES\_DIR Server Install Success !\\033\[0m" else echo \-e "\\033\[32mThe $M\_FILES\_DIR Make or Make install ERROR,Please Check......" exit 0 fifi\#Install PHP server if \[\[ "$1" \-eq "3" ]];then wget \-c $P\_URL/$P\_FILES \&\& tar \-jxvf $P\_FILES \&\& cd $P\_FILES\_DIR \&\&./configure \-\-prefix\=$P\_PREFIX \-\-with\-config\-file\-path\=$P\_PREFIX/etc \-\-with\-mysql\=$M\_PREFIX \-\-with\-apxs2\=$H\_PREFIX/bin/apxs if \[ $? \-eq 0 ];then make ZEND\_EXTRA\_LIBS\='\-liconv' \&\& make install echo \-e "\\n\\033\[32m\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\\033\[0m" echo \-e "\\033\[32mThe $P\_FILES\_DIR Server Install Success !\\033\[0m" else echo \-e "\\033\[32mThe $P\_FILES\_DIR Make or Make install ERROR,Please Check......" exit 0 fifiif \[\[ "$1" \-eq "4" ]];then sed \-i '/DirectoryIndex/s/index.html/index.php index.html/g' $H\_PREFIX/conf/httpd.conf $H\_PREFIX/bin/apachectl restart echo "AddType application/x\-httpd\-php .php" \>\>$H\_PREFIX/conf/httpd.conf IP\=\`ifconfig eth1\|grep "Bcast"\|awk '{print $2}'\|cut \-d: \-f2\` echo "You can access http://$IP/"cat \>$H\_PREFIX/htdocs/index.php \<\<EOF\<?phpphpinfo();?\>EOFfi | | --- | ## For循环语句实战 for循环语句主要用于对某个数据域进行循环读取、对文件进行遍历,通常用于需要循环某个文件或者列表。其语法格式以for…do开头,done结尾。语法格式如下: | For var in (表达式)do 语句1done | | --- | For循环语句Shell脚本编程案例如下: 1. 循环打印BAT企业官网: | \#!/bin/bash\#By author jfedu.net 2022for website in www.baidu.com www.taobao.com www.qq.comdo echo $websitedone | | --- | 1. 循环打印1至100数字,seq表示列出数据范围: | \#!/bin/bash\#By author jfedu.net 2022for i in \`seq 1 100\`do echo “NUM is $i”done | | --- | 1. For循环求1\-100的总和: | \#!/bin/bash\#By author jfedu.net 2022\#auto sum 1 100j\=0for ((i\=1;i\<\=100;i\+\+))do j\=\`expr $i \+ $j\`doneecho $j | | --- | 1. 对系统日志文件进行分组打包: | \#!/bin/bash\#By author jfedu.net 2022for i in \`find /var/log \-name “\*.log”\`do tar \-czf 2022\_log$i.tgz $idone | | --- | 1. For循环批量远程主机文件传输: | \#!/bin/bash\#auto scp files for client\#By author jfedu.net 2022for i in \`seq 100 200\`doscp \-r /tmp/jfedu.txt root@192\.168\.1\.$i:/data/webapps/wwwdone | | --- | 1. For循环批量远程主机执行命令: | \#!/bin/bash\#auto scp files for client\#By author jfedu.net 2022for i in \`seq 100 200\`do ssh \-l root 192\.168\.1\.$i ‘ls /tmp’done | | --- | 1. For循环打印10秒等待提示: | for ((j\=0;j\<\=10;j\+\+))do echo \-ne "\\033\[32m\-\\033\[0m" sleep 1 doneecho | | --- | ## Shell编程函数实战 Shell允许将一组命令集或语句形成一个可用块,这些块称为Shell函数,Shell函数的用于在于只需定义一次,后期随时使用即可,无需在Shell脚本中添加重复的语句块,其语法格式以function name(){开头,以}结尾。 Shell编程函数默认不能将参数传入()内部,Shell函数参数传递在调用函数名称传递,例如name args1 args2。 | function name (){ command1command2 ........}name args1 args2 | | --- | 1. 创建Apache软件安装函数,给函数Apache\_install传递参数1: | \#!/bin/bash\#auto install LAMP \#By author jfedu.net 2022\#Httpd define path variableH\_FILES\=httpd\-2\.2\.31\.tar.bz2H\_FILES\_DIR\=httpd\-2\.2\.31H\_URL\=http://mirrors.cnnic.cn/apache/httpd/H\_PREFIX\=/usr/local/apache2/function Apache\_install(){\#Install httpd web server if \[\[ "$1" \-eq "1" ]];then wget \-c $H\_URL/$H\_FILES \&\& tar \-jxvf $H\_FILES \&\& cd $H\_FILES\_DIR \&\&./configure \-\-prefix\=$H\_PREFIX if \[ $? \-eq 0 ];then make \&\& make install echo \-e "\\n\\033\[32m\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\\033\[0m" echo \-e "\\033\[32mThe $H\_FILES\_DIR Server Install Success !\\033\[0m" else echo \-e "\\033\[32mThe $H\_FILES\_DIR Make or Make install ERROR,Please Check......" exit 0 fifi}Apache\_install 1 | | --- | 1. 创建judge\_ip判断IP函数: | \#!/bin/bash\#By author jfedu.net 2022judge\_ip(){ read \-p "Please enter ip Address,example 192\.168\.0\.11 ip": IPADDR echo $IPADDR\|grep \-v "\[Aa\-Zz]"\|grep \-\-color \-E "(\[0\-9]{1,3}\\.){3}\[0\-9]{1,3}"}judge\_ip | | --- | ## Shell编程四剑客之Find 通过如上基础语法的学习,读者对Shell编程有了更近一步的理解,Shell编程不再是简单命令的堆积,而是演变成了各种特殊的语句、各种语法、编程工具、各种命令的集合。 在Shell编程工具中,四剑客工具的使用更加的广泛,Shell编程四剑客包括:find、sed、grep、awk,熟练掌握四剑客会对Shell编程能力极大的提升。 四剑客之Find工具实战,Find工具主要用于操作系统文件、目录的查找,其语法参数格式为: | find path \-option \[ \-print ] \[ \-exec \-ok command ] { } \\; | | --- | 其option常用参数详解如下: | \-name filename \#查找名为filename的文件;\-type b/d/c/p/l/f \#查是块设备、目录、字符设备、管道、符号链接、普通文件;\-size n\[c] \#查长度为n块\[或n字节]的文件;\-perm \#按执行权限来查找;\-user username \#按文件属主来查找;\-group groupname \#按组来查找;\-mtime \-n \+n \#按文件更改时间来查找文件,\-n指n天以内,\+n指n天以前;\-atime \-n \+n \#按文件访问时间来查找文件;\-ctime \-n \+n \#按文件创建时间来查找文件;\-mmin \-n \+n \#按文件更改时间来查找文件,\-n指n分钟以内,\+n指n分钟以前;\-amin \-n \+n \#按文件访问时间来查找文件;\-cmin \-n \+n \#按文件创建时间来查找文件;\-nogroup \#查无有效属组的文件;\-nouser \#查无有效属主的文件;\-newer f1 !f2 \#找文件,\-n指n天以内,\+n指n天以前;\-depth \#使查找在进入子目录前先行查找完本目录;\-fstype \#查更改时间比f1新但比f2旧的文件;\-mount \#查文件时不跨越文件系统mount点;\-follow \#如果遇到符号链接文件,就跟踪链接所指的文件;\-cpio \#查位于某一类型文件系统中的文件;\-prune \#忽略某个目录;\-maxdepth \#查找目录级别深度。 | | --- | 1. Find工具\-name参数案列: | find /data/ \-name "\*.txt" \#查找/data/目录以.txt结尾的文件;find /data/ \-name "\[A\-Z]\*" \#查找/data/目录以大写字母开头的文件;find /data/ \-name "test\*" \#查找/data/目录以test开头的文件; | | --- | 1. Find工具\-type参数案列: | find /data/ \-type d \#查找/data/目录下的文件夹;find /data/ ! \-type d \#查找/data/目录下的非文件夹;find /data/ \-type l \#查找/data/目录下的链接文件。find /data/ \-type d\|xargs chmod 755 \-R \#查目录类型并将权限设置为755;find /data/ \-type f\|xargs chmod 644 \-R \#查文件类型并将权限设置为644; | | --- | 1. Find工具\-size参数案列: | find /data/ \-size \+1M \#查文件大小大于1Mb的文件;find /data/ \-size 10M \#查文件大小为10M的文件;find /data/ \-size \-1M \#查文件大小小于1Mb的文件; | | --- | 1. Find工具\-perm参数案列: | find /data/ \-perm 755 \#查找/data/目录权限为755的文件或者目录;find /data/ \-perm \-007 \#与\-perm 777相同,表示所有权限;find /data/ \-perm \+644 \#文件权限符号644以上; | | --- | 1. Find工具\-mtime参数案列: | atime,access time 文件被读取或者执行的时间;ctime,change time 文件状态改变时间;mtime,modify time 文件内容被修改的时间;find /data/ \-mtime \+30 \-name "\*.log" \#查找30天以前的log文件;find /data/ \-mtime \-30 \-name "\*.txt" \#查找30天以内的log文件;find /data/ \-mtime 30 \-name "\*.txt" \#查找第30天的log文件;find /data/ \-mmin \+30 \-name "\*.log" \#查找30分钟以前修改的log文件;find /data/ \-amin \-30 \-name "\*.txt" \#查找30分钟以内被访问的log文件;find /data/ \-cmin 30 \-name "\*.txt" \#查找第30分钟改变的log文件。 | | --- | 1. Find工具参数综合案列: | \#查找/data目录以.log结尾,文件大于10k的文件,同时cp到/tmp目录;find /data/ \-name "\*.log" –type f \-size \+10k \-exec cp {} /tmp/ \\;\#查找/data目录以.txt结尾,文件大于10k的文件,权限为644并删除该文件;find /data/ \-name "\*.log" –type f \-size \+10k \-m perm 644 \-exec rm –rf {} \\;\#查找/data目录以.log结尾,30天以前的文件,大小大于10M并移动到/tmp目录;find /data/ \-name "\*.log" –type f \-mtime \+30 –size \+10M \-exec mv {} /tmp/ \\; | | --- | ## Shell编程四剑客之GREP 全面搜索正则表达式(Global search regular expression(RE) ,GREP)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。 Unix/Linux的grep家族包括grep、egrep和fgrep,其中egrep和fgrep的命令跟grep有细微的区别,egrep是grep的扩展,支持更多的re元字符, fgrep是fixed grep或fast grep简写,它们把所有的字母都看作单词,正则表达式中的元字符表示其自身的字面意义,不再有其他特殊的含义,一般使用比较少。 目前Linux操作系统默认使用GNU版本的grep。它功能更强,可以通过\-G、\-E、\-F命令行选项来使用egrep和fgrep的功能。其语法格式及常用参数详解如下: | grep \-\[acinv] 'word' Filename | | --- | Grep常用参数详解如下: | \-a 以文本文件方式搜索;\-c 计算找到的符合行的次数;\-i 忽略大小写;\-n 顺便输出行号;\-v 反向选择,即显示不包含匹配文本的所有行;\-h 查询多文件时不显示文件名;\-l 查询多文件时只输出包含匹配字符的文件名;\-s 不显示不存在或无匹配文本的错误信息;\-E 允许使用egrep扩展模式匹配。 | | --- | 学习Grep时,需要了解通配符、正则表达式两个概念,很多读者容易把彼此搞混淆,通配符主要用在[Linux](http://lib.csdn.net/base/linux" \t "_blank" \o "Linux知识库)的Shell命令中,常用于文件或者文件名称的操作,而正则表达式用于文本内容中的字符串搜索和替换,常用在AWK、GREP、SED、VIM工具中对文本的操作。 通配符类型详解: | \* 0个或者多个字符、数字;? 匹配任意一个字符;\# 表示注解;\| 管道符号;; 多个命令连续执行;\& 后台运行指令;! 逻辑运算非;\[ ] 内容范围,匹配括号中内容;{ } 命令块,多个命令匹配。 | | --- | 正则表达式详解: | \* 前一个字符匹配0次或多次;. 匹配除了换行符以外任意一个字符;.\* 代表任意字符;^ 匹配行首,即以某个字符开头;$ 匹配行尾,即以某个字符结尾;\\(..\\) 标记匹配字符;\[] 匹配中括号里的任意指定字符,但只匹配一个字符;\[^] 匹配除中括号以外的任意一个字符;\\ 转义符,取消特殊含义;\\\< 锚定单词的开始;\\\> 锚定单词的结束;{n} 匹配字符出现n次;{n,} 匹配字符出现大于等于n次;{n,m} 匹配字符至少出现n次,最多出现m次;\\w 匹配文字和数字字符;\\W \\w的反置形式,匹配一个或多个非单词字符;\\b 单词锁定符;\\s 匹配任何空白字符;\\d 匹配一个数字字符,等价于\[0\-9]。 | | --- | 常用GREP工具企业演练案列: | grep \-c "test" jfedu.txt 统计test字符总行数;grep \-i "TEST" jfedu.txt 不区分大小写查找TEST所有的行;grep \-n "test" jfedu.txt 打印test的行及行号;grep \-v "test" jfedu.txt 不打印test的行;grep "test\[53]" jfedu.txt 以字符test开头,接5或者3的行;grep "^\[^test]" jfedu.txt 显示输出行首不是test的行;grep "\[Mm]ay" jfedu.txt 匹配M或m开头的行;grep "K…D" jfedu.txt 匹配K,三个任意字符,紧接D的行;grep "\[A\-Z]\[9]D" jfedu.txt 匹配大写字母,紧跟9D的字符行;grep "T\\{2,\\}" jfedu.txt 打印字符T字符连续出现2次以上的行;grep "T\\{4,6\\}" jfedu.txt 打印字符T字符连续出现4次及6次的行;grep \-n "^$" jfedu.txt 打印空行的所在的行号;grep \-vE "\#\|^$" jfedu.txt 不匹配文件中的\#和空行;grep \-\-color \-ra \-E "db\|config\|sql" \* 匹配包含db或者config或者sql的文件;grep \-\-color \-E "\\\<(\[0\-9]{1,3}\\.){3}(\[0\-9]{1,3})\\\>" jfedu.txt 匹配IPV4地址。 | | --- | ## Shell数组编程 数组是相同数据类型的元素按一定顺序排列的集合,把有限个类型相同的变量用一个名字命名,然后用编号区分他们变量的集合,这个名称称之为数组名,编号成为下标。Linux Shell编程中常用一维数组。 数组的设计其实了为了处理方便,把具有相同类型的若干变量按有序的形式组织起来的一种形式,以减少重复频繁的单独定义。如图17\-3所示: ![](/media/202411/20241125143346216880.jpeg)图17\-3 一维、二维、三维数组 定义数组一般以小括号的方式来定义,数组的值可以随机指定,如下为一维数组的定义、统计、引用和删除操作,: 1. 一唯数组定义及创建: | JFTEST\=( test1test2test3 )LAMP\=(httpd php php\-devel php\-mysql mysql mysql\-server) | | --- | 1. 数组下标一般从0开始,如下为引用数组的方法: | echo ${JFTEST\[0]} 引用第一个数组变量,结果打印test1;echo ${JFTEST\[1]} 引用第二个数组变量;echo ${JFTEST\[@]} 显示该数组所有参数;echo ${\#JFTEST\[@]} 显示该数组参数个数;echo ${\#JFTEST\[0]} 显示test1字符长度;echo ${JFTEST\[@]:0} 打印数组所有的值;echo ${JFTEST\[@]:1} 打印从第二个值开始的所有值;echo ${JFTEST\[@]:0:2} 打印从第一个值与第二个值;echo ${JFTEST\[@]:1:2} 打印从第二个值与第三个值。 | | --- | 1. 数组替换操作: | JFTEST\=( \[0]\=www1 \[1]\=www2 \[2]\=www3 ) 数组赋值;echo ${JFTEST\[@]/test/jfedu} 将数组值test替换为jfedu;NEWJFTEST\=\`echo ${JFTEST\[@]/test/jfedu}\` 将结果赋值新数组。 | | --- | 1. 数组删除操作: | unset array\[0] 删除数组第一个值;unset array\[1] 删除数组第二个值;unset array 删除整个数组。 | | --- | 1. 数组Shell脚本企业案例一,网卡bond绑定脚本: | \#!/bin/bash\#Auto Make KVM Virtualization\#Auto config bond scripts\#By author jfedu.net 2022eth\_bond(){NETWORK\=( HWADDR\=\`ifconfig eth0 \|egrep "HWaddr\|Bcast" \|tr "\\n" " "\|awk '{print $5,$7,$NF}'\|sed \-e 's/addr://g' \-e 's/Mask://g'\|awk '{print $1}'\` IPADDR\=\`ifconfig eth0 \|egrep "HWaddr\|Bcast" \|tr "\\n" " "\|awk '{print $5,$7,$NF}'\|sed \-e 's/addr://g' \-e 's/Mask://g'\|awk '{print $2}'\` NETMASK\=\`ifconfig eth0 \|egrep "HWaddr\|Bcast" \|tr "\\n" " "\|awk '{print $5,$7,$NF}'\|sed \-e 's/addr://g' \-e 's/Mask://g'\|awk '{print $3}'\` GATEWAY\=\`route \-n\|grep "UG"\|awk '{print $2}'\`)cat \>ifcfg\-bond0\<\<EOFDEVICE\=bond0BOOTPROTO\=static${NETWORK\[1]}${NETWORK\[2]}${NETWORK\[3]}ONBOOT\=yesTYPE\=EthernetNM\_CONTROLLED\=noEOF | | --- | 1. 数组Shell脚本企业案例二,定义IPv4值: | \#!/bin/bash\#auto Change ip netmask gateway scripts \#By author jfedu.net 2022ETHCONF\=/etc/sysconfig/network\-scripts/ifcfg\-eth0HOSTS\=/etc/hostsNETWORK\=/etc/sysconfig/networkDIR\=/data/backup/\`date \+%Y%m%d\`NETMASK\=255\.255\.255\.0echo "\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-"count\_ip(){ count\=(\`echo $IPADDR\|awk \-F. '{print $1,$2,$3,$4}'\`) IP1\=${count\[0]} IP2\=${count\[1]} IP3\=${count\[2]} IP4\=${count\[3]}} | | --- | # Shell编程高级企业实战 企业生产环境中,服务器规模成百上千,如果依靠人工去维护和管理是非常吃力的,基于Shell编程脚本管理和维护服务器变得简单、从容,而且对企业自动化运维之路的建设起到极大的推动作用。 本章向读者介绍企业生产环境Shell编程案例、自动化备份MySQL数据、服务器信息收集、防止恶意IP访问、LAMP\+MySQL主从实战、千台服务器IP修改、Nginx\+Tomcat高级自动化部署脚本、Nginx虚拟主机配置、Docker管理平台等。 ## Shell编程实战系统备份脚本 日常企业运维中,需要备份Linux操作系统中重要的文件,例如/etc、/boot分区、重要网站数据等,在备份数据时,由于数据量非常大,需要指定高效的备份方案,如下为常用的备份数据方案: * 每周日进行完整备份,周一至周六使用增量备份; * 每周六进行完整备份,周日至周五使用增量备份。 企业备份数据的工具主要有:tar、cp、rsync、scp、sersync、dd等工具。如下为基于开源tar工具实现系统数据备份方案: Tar工具手动全备份网站,\-g参数指定新的快照文件: | tar \-g /tmp/snapshot \-czvf /tmp/2022\_full\_system\_data.tar.gz /data/sh/ | | --- | Tar工具手动增量备份网站,\-g参数指定全备已生成的快照文件,后续增量备份基于上一个增量备份快照文件: | tar \-g /tmp/snapshot \-czvf /tmp/2014\_add01\_system\_data.tar.gz /data/sh/ | | --- | Tar工具全备、增量备份网站,Shell脚本实现自动打包备份编写思路如下: * 系统备份数据按每天存放; * 创建完整备份函数块; * 创建增量备份函数块; * 根据星期数判断完整或增量; * 将脚本加入Crontab实现自动备份; Tar工具全备、增量备份网站,Shell脚本实现自动打包备份,代码如下: | \#!/bin/bash\#Auto Backup Linux System Files\#By author jfedu.net 2022\#Define Path variablesSOURCE\_DIR\=( $\*)TARGET\_DIR\=/data/backup/YEAR\=\`date \+%Y\`MONTH\=\`date \+%m\`DAY\=\`date \+%d\`WEEK\=\`date \+%u\`A\_NAME\=\`date \+%H%M\`FILES\=system\_backup.tgzCODE\=$?if \[ \-z "$\*" ];then echo \-e "\\033\[32mUsage:\\nPlease Enter Your Backup Files or Directories\\n\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\\n\\nUsage: { $0 /boot /etc}\\033\[0m" exitfi\#Determine Whether the Target Directory Existsif \[ ! \-d $TARGET\_DIR/$YEAR/$MONTH/$DAY ];then mkdir \-p $TARGET\_DIR/$YEAR/$MONTH/$DAY echo \-e "\\033\[32mThe $TARGET\_DIR Created Successfully !\\033\[0m"fi\#EXEC Full\_Backup Function CommandFull\_Backup(){if \[ "$WEEK" \-eq "7" ];then rm \-rf $TARGET\_DIR/snapshot cd $TARGET\_DIR/$YEAR/$MONTH/$DAY ;tar \-g $TARGET\_DIR/snapshot \-czvf $FILES ${SOURCE\_DIR\[@]} \[ "$CODE" \=\= "0" ]\&\&echo \-e "\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\\n\\033\[32mThese Full\_Backup System Files Backup Successfully !\\033\[0m"fi}\#Perform incremental BACKUP Function CommandAdd\_Backup(){ if \[ $WEEK \-ne "7" ];then cd $TARGET\_DIR/$YEAR/$MONTH/$DAY ;tar \-g $TARGET\_DIR/snapshot \-czvf $A\_NAME$FILES ${SOURCE\_DIR\[@]} \[ "$CODE" \=\= "0" ]\&\&echo \-e "\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\\n\\033\[32mThese Add\_Backup System Files $TARGET\_DIR/$YEAR/$MONTH/$DAY/${YEAR}\_$A\_NAME$FILES Backup Successfully !\\033\[0m" fi}sleep 3 Full\_Backup;Add\_Backup | | --- | Crontab任务计划中添加如下语句,每天凌晨1点整执行备份脚本即可: | 0 1 \* \* \* /bin/sh /data/sh/auto\_backup.sh /boot /etc/ \>\> /tmp/back.log 2\>\&1 | | --- | ## Shell编程实战收集服务器信息 在企业上产环境中,经常会对服务器资产进行统计存档,单台服务器可以手动去统计服务器的CPU型号、内存大小、硬盘容量、网卡流量等,如果服务器数量超过百台、千台,使用手工方式就变得非常吃力。 基于Shell脚本实现自动化服务器硬件信息的收集,并将收集的内容存放在数据库,能更快、更高效的实现对服务器资产信息的管理。Shell脚本实现服务器信息自动收集,编写思路如下: * 创建数据库和表存储服务器信息; * 基于Shell四剑客awk、find、sed、grep获取服务器信息; * 将获取的信息写成SQL语句; * 定期对SQL数据进行备份; * 将脚本加入Crontab实现自动备份; 创建数据库表,创建SQL语句如下: | CREATE TABLE \`audit\_system\` ( \`id\` int(11\) NOT NULL AUTO\_INCREMENT, \`ip\_info\` varchar(50\) NOT NULL, \`serv\_info\` varchar(50\) NOT NULL, \`cpu\_info\` varchar(50\) NOT NULL, \`disk\_info\` varchar(50\) NOT NULL, \`mem\_info\` varchar(50\) NOT NULL, \`load\_info\` varchar(50\) NOT NULL, \`mark\_info\` varchar(50\) NOT NULL, PRIMARY KEY (\`id\`), UNIQUE KEY \`ip\_info\` (\`ip\_info\`), UNIQUE KEY \`ip\_info\_2\` (\`ip\_info\`) ); | | --- | Shell脚本实现服务器信息自动收集,代码如下: | \#!/bin/bash\#Auto get system info\#By author jfedu.net 2022\#Define Path variablesecho \-e "\\033\[34m \\033\[1m"cat \<\<EOF\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+Welcome to use system Collect\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+EOFip\_info\=\`ifconfig \|grep "Bcast"\|tail \-1 \|awk '{print $2}'\|cut \-d: \-f 2\`cpu\_info1\=\`cat /proc/cpuinfo \|grep 'model name'\|tail \-1 \|awk \-F: '{print $2}'\|sed 's/^ //g'\|awk '{print $1,$3,$4,$NF}'\`cpu\_info2\=\`cat /proc/cpuinfo \|grep "physical id"\|sort \|uniq \-c\|wc \-l\`serv\_info\=\`hostname \|tail \-1\`disk\_info\=\`fdisk \-l\|grep "Disk"\|grep \-v "identifier"\|awk '{print $2,$3,$4}'\|sed 's/,//g'\`mem\_info\=\`free \-m \|grep "Mem"\|awk '{print "Total",$1,$2"M"}'\`load\_info\=\`uptime \|awk '{print "Current Load: "$(NF\-2\)}'\|sed 's/\\,//g'\`mark\_info\='BeiJing\_IDC'echo \-e "\\033\[32m\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\\033\[1m"echo IPADDR:${ip\_info}echo HOSTNAME:$serv\_infoecho CPU\_INFO:${cpu\_info1} X${cpu\_info2}echo DISK\_INFO:$disk\_infoecho MEM\_INFO:$mem\_infoecho LOAD\_INFO:$load\_infoecho \-e "\\033\[32m\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\\033\[0m"echo \-e \-n "\\033\[36mYou want to write the data to the databases? \\033\[1m" ;read ensureif \[ "$ensure" \=\= "yes" \-o "$ensure" \=\= "y" \-o "$ensure" \=\= "Y" ];then echo "\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-" echo \-e '\\033\[31mmysql \-uaudit \-p123456 \-D audit \-e ''' "insert into audit\_system values('','${ip\_info}','$serv\_info','${cpu\_info1} X${cpu\_info2}','$disk\_info','$mem\_info','$load\_info','$mark\_info')" ''' \\033\[0m ' mysql \-uroot \-p123456 \-D test \-e "insert into audit\_system values('','${ip\_info}','$serv\_info','${cpu\_info1} X${cpu\_info2}','$disk\_info','$mem\_info','$load\_info','$mark\_info')"else echo "Please wait,exit......" exitfi | | --- | 手动读取数据库服务器信息命令: | mysql \-uroot \-p123 \-e 'use wugk1 ;select \* from audit\_audit\_system;'\|sed 's/\-//g'\|grep \-v "id" | | --- | ## Shell编程实战拒绝恶意IP登录 企业服务器暴露在外网,每天会有大量的人使用各种用户名和密码尝试登陆服务器,如果让其一直尝试,难免会猜出密码,通过开发Shell脚本,可以自动将尝试登陆服务器错误密码次数的IP列表加入到防火墙配置中。 Shell脚本实现服务器拒绝恶意IP登陆,编写思路如下: * 登陆服务器日志/var/log/secure; * 检查日志中认证失败的行并打印其IP地址; * 将IP地址写入至防火墙; * 禁止该IP访问服务器SSH 22端口; * 将脚本加入Crontab实现自动禁止恶意IP; Shell脚本实现服务器拒绝恶意IP登陆,代码如下: | \#!/bin/bash\#Auto drop ssh failed IP address\#By author jfedu.net 2022\#Define Path variablesSEC\_FILE\=/var/log/secureIP\_ADDR\=\`awk '{print $0}' /var/log/secure\|grep \-i "fail"\| egrep \-o "(\[0\-9]{1,3}\\.){3}\[0\-9]{1,3}" \| sort \-nr \| uniq \-c \|awk '$1\>\=15 {print $2}'\`IPTABLE\_CONF\=/etc/sysconfig/iptablesechocat \<\<EOF\+\+\+\+\+\+\+\+\+\+\+\+\+\+welcome to use ssh login drop failed ip\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+EOFechofor ((j\=0;j\<\=6;j\+\+)) ;do echo \-n "\-";sleep 1 ;doneechofor i in \`echo $IP\_ADDR\`do cat $IPTABLE\_CONF \|grep $i \>/dev/nullif \[ $? \-ne 0 ];thensed \-i "/lo/a \-A INPUT \-s $i \-m state \-\-state NEW \-m tcp \-p tcp \-\-dport 22 \-j DROP" $IPTABLE\_CONFfidoneNUM\=\`find /etc/sysconfig/ \-name iptables \-a \-mmin \-1\|wc \-l\` if \[ $NUM \-eq 1 ];then /etc/init.d/iptables restart fi | | --- | ## Shell编程实战LAMP一键安装 LAMP是目前互联网主流WEB网站架构,通过源码安装、维护和管理对于单台很轻松,如果服务器数量多,手工管理就非常困难,基于Shell脚本可以更快速的维护LAMP架构。 Shell脚本实现服务器LAMP一键源码安装配置,编写思路如下: * 脚本的功能,实现安装LAMP环境、论坛网站; * Apache安装配置、MYSQL、PHP安装; * 源码LAMP整合配置; * 启动数据库,创建数据库并授权; * 重启LAMP所有服务, 验证访问; Shell脚本实现服务器LAMP一键源码安装配置,代码如下: | \#!/bin/bash\#Auto install LAMP \#By author jfedu.net 2022\#Define Path variables\#Httpd define path variableH\_FILES\=httpd\-2\.2\.32\.tar.bz2H\_FILES\_DIR\=httpd\-2\.2\.32H\_URL\=http://mirrors.cnnic.cn/apache/httpd/H\_PREFIX\=/usr/local/apache2/\#MySQL define path variableM\_FILES\=mysql\-5\.5\.20\.tar.gzM\_FILES\_DIR\=mysql\-5\.5\.20M\_URL\=http://down1\.chinaunix.net/distfiles/M\_PREFIX\=/usr/local/mysql/\#PHP define path variableP\_FILES\=php\-5\.3\.28\.tar.bz2P\_FILES\_DIR\=php\-5\.3\.28P\_URL\=http://mirrors.sohu.com/php/P\_PREFIX\=/usr/local/php5/function httpd\_install(){if \[\[ "$1" \-eq "1" ]];then wget \-c $H\_URL/$H\_FILES \&\& tar \-jxvf $H\_FILES \&\& cd $H\_FILES\_DIR \&\&./configure \-\-prefix\=$H\_PREFIX if \[ $? \-eq 0 ];then make \&\& make install fifi}function mysql\_install(){if \[\[ "$1" \-eq "2" ]];thenwget \-c $M\_URL/$M\_FILES \&\& tar \-xzvf $M\_FILES \&\& cd $M\_FILES\_DIR \&\&yum install cmake ncurses\-devel \-y ;cmake . \-DCMAKE\_INSTALL\_PREFIX\=$M\_PREFIX \\\-DMYSQL\_UNIX\_ADDR\=/tmp/mysql.sock \\\-DMYSQL\_DATADIR\=/data/mysql \\\-DSYSCONFDIR\=/etc \\\-DMYSQL\_USER\=mysql \\\-DMYSQL\_TCP\_PORT\=3306 \\\-DWITH\_XTRADB\_STORAGE\_ENGINE\=1 \\\-DWITH\_INNOBASE\_STORAGE\_ENGINE\=1 \\\-DWITH\_PARTITION\_STORAGE\_ENGINE\=1 \\\-DWITH\_BLACKHOLE\_STORAGE\_ENGINE\=1 \\\-DWITH\_MYISAM\_STORAGE\_ENGINE\=1 \\\-DWITH\_READLINE\=1 \\\-DENABLED\_LOCAL\_INFILE\=1 \\\-DWITH\_EXTRA\_CHARSETS\=1 \\\-DDEFAULT\_CHARSET\=utf8 \\\-DDEFAULT\_COLLATION\=utf8\_general\_ci \\\-DEXTRA\_CHARSETS\=all \\\-DWITH\_BIG\_TABLES\=1 \\\-DWITH\_DEBUG\=0if \[ $? \-eq 0 ];then make \&\& make install echo \-e "\\n\\033\[32m\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\\033\[0m" echo \-e "\\033\[32mThe $M\_FILES\_DIR Server Install Success !\\033\[0m" else echo \-e "\\033\[32mThe $M\_FILES\_DIR Make or Make install ERROR,Please Check......" exit 0fi/bin/cp support\-files/my\-small.cnf /etc/my.cnf/bin/cp support\-files/mysql.server /etc/init.d/mysqldchmod \+x /etc/init.d/mysqldchkconfig \-\-add mysqldchkconfig mysqld onfi}function php\_install(){if \[\[ "$1" \-eq "3" ]];then yum install libxml2\-devel perl\-devel perl libtool\* \-y wget \-c $P\_URL/$P\_FILES \&\& tar \-jxvf $P\_FILES \&\& cd $P\_FILES\_DIR \&\&./configure \-\-prefix\=$P\_PREFIX \-\-with\-config\-file\-path\=$P\_PREFIX/etc \-\-with\-mysql\=$M\_PREFIX \-\-with\-apxs2\=$H\_PREFIX/bin/apxs if \[ $? \-eq 0 ];then make ZEND\_EXTRA\_LIBS\='\-liconv' \&\& make install echo \-e "\\n\\033\[32m\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\\033\[0m" echo \-e "\\033\[32mThe $P\_FILES\_DIR Server Install Success !\\033\[0m" else echo \-e "\\033\[32mThe $P\_FILES\_DIR Make or Make install ERROR,Please Check......" exit 0 fifi}function lamp\_config(){if \[\[ "$1" \-eq "4" ]];then sed \-i '/DirectoryIndex/s/index.html/index.php index.html/g' $H\_PREFIX/conf/httpd.conf $H\_PREFIX/bin/apachectl restart echo "AddType application/x\-httpd\-php .php" \>\>$H\_PREFIX/conf/httpd.conf IP\=\`ifconfig eth0\|grep "Bcast"\|awk '{print $2}'\|cut \-d: \-f2\` echo "You can to access http://$IP/"cat \>$H\_PREFIX/htdocs/index.php\<\<EOF\<?phpphpinfo();?\>EOFfi}PS3\="Please enter you select install menu:"select i in http mysql php config quitdocase $i in http) httpd\_install 1 ;; mysql) mysql\_install 2 ;; php) php\_install 3 ;; config) lamp\_config 4 ;; quit) exitesacdone | | --- | ## Shell编程实战MYSQL主从复制 MYSQL数据库服务器应用主要应用于与动态网站结合,存放网站必要的数据,例如订单、交易、员工表、薪资等记录,为了实现数据备份,需引入MYSQL主从架构,MYSQL主从架构脚本可以实现自动化安装、配置和管理。 Shell脚本实现服务器MYSQL一键YUM安装配置,编写思路如下: MYSQL主库的操作: * 主库上安装MYSQL,设置server\-id、bin\-log; * 授权复制同步的用户,对客户端授权; * 确认bin\-log文件名、position位置点。 MYSQL丛库的操作: * 从库上安装MYSQL,设置server\-id; * change master 指定主库和bin\-log名和position; * start slave; 启动丛库IO线程; * show slave status\\G查看主从的状态。 Shell脚本实现服务器MYSQL一键YUM安装配置,需要提前手动授权主库可以免密码登录丛库服务器,代码如下: | \#!/bin/bash\#Auto install Mysql AB Repliation\#By author jfedu.net 2022\#Define Path variablesMYSQL\_SOFT\="mysql mysql\-server mysql\-devel php\-mysql mysql\-libs"NUM\=\`rpm \-qa \|grep \-i mysql \|wc \-l\`INIT\="/etc/init.d/mysqld"CODE\=$?\#Mysql To Install 2022if \[ $NUM \-ne 0 \-a \-f $INIT ];then echo \-e "\\033\[32mThis Server Mysql already Install.\\033\[0m" read \-p "Please ensure yum remove Mysql Server,YES or NO": INPUT if \[ $INPUT \=\= "y" \-o $INPUT \=\= "yes" ];then yum remove $MYSQL\_SOFT \-y ;rm \-rf /var/lib/mysql /etc/my.cnf yum install $MYSQL\_SOFT \-y else echo fielse yum remove $MYSQL\_SOFT \-y ;rm \-rf /var/lib/mysql /etc/my.cnf yum install $MYSQL\_SOFT \-y if \[ $CODE \-eq 0 ];then echo \-e "\\033\[32mThe Mysql Install Successfully.\\033\[0m" else echo \-e "\\033\[32mThe Mysql Install Failed.\\033\[0m" exit 1 fifimy\_config(){cat \>/etc/my.cnf\<\<EOF\[mysqld]datadir\=/var/lib/mysqlsocket\=/var/lib/mysql/mysql.sockuser\=mysqlsymbolic\-links\=0log\-bin\=mysql\-binserver\-id \= 1auto\_increment\_offset\=1auto\_increment\_increment\=2\[mysqld\_safe]log\-error\=/var/log/mysqld.logpid\-file\=/var/run/mysqld/mysqld.pidEOF}my\_config/etc/init.d/mysqld restartps \-ef \|grep mysqlMYSQL\_CONFIG(){\#Master Config Mysqlmysql \-e "grant replication slave on \*.\* to 'tongbu'@'%' identified by '123456';"MASTER\_FILE\=\`mysql \-e "show master status;"\|tail \-1\|awk '{print $1}'\`MASTER\_POS\=\`mysql \-e "show master status;"\|tail \-1\|awk '{print $2}'\`MASTER\_IPADDR\=\`ifconfig eth0\|grep "Bcast"\|awk '{print $2}'\|cut \-d: \-f2\`read \-p "Please Input Slave IPaddr: " SLAVE\_IPADDR\#Slave Config Mysqlssh \-l root $SLAVE\_IPADDR "yum remove $MYSQL\_SOFT \-y ;rm \-rf /var/lib/mysql /etc/my.cnf ;yum install $MYSQL\_SOFT \-y" ssh \-l root $SLAVE\_IPADDR "$my\_config" \#scp \-r /etc/my.cnf root@192\.168\.111\.129:/etc/ssh \-l root $SLAVE\_IPADDR "sed \-i 's\#server\-id \= 1\#server\-id \= 2\#g' /etc/my.cnf" ssh \-l root $SLAVE\_IPADDR "sed \-i '/log\-bin\=mysql\-bin/d' /etc/my.cnf" ssh \-l root $SLAVE\_IPADDR "/etc/init.d/mysqld restart" ssh \-l root $SLAVE\_IPADDR "mysql \-e \\"change master to master\_host\='$MASTER\_IPADDR',master\_user\='tongbu',master\_password\='123456',master\_log\_file\='$MASTER\_FILE',master\_log\_pos\=$MASTER\_POS;\\""ssh \-l root $SLAVE\_IPADDR "mysql \-e \\"slave start;\\"" ssh \-l root $SLAVE\_IPADDR "mysql \-e \\"show slave status\\G;\\"" }read \-p "Please ensure your Server is Master and you will config mysql Replication?yes or no": INPUTif \[ $INPUT \=\= "y" \-o $INPUT \=\= "yes" ];then MYSQL\_CONFIGelse exit 0fi | | --- | ## Shell编程实战修改IP及主机名 企业中服务器IP地址系统通过自动化工具安装完系统,IP均是自动获取的,而服务器要求固定的静态IP,百台服务器手工去配置静态IP是不可取的,可以基于Shell脚本自动修改IP、主机名等信息。 Shell脚本实现服务器IP、主机名自动修改及配置,编写思路如下: * 静态IP修改; * 动态IP修改; * 根据IP\-生成主机名并配置; * 修改DNS域名解析; Shell脚本实现服务器IP、主机名自动修改及配置,代码如下: | \#!/bin/bash \#Auto Change ip netmask gateway scripts \#By author jfedu.net 2022\#Define Path variablesETHCONF\=/etc/sysconfig/network\-scripts/ifcfg\-eth0 HOSTS\=/etc/hosts NETWORK\=/etc/sysconfig/network DIR\=/data/backup/\`date \+%Y%m%d\`NETMASK\=255\.255\.255\.0 echo "\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-"judge\_ip(){ read \-p "Please enter ip Address,example 192\.168\.0\.11 ip": IPADDR echo $IPADDR\|grep \-v "\[Aa\-Zz]"\|grep \-\-color \-E "(\[0\-9]{1,3}\\.){3}\[0\-9]{1,3}"}count\_ip(){ count\=(\`echo $IPADDR\|awk \-F. '{print $1,$2,$3,$4}'\`) IP1\=${count\[0]} IP2\=${count\[1]} IP3\=${count\[2]} IP4\=${count\[3]}}ip\_check(){judge\_ipwhile \[ $? \-ne 0 ]do judge\_ipdonecount\_ipwhile \[ "$IP1" \-lt 0 \-o "$IP1" \-ge 255 \-o "$IP2" \-ge 255 \-o "$IP3" \-ge 255 \-o "$IP4" \-ge 255 ]do judge\_ip while \[ $? \-ne 0 ] do judge\_ip done count\_ipdone}change\_ip(){ if \[ ! \-d $DIR ];then mkdir \-p $DIR fi echo "The Change ip address to Backup Interface eth0" cp $ETHCONF $DIR grep "dhcp" $ETHCONF if \[ $? \-eq 0 ];then read \-p "Please enter ip Address:" IPADDR sed \-i 's/dhcp/static/g' $ETHCONF echo \-e "IPADDR\=$IPADDR\\nNETMASK\=$NETMASK\\nGATEWAY\=\`echo $IPADDR\|awk \-F. '{print $1"."$2"."$3}'\`.2" \>\>$ETHCONF echo "The IP configuration success. !" else echo \-n "Static IP has been configured,please confirm whether to modify,yes or No": read i fiif \[ "$i" \=\= "y" \-o "$i" \=\= "yes" ];then ip\_check sed \-i \-e '/IPADDR/d' \-e '/NETMASK/d' \-e '/GATEWAY/d' $ETHCONF echo \-e "IPADDR\=$IPADDR\\nNETMASK\=$NETMASK\\nGATEWAY\=\`echo $IPADDR\|awk \-F. '{print $1"."$2"."$3}'\`.2" \>\>$ETHCONF echo "The IP configuration success. !" echoelse echo "Static IP already exists,please exit." exit $? fi }change\_hosts(){ if \[ ! \-d $DIR ];then mkdir \-p $DIR fi cp $HOSTS $DIR ip\_checkhost\=\` echo $IPADDR\|sed 's/\\./\-/g'\|awk '{print "BJ\-IDC\-"$0"\-jfedu.net"}'\` cat $HOSTS \|grep "$host" if \[ $? \-ne 0 ];then echo "$IPADDR $host" \>\> $HOSTS echo "The hosts modify success " fi grep "$host" $NETWORK if \[ $? \-ne 0 ];then sed \-i "s/^HOSTNAME/\#HOSTNAME/g" $NETWORK echo "NETWORK\=$host" \>\>$NETWORK hostname $host;sufi} PS3\="Please Select configuration ip or configuration host:" select i in "modify\_ip" "modify\_hosts" "exit" do case $i in modify\_ip) change\_ip ;; modify\_hosts) change\_hosts ;; exit) exit ;; \*) echo \-e "1\) modify\_ip\\n2\) modify\_ip\\n3\)exit" esac done | | --- | ## Shell编程实战Zabbix安装配置 Zabbix是一款分布式监控系统,基于C/S模式,需在服务器安装Zabbix\_server,在客户端安装Zabbix\_agent,通过Shell脚本可以更快速的实现该需求。 Shell脚本实现Zabbix服务器端和客户端自动安装,编写思路如下: * Zabbix软件的版本源码安装、路径、\-\-enable\-server、\-\-enable\-agent; * cp zabbix\_agentd启动进程\-/etc/init.d/zabbix\_agentd、给执行x权限; * 配置zabbix\_agentd.conf文件,指定server IP变量; * 指定客户端的Hostname其实可以等于客户端IP地址; * 启动zabbix\_agentd服务,创建zabbix user。 Shell脚本实现Zabbix服务器端和客户端自动安装,代码如下: | \#!/bin/bash\#Auto install zabbix server and client\#By author jfedu.net 2022\#Define Path variablesZABBIX\_SOFT\="zabbix\-3\.2\.6\.tar.gz"INSTALL\_DIR\="/usr/local/zabbix/"SERVER\_IP\="192\.168\.111\.128"IP\=\`ifconfig\|grep Bcast\|awk '{print $2}'\|sed 's/addr://g'\`SERVER\_INSTALL(){yum \-y install curl curl\-devel net\-snmp net\-snmp\-devel perl\-DBIgroupadd zabbix ;useradd \-g zabbix zabbix;usermod \-s /sbin/nologin zabbixtar \-xzf $ZABBIX\_SOFT;cd \`echo $ZABBIX\_SOFT\|sed 's/.tar.\*//g'\`./configure \-\-prefix\=/usr/local/zabbix \-\-enable\-server \-\-enable\-agent \-\-with\-mysql \-\-enable\-ipv6 \-\-with\-net\-snmp \-\-with\-libcurl \&\&make installif \[ $? \-eq 0 ];then ln \-s /usr/local/zabbix/sbin/zabbix\_\* /usr/local/sbin/ficd \- ;cd zabbix\-3\.2\.6cp misc/init.d/tru64/{zabbix\_agentd,zabbix\_server} /etc/init.d/ ;chmod o\+x /etc/init.d/zabbix\_\*mkdir \-p /var/www/html/zabbix/;cp \-a frontends/php/\* /var/www/html/zabbix/\#config zabbix server cat \>$INSTALL\_DIR/etc/zabbix\_server.conf\<\<EOFLogFile\=/tmp/zabbix\_server.logDBHost\=localhostDBName\=zabbixDBUser\=zabbixDBPassword\=123456EOF\#config zabbix agentdcat \>$INSTALL\_DIR/etc/zabbix\_agentd.conf\<\<EOFLogFile\=/tmp/zabbix\_agentd.logServer\=$SERVER\_IPServerActive\=$SERVER\_IPHostname \= $IP EOF\#start zabbix agentd/etc/init.d/zabbix\_server restart/etc/init.d/zabbix\_agentd restart/etc/init.d/iptables stopsetenforce 0}AGENT\_INSTALL(){yum \-y install curl curl\-devel net\-snmp net\-snmp\-devel perl\-DBIgroupadd zabbix ;useradd \-g zabbix zabbix;usermod \-s /sbin/nologin zabbixtar \-xzf $ZABBIX\_SOFT;cd \`echo $ZABBIX\_SOFT\|sed 's/.tar.\*//g'\`./configure \-\-prefix\=/usr/local/zabbix \-\-enable\-agent\&\&make installif \[ $? \-eq 0 ];then ln \-s /usr/local/zabbix/sbin/zabbix\_\* /usr/local/sbin/ficd \- ;cd zabbix\-3\.2\.6cp misc/init.d/tru64/zabbix\_agentd /etc/init.d/zabbix\_agentd ;chmod o\+x /etc/init.d/zabbix\_agentd\#config zabbix agentdcat \>$INSTALL\_DIR/etc/zabbix\_agentd.conf\<\<EOFLogFile\=/tmp/zabbix\_agentd.logServer\=$SERVER\_IPServerActive\=$SERVER\_IPHostname \= $IP EOF\#start zabbix agentd/etc/init.d/zabbix\_agentd restart/etc/init.d/iptables stopsetenforce 0}read \-p "Please confirm whether to install Zabbix Server,yes or no? " INPUTif \[ $INPUT \=\= "yes" \-o $INPUT \=\= "y" ];then SERVER\_INSTALLelse AGENT\_INSTALLfi | | --- | ## Shell编程实战Nginx虚拟主机 Nginx WEB服务器的最大特点在于Nginx常被用于负载均衡、反向代理,单台Nginx服务器配置多个虚拟主机,百台服务器配置N多虚拟主机,基于Shell脚本可以更加高效的配置虚拟主机及添加、管理。 Shell脚本实现Nginx自动安装及虚拟主机的维护,编写思路如下: * 脚本指定参数v1\.jfedu.net; * 创建v1\.jfedu.net同时创建目录/var/www/v1; * 将Nginx虚拟主机配置定向到新的目录; * 重复虚拟主机不再添加。 Shell脚本实现Nginx自动安装及虚拟主机的维护,代码如下: | \#!/bin/bash\#Auto config Nginx virtual Hosts \#By author jfedu.net 2022\#Define Path variablesNGINX\_CONF\="/usr/local/nginx/conf/"NGINX\_MAKE\="\-\-user\=www \-\-group\=www \-\-prefix\=/usr/local/nginx \-\-with\-http\_stub\_status\_module \-\-with\-http\_ssl\_module"NGINX\_SBIN\="/usr/local/nginx/sbin/nginx"NGINX\_INSTALL(){\#Install Nginx serverNGINX\_FILE\=nginx\-1\.12\.0\.tar.gzNGINX\_DIR\=\`echo $NGINX\_FILE\|sed 's/.tar\*.\*//g'\`if \[ ! \-e /usr/local/nginx/ \-a ! \-e /etc/nginx/ ];then pkill nginx wget \-c http://nginx.org/download/$NGINX\_FILE yum install pcre\-devel pcre \-y rm \-rf $NGINX\_DIR ;tar xf $NGINX\_FILE cd $NGINX\_DIR;useradd www;./configure $NGINX\_MAKE make \&\&make install grep \-vE "\#\|^$" $NGINX\_CONF/nginx.conf \>$NGINX\_CONF/nginx.conf.swp \\mv $NGINX\_CONF/nginx.conf.swp $NGINX\_CONF/nginx.conf for i in \`seq 1 6\`;do sed \-i '$d' $NGINX\_CONF/nginx.conf;done echo "}" \>\>$NGINX\_CONF/nginx.conf cd ../fi}NGINX\_CONFIG(){\#config tomcat nginx vhostsgrep "include domains" $NGINX\_CONF/nginx.conf \>\>/dev/nullif \[ $? \-ne 0 ];then \#sed \-i '$d' $NGINX\_CONF/nginx.conf echo \-e "\\ninclude domains/\*;\\n}" \>\>$NGINX\_CONF/nginx.conf mkdir \-p $NGINX\_CONF/domains/fiVHOSTS\=$1ls $NGINX\_CONF/domains/$VHOSTS\>\>/dev/null 2\>\&1if \[ $? \-ne 0 ];then \#cp \-r xxx.jfedu.net $NGINX\_CONF/domains/$VHOSTS \#sed \-i "s/xxx/$VHOSTS/g" $NGINX\_CONF/domains/$VHOSTS cat\>$NGINX\_CONF/domains/$VHOSTS\<\<EOF \#vhost server $VHOSTS server { listen 80; server\_name $VHOSTS; location / { root /data/www/$VHOSTS/; index index.html index.htm; } }EOF mkdir \-p /data/www/$VHOSTS/ cat\>/data/www/$VHOSTS/index.html\<\<EOF \<html\> \<h1\>\<center\>The First Test Nginx page.\</center\>\</h1\> \<hr color\="red"\> \<h2\>\<center\>$VHOSTS\</center\>\</h2\> \</html\>EOF echo \-e "\\033\[32mThe $VHOSTS Config success,You can to access http://$VHOSTS/\\033\[0m" NUM\=\`ps \-ef \|grep nginx\|grep \-v grep\|grep \-v auto\|wc \-l\` $NGINX\_SBIN \-t \>\>/dev/null 2\>\&1 if \[ $? \-eq 0 \-a $NUM \-eq 0 ];then $NGINX\_SBIN else $NGINX\_SBIN \-t \>\>/dev/null 2\>\&1 if \[ $? \-eq 0 ];then $NGINX\_SBIN \-s reload fi fielse echo \-e "\\033\[32mThe $VHOSTS has been config,Please exit.\\033\[0m"fi}if \[ \-z $1 ];then echo \-e "\\033\[32m\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\\033\[0m" echo \-e "\\033\[32mPlease enter sh $0 xx.jf.com.\\033\[0m" exit 0fiNGINX\_INSTALLNGINX\_CONFIG $1 | | --- | ## Shell编程实战Nginx、Tomcat脚本 Tomcat用于发布JSP WEB页面,根据企业实际需求,会在单台服务器配置N个Tomcat实例,同时手动将Tomcat创建后的实例加入至Nginx虚拟主机中,同时重启Nginx,开发Nginx、Tomcat自动创建Tomcat实例及Nginx虚拟主机管理脚本能让大大的减轻人工的干预,实现快速的交付。 Shell脚本实现Nginx自动安装、虚拟主机及自动将Tomcat加入至虚拟主机,编写思路如下: * 手动拷贝Tomcat与脚本一致目录(可自动修改); * 手动修改Tomcat端口为6001、7001、8001(可自动修改); * 脚本指定参数v1\.jfedu.net; * 创建v1\.jfedu.net Tomcat实例; * 修改Tomcat实例端口,保证Port唯一; * 将Tomcat实例加入Nginx虚拟主机; * 重复创建Tomcat实例,端口自动增加,并加入原Nginx虚拟主机,实现负载均衡; Shell脚本实现Nginx自动安装、虚拟主机及自动将Tomcat加入至虚拟主机,代码如下: | \#!/bin/bash\#Auto config Nginx and tomcat cluster\#By author jfedu.net 2022\#Define Path variablesNGINX\_CONF\="/usr/local/nginx/conf/"install\_nginx(){ NGINX\_FILE\=nginx\-1\.10\.2\.tar.gz NGINX\_DIR\=\`echo $NGINX\_FILE\|sed 's/.tar\*.\*//g'\` wget \-c http://nginx.org/download/$NGINX\_FILE yum install pcre\-devel pcre \-y rm \-rf $NGINX\_DIR ;tar xf $NGINX\_FILE cd $NGINX\_DIR;useradd www;./configure \-\-user\=www \-\-group\=www \-\-prefix\=/usr/local/nginx2 \-\-with\-http\_stub\_status\_module \-\-with\-http\_ssl\_module make \&\&make install cd ../}install\_tomcat(){ JDK\_FILE\="jdk1\.7\.0\_25\.tar.gz" JDK\_DIR\=\`echo $JDK\_FILE\|sed 's/.tar.\*//g'\` tar \-xzf $JDK\_FILE ;mkdir \-p /usr/java/ ;mv $JDK\_DIR /usr/java/ sed \-i '/JAVA\_HOME/d;/JAVA\_BIN/d;/JAVA\_OPTS/d' /etc/profile cat \>\> /etc/profile \<\<EOF export JAVA\_HOME\=/export/servers/$JAVA\_DIR export JAVA\_BIN\=/export/servers/$JAVA\_DIR/bin export PATH\=\\$JAVA\_HOME/bin:\\$PATH export CLASSPATH\=.:\\$JAVA\_HOME/lib/dt.jar:\\$JAVA\_HOME/lib/tools.jar export JAVA\_HOME JAVA\_BIN PATH CLASSPATHEOF source /etc/profile;java \-version \#install tomcat start ls tomcat}config\_tomcat\_nginx(){ \#config tomcat nginx vhosts grep "include domains" $NGINX\_CONF/nginx.conf \>\>/dev/null if \[ $? \-ne 0 ];then sed \-i '$d' $NGINX\_CONF/nginx.conf echo \-e "\\ninclude domains/\*;\\n}" \>\>$NGINX\_CONF/nginx.conf mkdir \-p $NGINX\_CONF/domains/ fi VHOSTS\=$1 NUM\=\`ls /usr/local/\|grep \-c tomcat\` if \[ $NUM \-eq 0 ];then cp \-r tomcat /usr/local/tomcat\_$VHOSTS cp \-r xxx.jfedu.net $NGINX\_CONF/domains/$VHOSTS \#sed \-i "s/VHOSTS/$VHOSTS/g" $NGINX\_CONF/domains/$VHOSTS sed \-i "s/xxx/$VHOSTS/g" $NGINX\_CONF/domains/$VHOSTS exit 0 fi \#\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- \#VHOSTS\=$1 VHOSTS\_NUM\=\`ls $NGINX\_CONF/domains/\|grep \-c $VHOSTS\` SERVER\_NUM\=\`grep \-c "127" $NGINX\_CONF/domains/$VHOSTS\` SERVER\_NUM\_1\=\`expr $SERVER\_NUM \+ 1\` rm \-rf /tmp/.port.txt for i in \`find /usr/local/ \-maxdepth 1 \-name "tomcat\*"\`;do grep "port" $i/conf/server.xml \|egrep \-v "\\\-\-\|8080\|SSLEnabled"\|awk '{print $2}'\|sed 's/port\=//g;s/\\"//g'\|sort \-nr \>\>/tmp/.port.txt done MAX\_PORT\=\`cat /tmp/.port.txt\|grep \-v 8443\|sort \-nr\|head \-1\` PORT\_1\=\`expr $MAX\_PORT \- 2000 \+ 1\` PORT\_2\=\`expr $MAX\_PORT \- 1000 \+ 1\` PORT\_3\=\`expr $MAX\_PORT \+ 1\` if \[ $VHOSTS\_NUM \-eq 1 ];then read \-p "The $VHOSTS is exists,You sure create mulit Tomcat for the $VHOSTS? yes or no " INPUT if \[ $INPUT \=\= "YES" \-o $INPUT \=\= "Y" \-o $INPUT \=\= "yes" ];then cp \-r tomcat /usr/local/tomcat\_${VHOSTS}\_${SERVER\_NUM\_1} sed \-i "s/6001/$PORT\_1/g" /usr/local/tomcat\_${VHOSTS}\_${SERVER\_NUM\_1}/conf/server.xml sed \-i "s/7001/$PORT\_2/g" /usr/local/tomcat\_${VHOSTS}\_${SERVER\_NUM\_1}/conf/server.xml sed \-i "s/8001/$PORT\_3/g" /usr/local/tomcat\_${VHOSTS}\_${SERVER\_NUM\_1}/conf/server.xml sed \-i "/^upstream/a server 127\.0\.0\.1:${PORT\_2} weight\=1 max\_fails\=2 fail\_timeout\=30s;" $NGINX\_CONF/domains/$VHOSTS exit 0 fi exit fi cp \-r tomcat /usr/local/tomcat\_$VHOSTS cp \-r xxx.jfedu.net $NGINX\_CONF/domains/$VHOSTS sed \-i "s/VHOSTS/$VHOSTS/g" $NGINX\_CONF/domains/$VHOSTS sed \-i "s/xxx/$VHOSTS/g" $NGINX\_CONF/domains/$VHOSTS sed \-i "s/7001/${PORT\_2}/g" $NGINX\_CONF/domains/$VHOSTS \#\#\#\#\#\#\#config tomcat sed \-i "s/6001/$PORT\_1/g" /usr/local/tomcat\_${VHOSTS}/conf/server.xml sed \-i "s/7001/$PORT\_2/g" /usr/local/tomcat\_${VHOSTS}/conf/server.xml sed \-i "s/8001/$PORT\_3/g" /usr/local/tomcat\_${VHOSTS}/conf/server.xml}if \[ ! \-d $NGINX\_CONF \-o ! \-d /usr/java/$JDK\_DIR ];then install\_nginx install\_tomcatficonfig\_tomcat\_nginx $1 | | --- | ## Shell编程实战Docker管理脚本 Docker虚拟化是目前主流的虚拟化解决方案,越来越多的企业在使用Docker轻量级虚拟化,构建、维护和管理Docker虚拟化平台是运维人员非常重要的一个环节,开发Docker Shell脚本可以在命令行界面快速管理和维护Docker。 Shell脚本实现Docker自动安装、自动导入镜像、创建虚拟机、指定IP地址、将创建的Docker虚拟机加入Excel存档或者加入MYSQL数据库,编写思路如下: * 基于CentOS6\.5\+或者7\.x YUM安装Docker; * Docker脚本参数指定CPU、内存、硬盘容量; * Docker自动检测局域网IP并赋予Docker虚拟机; * Docker基于pipework指定IP; * 将创建的Docker虚拟机加入至CSV(Excel)或者MYSQL库; Shell脚本实现Docker自动安装、自动导入镜像、创建虚拟机、指定IP地址、将创建的Docker虚拟机加入CSV(Excel)存档或者加入MYSQL数据库,代码如下: | \#!/bin/bash\#Auto install docker and Create VM\#By author jfedu.net 2022\#Define Path variablesIPADDR\=\`ifconfig\|grep \-E "\\\<inet\\\>"\|awk '{print $2}'\|grep "192\.168"\|head \-1\`GATEWAY\=\`route \-n\|grep "UG"\|awk '{print $2}'\|grep "192\.168"\|head \-1\`IPADDR\_NET\=\`ifconfig\|grep \-E "\\\<inet\\\>"\|awk '{print $2}'\|grep "192\.168"\|head \-1\|awk \-F. '{print $1"."$2"."$3"."}'\`LIST\="/root/docker\_vmlist.csv"if \[ ! \-f /usr/sbin/ifconfig ];then yum install net\-tools\* \-yfifor i in \`seq 1 253\`;do ping \-c 1 ${IPADDR\_NET}${i} ;\[ $? \-ne 0 ]\&\& DOCKER\_IPADDR\="${IPADDR\_NET}${i}" \&\&break;done \>\>/dev/null 2\>\&1echo "\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#"echo \-e "Dynamic get docker IP,The Docker IP address\\n\\n$DOCKER\_IPADDR"NETWORK\=( HWADDR\=\`ifconfig eth0\|grep ether\|awk '{print $2}'\` IPADDR\=\`ifconfig eth0\|grep \-E "\\\<inet\\\>"\|awk '{print $2}'\` NETMASK\=\`ifconfig eth0\|grep \-E "\\\<inet\\\>"\|awk '{print $4}'\` GATEWAY\=\`route \-n\|grep "UG"\|awk '{print $2}'\`)if \[ \-z "$1" \-o \-z "$2" ];then echo \-e "\\033\[32m\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\\033\[0m" echo \-e "\\033\[32mPlease exec $0 CPU(C) MEM(G),example $0 4 8\\033\[0m" exit 0fi\#CPU\=\`expr $2 \- 1\`if \[ ! \-e /usr/bin/bc ];then yum install bc \-y \>\>/dev/null 2\>\&1fiCPU\_ALL\=\`cat /proc/cpuinfo \|grep processor\|wc \-l\`if \[ ! \-f $LIST ];then CPU\_COUNT\=$1 CPU\_1\="0" CPU1\=\`expr $CPU\_1 \+ 0\` CPU2\=\`expr $CPU1 \+ $CPU\_COUNT \- 1\` if \[ $CPU2 \-gt $CPU\_ALL ];then echo \-e "\\033\[32mThe System CPU count is $CPU\_ALL,not more than it.\\033\[0m" exit fielse CPU\_COUNT\=$1 CPU\_1\=\`cat $LIST\|tail \-1\|awk \-F"," '{print $4}'\|awk \-F"\-" '{print $2}'\` CPU1\=\`expr $CPU\_1 \+ 1\` CPU2\=\`expr $CPU1 \+ $CPU\_COUNT \- 1\` if \[ $CPU2 \-gt $CPU\_ALL ];then echo \-e "\\033\[32mThe System CPU count is $CPU\_ALL,not more than it.\\033\[0m" exit fifiMEM\_F\=\`echo $2 \\\* 1024\|bc\`MEM\=\`printf "%.0f\\n" $MEM\_F\`DISK\=20USER\=$3REMARK\=$4ping $DOCKER\_IPADDR \-c 1 \>\>/dev/null 2\>\&1if \[ $? \-eq 0 ];then echo \-e "\\033\[32m\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\\033\[0m" echo \-e "\\033\[32mThe IP address to be used,Please change other IP,exit.\\033\[0m" exit 0fiif \[ ! \-e /usr/bin/docker ];then yum install docker\* device\-mapper\* \-y mkdir \-p /export/docker/ cd /var/lib/ ;rm \-rf docker ;ln \-s /export/docker/ . mkdir \-p /var/lib/docker/devicemapper/devicemapper dd if\=/dev/zero of\=/var/lib/docker/devicemapper/devicemapper/data bs\=1G count\=0 seek\=2000 service docker start if \[ $? \-ne 0 ];then echo "Docker install error ,please check." exit fifi cd /etc/sysconfig/network\-scripts/ mkdir \-p /data/backup/\`date \+%Y%m%d\-%H%M\` yes\|cp ifcfg\-eth\* /data/backup/\`date \+%Y%m%d\-%H%M\`/if \[ \-e /etc/sysconfig/network\-scripts/ifcfg\-br0 ];then echoelse cat \>ifcfg\-eth0 \<\<EOF DEVICE\=eth0 BOOTPROTO\=none ${NETWORK\[0]} NM\_CONTROLLED\=no ONBOOT\=yes TYPE\=Ethernet BRIDGE\="br0" ${NETWORK\[1]} ${NETWORK\[2]} ${NETWORK\[3]} USERCTL\=noEOF cat \>ifcfg\-br0 \<\<EOF DEVICE\="br0" BOOTPROTO\=none ${NETWORK\[0]} IPV6INIT\=no NM\_CONTROLLED\=no ONBOOT\=yes TYPE\="Bridge" ${NETWORK\[1]} ${NETWORK\[2]} ${NETWORK\[3]} USERCTL\=noEOF /etc/init.d/network restartfiecho 'Your can restart Ethernet Service: /etc/init.d/network restart !'echo '\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-'cd \-\#\#\#\#\#\#\#create docker containerservice docker status \>\>/dev/nullif \[ $? \-ne 0 ];then service docker restartfiNAME\="Docker\_\`echo $DOCKER\_IPADDR\|awk \-F"." '{print $(NF\-1\)"\_"$NF}'\`"IMAGES\=\`docker images\|grep \-v "REPOSITORY"\|grep \-v "none"\|grep "jfedu"\|head \-1\|awk '{print $1}'\`if \[ \-z $IMAGES ];then echo "Plesae Download Docker Centos Images,you can to be use docker search centos,and docker pull centos6\.5\-ssh,exit 0" if \[ ! \-f jfedu\_centos68\.tar ];then echo "Please upload jfedu\_centos68\.tar for docker server." exit fi cat jfedu\_centos68\.tar\|docker import \- jfedu\_centos6\.8fiIMAGES\=\`docker images\|grep \-v "REPOSITORY"\|grep \-v "none"\|grep "jfedu"\|head \-1\|awk '{print $1}'\`CID\=$(docker run \-itd \-\-privileged \-\-cpuset\-cpus\=${CPU1}\-${CPU2} \-m ${MEM}m \-\-net\=none \-\-name\=$NAME $IMAGES /bin/bash)echo $CIDdocker ps \-a \|grep "$NAME"pipework br0 $NAME $DOCKER\_IPADDR/24@$IPADDRdocker exec $NAME /etc/init.d/sshd startif \[ ! \-e $LIST ];then echo "编号,容器ID,容器名称,CPU,内存,硬盘,容器IP,宿主机IP,使用人,备注" \>$LISTfi\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#NUM\=\`cat $LIST \|grep \-v CPU\|tail \-1\|awk \-F, '{print $1}'\`if \[\[ $NUM \-eq "" ]];then NUM\="1"else NUM\=\`expr $NUM \+ 1\`fi\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\# echo \-e "\\033\[32mCreate virtual client Successfully.\\n$NUM \`echo $CID\|cut \-b 1\-12\`,$NAME,$CPU1\-$CPU2,${MEM}M,${DISK}G,$DOCKER\_IPADDR,$IPADDR,$USER,$REMARK\\033\[0m"if \[ \-z $USER ];then USER\="NULL" REMARK\="NULL"fiecho $NUM,\`echo $CID\|cut \-b 1\-12\`,$NAME,$CPU1\-$CPU2,${MEM}M,${DISK}G,$DOCKER\_IPADDR,$IPADDR,$USER,$REMARK \>\>$LISTrm \-rf /root/docker\_vmlist\_\*iconv \-c \-f utf\-8 \-t gb2312 $LIST \-o /root/docker\_vmlist\_\`date \+%H%M\`.csv | | --- | ## Shell编程实战Bind管理脚本 Bind主要应用于企业DNS构建平台,而DNS用于将域名与IP进行解析,用户在浏览器只需输入域名,即可访问服务器IP地址的虚拟主机网站。 Bind难点在于创建各种记录,例如A记录、mail记录、反向记录、资源记录,基于Shell脚本可以减轻人工的操作,节省大量的时间成本。 Shell脚本实现Bind自动安装、初始化Bind环境、自动添加A记录、反向记录、批量添加A记录,编写思路如下: * YUM方式自动安装Bind; * 自动初始化Bind配置; * 创建安装、初始化、添加记录函数; * 自动添加单个A记录及批量添加A记录和反向记录; Shell脚本实现Bind自动安装、初始化Bind环境、自动添加A记录、反向记录、批量添加A记录,代码如下: | \#!/bin/bash\#Auto install config bind server\#By author jfedu.net 2022\#Define Path variablesBND\_ETC\=/var/named/chroot/etcBND\_VAR\=/var/named/chroot/var/namedBAK\_DIR\=/data/backup/dns\_\`date \+%Y%m%d\-%H%M\`\#\#Backup named serverif \[ ! \-d $BAK\_DIR ];then echo "Please waiting Backup Named Config ............" mkdir \-p $BAK\_DIR cp \-a /var/named/chroot/{etc,var} $BAK\_DIR cp \-a /etc/named.\* $BAK\_DIRfi\#\#Define Shell Install Function Install () { if \[ ! \-e /etc/init.d/named ];then yum install bind\* \-yelse echo \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- echo "The Named Server is exists ,Please exit ........." sleep 1 fi}\#\#Define Shell Init Function Init\_Config (){ sed \-i \-e 's/localhost;/any;/g' \-e '/port/s/127\.0\.0\.1/any/g' /etc/named.conf echo \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- sleep 2 echo "The named.conf config Init success !"}\#\#Define Shell Add Name Function Add\_named (){\#\#DNS name read \-p "Please Insert Into Your Add Name ,Example 51cto.com :" NAME echo $NAME \|grep \-E "com\|cn\|net\|org" while \[ "$?" \-ne 0 ] do read \-p "Please reInsert Into Your Add Name ,Example 51cto.com :" NAME echo $NAME \|grep \-E "com\|cn\|net\|org" done\#\# IP address read \-p "Please Insert Into Your Name Server IP ADDress:" IP echo $IP \|egrep \-o "(\[0\-9]{1,3}\\.){3}\[0\-9]{1,3}" while \[ "$?" \-ne "0" ] do read \-p "Please reInsert Into Your Name Server IP ADDress:" IP echo $IP \|egrep \-o "(\[0\-9]{1,3}\\.){3}\[0\-9]{1,3}" done ARPA\_IP\=\`echo $IP\|awk \-F. '{print $3"."$2"."$1}'\` ARPA\_IP1\=\`echo $IP\|awk \-F. '{print $4}'\` cd $BND\_ETC grep "$NAME" named.rfc1912\.zonesif \[ $? \-eq 0 ];then echo "The $NAME IS exist named.rfc1912\.zones conf ,please exit ..." exitelse read \-p "Please Insert Into SLAVE Name Server IP ADDress:" SLAVE echo $SLAVE \|egrep \-o "(\[0\-9]{1,3}\\.){3}\[0\-9]{1,3}" while \[ "$?" \-ne "0" ] do read \-p "Please Insert Into SLAVE Name Server IP ADDress:" SLAVE echo $SLAVE \|egrep \-o "(\[0\-9]{1,3}\\.){3}\[0\-9]{1,3}" done grep "rev" named.rfc1912\.zones if \[ $? \-ne 0 ];then cat \>\>named.rfc1912\.zones \<\<EOF\#\`date \+%Y\-%m\-%d\` Add $NAME CONFIG zone "$NAME" IN { type master; file "$NAME.zone"; allow\-update { none; };};zone "$ARPA\_IP.in\-addr.arpa" IN { type master; file "$ARPA\_IP.rev"; allow\-update { none; };};EOF else cat \>\>named.rfc1912\.zones \<\<EOF\#\`date \+%Y\-%m\-%d\` Add $NAME CONFIGzone "$NAME" IN { type master; file "$NAME.zone"; allow\-update { none; };};EOF fifi \[ $? \-eq 0 ]\&\& echo "The $NAME config name.rfc1912\.zones success !" sleep 3 ;echo "Please waiting config $NAME zone File ............." cd $BND\_VAR read \-p "Please insert Name DNS A HOST ,EXample www or mail :" HOST read \-p "Please insert Name DNS A NS IP ADDR ,EXample 192\.168\.111\.130 :" IP\_HOST echo $IP\_HOST \|egrep \-o "(\[0\-9]{1,3}\\.){3}\[0\-9]{1,3}" ARPA\_IP2\=\`echo $IP\_HOST\|awk \-F. '{print $3"."$2"."$1}'\` ARPA\_IP3\=\`echo $IP\_HOST\|awk \-F. '{print $4}'\` while \[ "$?" \-ne "0" ]do read \-p "Please Reinsert Name DNS A IPADDRESS ,EXample 192\.168\.111\.130 :" IP\_HOST echo $IP\_HOST \|egrep \-o "(\[0\-9]{1,3}\\.){3}\[0\-9]{1,3}"done cat \>$NAME.zone \<\<EOF\\$TTL 86400@ IN SOA localhost. root.localhost. ( 43 ; serial (d. adams) 1H ; refresh 15M ; retry 1W ; expiry 1D ) ; minimum IN NS $NAME.EOF REV\=\`ls \*.rev\` ls \*.rev \>\>/dev/nullif \[ $? \-ne 0 ];then cat \>\>$ARPA\_IP.rev \<\<EOF\\$TTL 86400@ IN SOA localhost. root.localhost. ( 1997022703 ; Serial 28800 ; Refresh 14400 ; Retry 3600000 ; Expire 86400 ) ; Minimum IN NS $NAME.EOF echo "$HOST IN A $IP\_HOST" \>\>$NAME.zone echo "$ARPA\_IP3 IN PTR $HOST.$NAME." \>\>$ARPA\_IP.rev \[ $? \-eq 0 ]\&\& echo \-e "The $NAME config success:\\n$HOST IN A $IP\_HOST\\n$ARPA\_IP3 IN PTR $HOST.$NAME." else sed \-i "9a IN NS $NAME." $REV echo "$HOST IN A $IP\_HOST" \>\>$NAME.zone echo "$ARPA\_IP3 IN PTR $HOST.$NAME." \>\>$REV \[ $? \-eq 0 ]\&\& echo \-e "The $NAME config success1:\\n$HOST IN A $IP\_HOST\\n$ARPA\_IP3 IN PTR $HOST.$NAME." fi}\#\#Define Shell List A Function Add\_A\_List (){if cd $BND\_VAR REV\=\`ls \*.rev\` read \-p "Please Insert Into Your Add Name ,Example 51cto.com :" NAME \[ ! \-e "$NAME.zone" ];then echo "The $NAME.zone File is not exist ,Please ADD $NAME.zone File :" Add\_named ;else read \-p "Please Enter List Name A NS File ,Example /tmp/name\_list.txt: " FILE if \[ \-e $FILE ];then for i in \`cat $FILE\|awk '{print $2}'\|sed "s/$NAME//g"\|sed 's/\\.$//g'\` \#for i in \`cat $FILE\|awk '{print $1}'\|sed "s/$NAME//g"\|sed 's/\\.$//g'\`do j\=\`awk \-v I\="$i.$NAME" '{if(I\=\=$2\)print $1}' $FILE\` echo \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- echo "The $NAME.zone File is exist ,Please Enter insert NAME HOST ...." sleep 1 ARPA\_IP\=\`echo $j\|awk \-F. '{print $3"."$2"."$1}'\` ARPA\_IP2\=\`echo $j\|awk \-F. '{print $4}'\` echo "$i IN A $j" \>\>$NAME.zone echo "$ARPA\_IP2 IN PTR $i.$NAME." \>\>$REV \[ $? \-eq 0 ]\&\& echo \-e "The $NAME config success:\\n$i IN A $j\\n$ARPA\_IP2 IN PTR $i.$NAME." done else echo "The $FILE List File IS Not Exist .......,Please exit ..." fifi}\#\#Define Shell Select Menu PS3\="Please select Menu Name Config: "select i in "自动安装Bind服务" "自动初始化Bind配置" "添加解析域名" "批量添加A记录" docase $i in "自动安装Bind服务") Install;; "自动初始化Bind配置") Init\_Config;; "添加解析域名") Add\_named;; "批量添加A记录") Add\_A\_List;; \* ) echo \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- sleep 1 echo "Please exec: sh $0 { Install(1\) or Init\_Config(2\) or Add\_named(3\) or Add\_config\_A(4\) }" ;;esacdone | | --- | # 黑客攻防Linux服务器企业实战 从各大云服务器厂商购买的云主机,通常都有外网IP地址,用户名和密码,通过CRT或者Xshell可以远程登录服务器的22端口。 每天大量的黑客通过各种工具,扫描登录你的服务器的22端口,企图以用户名和密码一直循环登录你的服务器,如果服务器的密码复杂度不够的话,被黑客拿到root或者其他普通用户密码,整个服务器就裸奔在黑客的眼皮底下了。这样就变成了人为刀俎我为鱼肉! 基于DenyHosts工具可以阻止试图猜测SSH登录口令,该软件会分析/var/log/secure等日志文件,当发现同一IP在进行多次SSH密码尝试时就将客户的IP记录到/etc/hosts.deny文件,从而可以实现禁止该IP访问服务器。 ## 基于二进制方式安装DenyHosts yum install epel\-release \-y yum install denyhosts\* \-y ## DenyHosts配置目录详解 DenyHosts软件涉及的配置文件和目录非常繁多,如下为每个目录具体的功能详解: 该目录中主要存放计划任务,日志压缩、chkconfig 、service启动文件; | /etc/cron.d/denyhosts/etc/denyhosts.conf/etc/logrotate.d/denyhosts /etc/rc.d/init.d/denyhosts/etc/sysconfig/denyhosts | | --- | 如下目录主要存放 denyhosts 所拒绝及允许的一些主机信息: | /var/lib/denyhosts/allowed\-hosts/var/lib/denyhosts/allowed\-warned\-hosts/var/lib/denyhosts/hosts/var/lib/denyhosts/hosts\-restricted/var/lib/denyhosts/hosts\-root/var/lib/denyhosts/hosts\-valid/var/lib/denyhosts/offset/var/lib/denyhosts/suspicious\-logins/var/lib/denyhosts/sync\-hosts/var/lib/denyhosts/users\-hosts/var/lib/denyhosts/users\-invalid/var/lib/denyhosts/users\-valid/var/log/denyhosts | | --- | ## DenyHosts配置实战 egrep \-vE "^$\|^\#" /etc/denyhosts.conf | \#系统安全日志文件,主要获取ssh信息SECURE\_LOG \= /var/log/secure\# 拒绝写入IP文件 hosts.denyHOSTS\_DENY \= /etc/hosts.deny\#过多久后清除已经禁止的,其中w代表周,d代表天,h代表小时,s代表秒,m代表分钟PURGE\_DENY \= 4w\# denyhosts所要阻止的服务名称BLOCK\_SERVICE \= sshd\# 允许无效用户登录失败的次数DENY\_THRESHOLD\_INVALID \= 3\# 允许普通用户登录失败的次数DENY\_THRESHOLD\_VALID \= 3\# 允许ROOT用户登录失败的次数DENY\_THRESHOLD\_ROOT \= 3\# 设定 deny host 写入到该资料夹DENY\_THRESHOLD\_RESTRICTED \= 1\# 将deny的host或ip纪录到Work\_dir中 WORK\_DIR \= /var/lib/denyhostsSUSPICIOUS\_LOGIN\_REPORT\_ALLOWED\_HOSTS\=YES\# 是否做域名反解HOSTNAME\_LOOKUP\=YES\# 将DenyHOts启动的pid纪录到LOCK\_FILE中,已确保服务正确启动,防止同时启动多个服务LOCK\_FILE \= /var/lock/subsys/denyhosts\#\#\#\#\#\#\#\#\#\#\#\#\# 管理员Mail地址ADMIN\_EMAIL \= rootSMTP\_HOST \= localhostSMTP\_PORT \= 25SMTP\_FROM \= DenyHosts \<nobody@localhost\>SMTP\_SUBJECT \= DenyHosts Report from $\[HOSTNAME]\# 有效用户登录失败计数归零的时间AGE\_RESET\_VALID\=5d\# ROOT用户登录失败计数归零的时间AGE\_RESET\_ROOT\=25d\# 用户的失败登录计数重置为0的时间(/usr/share/denyhosts/restricted\-usernames)AGE\_RESET\_RESTRICTED\=25d\# 无效用户登录失败计数归零的时间AGE\_RESET\_INVALID\=10dDAEMON\_LOG \= /var/log/denyhostsDAEMON\_SLEEP \= 30s\# 该项与PURGE\_DENY 设置成一样,也是清除hosts.deniedssh 用户的时间DAEMON\_PURGE \= 1h | | --- | ## 启动DenyHosts服务 service denyhosts restart ![](/media/202411/20241125143346427859.png) 分别测试 invalid、valid、root 三类用户设置不同的ssh连接失败次数,验证Denyhosts: 允许 invalid 用户只能失败5次、ROOT 用户失败4次、valid用户失败10次 | DENY\_THRESHOLD\_INVALID \= 5 DENY\_THRESHOLD\_VALID \= 10 DENY\_THRESHOLD\_ROOT \= 4 | | --- | ![](/media/202411/20241125143346434195.png) ## 删除被DenyHosts禁止IP 删除一个已经禁止的主机IP,在/etc/hosts.deny删除无效,还需进入/var/lib/denyhosts,进入以下操作: 1. 停止DenyHosts服务,service denyhosts stop; 2. /etc/hosts.deny 中删除被禁止的主机IP; 3. vi /var/lib/denyhosts,并且删除已被添加的主机信息; | /var/lib/denyhosts/hosts /var/lib/denyhosts/hosts\-restricted /var/lib/denyhosts/hosts\-root/var/lib/denyhosts/hosts\-valid /var/lib/denyhosts/users\-hosts /var/lib/denyhosts/users\-invalid /var/lib/denyhosts/users\-valid | | --- | 1. vi /var/lib/denyhosts/allowed\-hosts加入允许的IP即可; 2. 启动DenyHosts服务: service denyhosts restart 也可以通过SHELL指令批量解封: for i in \`ls /var/lib/denyhosts/\`;do sed \-i '/139\.199\.228\.59/d' /var/lib/denyhosts/$i;done sed \-i '/139\.199\.228\.59/d' /etc/hosts.deny echo "139\.199\.228\.59" \>\>/var/lib/denyhosts/allowed\-hosts ![](/media/202411/20241125143346440970.png) | \#!/bin/bash\#2022年7月15日21:38:32\#auto remove deny ip\#by author www.jfedu.net\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#DENY\_DIR\="/var/lib/denyhosts"DENY\_IP\=$1if \[ $\# \-eq 0 ];then echo \-e "\\033\[32m\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\\033\[0m" echo \-e "\\033\[32mUsage:{/bin/bash $0 1\.1\.1\.1\|192\.168\.1\.100\|help}\\033\[0m" exit 0fiif \[ $1 \=\= "help" ];then echo \-e "\\033\[32m\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\\033\[0m" echo \-e "\\033\[32mUsage:{/bin/bash $0 1\.1\.1\.1\|192\.168\.1\.100\|help}\\033\[0m" exit 1fifor i in \`ls $DENY\_DIR/\`do sed \-i "/$DENY\_IP/d" $DENY\_DIR/$idonesed \-i "/$DENY\_IP/d" /etc/hosts.denyecho "$DENY\_IP" \>\>$DENY\_DIR/allowed\-hostsecho \-e "\\033\[32m\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\\033\[0m"echo \-e "\\033\[32mThe Deny IP removed Success.\\033\[0m"service denyhosts restart | | --- | ## 配置Denyhosts发送报警邮件 vi /etc/denyhosts.conf,配置SMTP相关如下代码: | ADMIN\_EMAIL \= wgkgood@163\.comSMTP\_HOST \= smtp.163\.comSMTP\_PORT \= 25SMTP\_FROM \= wgkgood@163\.comSMTP\_PASSWORD\= jfedu6666 | | --- | ## 基于SHELL全自动脚本实现防黑客攻击 企业服务器暴露在外网,每天会有大量的人使用各种用户名和密码尝试登陆服务器,如果让其一直尝试,难免会猜出密码,通过开发Shell脚本,可以自动将尝试登陆服务器错误密码次数的IP列表加入到防火墙配置中。 Shell脚本实现服务器拒绝恶意IP登陆,编写思路如下: * 登陆服务器日志/var/log/secure; * 检查日志中认证失败的行并打印其IP地址; * 将IP地址写入至防火墙; * 禁止该IP访问服务器SSH 22端口; * 将脚本加入Crontab实现自动禁止恶意IP; Shell脚本实现服务器拒绝恶意IP登陆,代码如下: | \#!/bin/bash\#Auto drop ssh failed IP address\#By author jfedu.net 2022\#Define Path variablesSEC\_FILE\=/var/log/secureIP\_ADDR\=\`awk '{print $0}' /var/log/secure\|grep \-i "fail"\| egrep \-o "(\[0\-9]{1,3}\\.){3}\[0\-9]{1,3}" \| sort \-nr \| uniq \-c \|awk '$1\>\=15 {print $2}'\`IPTABLE\_CONF\=/etc/sysconfig/iptablesechocat \<\<EOF\+\+\+\+\+\+\+\+\+\+\+\+\+\+welcome to use ssh login drop failed ip\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+\+EOFechofor ((j\=0;j\<\=6;j\+\+)) ;do echo \-n "\-";sleep 1 ;doneechofor i in \`echo $IP\_ADDR\`do cat $IPTABLE\_CONF \|grep $i \>/dev/nullif \[ $? \-ne 0 ];thensed \-i "/lo/a \-A INPUT \-s $i \-m state \-\-state NEW \-m tcp \-p tcp \-\-dport 22 \-j DROP" $IPTABLE\_CONFfidoneNUM\=\`find /etc/sysconfig/ \-name iptables \-a \-mmin \-1\|wc \-l\` if \[ $NUM \-eq 1 ];then /etc/init.d/iptables restart fi | | --- | # 企业邮件入门简介 邮件服务器是一种用来负责[电子邮件](http://baike.baidu.com/view/1524.htm" \t "_blank)收发管理的设备。自主构建邮件服务器比网络上的免费邮箱更安全和高效,因此邮件服务器是每个公司必备的服务软件之一。对于运维SA需要掌握服务器相关的知识以及维护方法。 邮件服务器构成了电子[邮件系统](http://baike.baidu.com/view/1677840.htm" \t "_blank)的核心,每个收信人都有一个位于某个邮件服务器上的邮箱(mailbox),一个邮件消息的典型旅程是从发信人的[用户代理](http://baike.baidu.com/view/1510829.htm" \t "_blank)开始,邮件发信人的邮件服务器,中转到收信人的邮件服务器,然后投递到收信人的邮箱中。 简单邮件传送协议(Simple Mail Transfer Protocol,SMTP)是因特网电子邮件系统首要的应用层协议。它使用由TCP提供的可靠的数据传输服务把邮件消息从发信人的邮件服务器传送到收信人的邮件服务器。 为使用户的系统域名能被正确解析为相应服务器地址,邮件服务器需要能够在互联网络上被识别和查找到。这样邮件系统才能实现邮件的投递和接收。因此邮件服务器需要对此做DNS设置,包括MX记录和A记录的设置。 整个邮件系统包括:服务器端和客户端,服务器需要基于SMTP协议,客户端基于POP3、IMAP等协议。SMTP监听端口为TCP 25端口,POP3监听端口为110,IMAP监听端口为143。 例如当发送一封电子邮件信息时,信息会一台[服务器](http://www.07net01.com/tags-%E6%9C%8D%E5%8A%A1%E5%99%A8-0.html" \t "_blank)、一台服务器地的被传递,直到发送到收件人的电子邮件服务器。 更准确地说,信息被发送到负责传输邮件的服务器(被称为邮件传输代理(Mail Transport Agent,MTA),经过若干MTA后,最终到达收件人的MTA。在[互联网](http://www.07net01.com/tags-%E4%BA%92%E8%81%94%E7%BD%91-0.html" \t "_blank)上,MTA之间使用SMTP协议进行通信,也称为SMTP服务器。 收件人的MTA会将电子邮件投递给邮件接收服务器(被称为邮件投递代理(Mail Delivery Agent,MDA),MDA会保存邮件并等待用户收取。MDA主要有两种协议:POP(Post [Office](http://www.07net01.com/tags-Office-0.html" \t "_blank) Protocol)、 ![说明: 59373300506211](/media/202411/20241125143346449861.png) 最简单比喻就是:MTA类似邮局,而MDA类似信箱,MDA [存储](http://www.07net01.com/storage_networking/" \t "_blank)邮件并等待收件人检查信箱。收件人不需要让发件人与收件人建立连接。为避免人们的邮件被其他人看到,MDA要验证用户名和密码才能访问。收取邮件的工作由一个叫做邮件用户代理(Mail User Agent,MUA)的[程序](http://www.07net01.com/tags-%E7%A8%8B%E5%BA%8F-0.html" \t "_blank)来完成。如果MUA是用户[电脑](http://www.07net01.com/tags-%E7%94%B5%E8%84%91-0.html" \t "_blank)或其他设备上的一个程序,则称它为邮件客户端(如 Mozilla Thunderbird,网易邮箱大师,foxmail,[微软](http://www.07net01.com/tags-%E5%BE%AE%E8%BD%AF-0.html" \t "_blank)的 Outlook)。 [POP3](http://help.163.com/09/1223/14/5R7P6CJ600753VB8.html?servCode=6010376):协议允许电子邮件客户端下载服务器上的邮件,但是在客户端的操作(如移动邮件、标记已读等),不会反馈到服务器上,比如通过客户端收取了邮箱中的3封邮件并移动到其他文件夹,邮箱服务器上的这些邮件是没有同时被移动的,所以有很多同学反馈使用foxmail客户端配置pop3收取邮件的时候,有时候非常快,而使用IMAP方式,收取打开邮件非常慢。 [IMAP](http://help.163.com/09/1223/14/5R7P6CJ600753VB8.html?servCode=6010376):协议提供webmail 与电子邮件客户端之间的双向通信,客户端的操作都会反馈到服务器上,对邮件进行的操作,服务器上的邮件也会做相应的动作。 目前主流免费邮箱服务商有:网易邮箱、QQ邮箱、新浪、搜狐邮箱等等。邮箱的选择,如果是个人甚至中小型公司的话,可以直接使用网易或者QQ企业邮箱。因为维护一个邮件服务器也是一项非常庞大的工程。 Linux平台开源免费的邮件服务器包括:Sendmail、Postfix、Qmail;而Windows平台主要为Exchange服务器(正版需要收费),如下章节主要实战基于Linux平台来构建企业独立的邮件服务器系统。 邮件相关名称概念理解,汇总如下: | MUA:用户代理端,即用户使用的写信、收信客户端软件;MTA:邮件传送端,即常说的邮件服务器,用于转发、收取用户邮件。MDA:邮件代理端,相当于MUA和MTA的中间人,可用于过滤垃圾邮件。POP:邮局协议,用于MUA连接服务器收取用户邮件,通信端口110。IMAP:互联网应用协议,功能较POP多,通信端口143。SMTP:简单邮件传送协议,MUA连接MTA或MTA连接MTA发送邮件使用此协议,通信端口25。 | | --- | ## Sendmail安装配置 作为Linux/UNIX下的老牌邮件服务器,Sendmail作为一种免费的邮件服务器软件,已被广泛的应用于各种服务器中,它在稳定性、可移植性、及确保没有bug等方面具有一定的特色,且可以在网络中搜索到大量的使用资料,是一款最经典的Linux系统下邮件服务器。 1. Sendmail环境版本 | 系统版本:CentOS 6\.8 64位 Sendmail版本:Sendmail\-8\.14Openwebmail版本:openwebmail\-2\.53\-6、openwebmail\-data\-2\.53\-6 | | --- | 1. SendMail安装 | yum install sendmail\* \-y | | --- | ![](/media/202411/20241125143346457560.png) ![](/media/202411/20241125143346462828.png) ![](/media/202411/20241125143346467975.png) 1. SendMail服务配置 配置sendmail.cf服务,通过local\-host\-names设置邮件服务器提供邮件服务的域名为jfteach.com(jingfengjiaoyu.com); | cp /etc/mail/sendmail.mc /etc/mail/sendmail.mc.backcp /etc/mail/sendmail.cf /etc/mail/sendmail.cf.backecho "jfteach.com" \>\>/etc/mail/local\-host\-names | | --- | 配置Sendmail监听服务器网卡地址为0\.0\.0\.0: | sed \-i 's/Addr\=127\.0\.0\.1/Addr\=0\.0\.0\.0/g' /etc/mail/sendmail.mc | | --- | 修改vi /etc/mail/sendmail.mc如下两行,开启SMTP所有的用户必须认证。 | Dnl TRUST\_AUTH\_MECH(\`EXTERNAL DIGEST\-MD5 CRAM\-MD5 LOGIN PLAIN’)dnl Dnl define(\`confAUTH\_MECHANISMS’, \`EXTERNAL GSSAPI DIGEST\-MD5 CRAM\-MD5 LOGIN PLAIN’)dnl | | --- | 修改为如下: | TRUST\_AUTH\_MECH(\`EXTERNAL DIGEST\-MD5 CRAM\-MD5 LOGIN PLAIN’)dnl define(\`confAUTH\_MECHANISMS’, \`EXTERNAL GSSAPI DIGEST\-MD5 CRAM\-MD5 LOGIN PLAIN’)dnl | | --- | 即去掉首行的dnl 。这样sendmail配置完毕。 Sendmail.mc文件修改完毕,使用m4命令生成sendmail.cf主配置文件: | m4 sendmail.mc \>sendmail.cf | | --- | ![](/media/202411/20241125143346474042.png) 1. 配置SMTP认证 Saslauthd服务作用,提供SMTP用户验证,检查用户名和密码是否正确,基于系统shadow文件来实现验证配置。 | service saslauthd restart | | --- | ## Dovecot服务配置 Dovecot是一个开源的 IMAP 和 POP3 [邮件服务器](http://baike.baidu.com/item/%E9%82%AE%E4%BB%B6%E6%9C%8D%E5%8A%A1%E5%99%A8/985736" \t "_blank),支持 Linux/Unix系统,作为IMAP和POP3服务器,Dovecot为邮件用户代理(MUA)提供了一种访问服务器上存储的邮件的方法。但是Dovecot并不负责从其他邮件服务器接收邮件。(类似MDA) Dovecot只是将已存储在邮件服务器上的邮件通过MUA显示出来,IMAP和POP3是用于连接MUA与邮件存储服务器的两种常见的协议。 | yum install dovecot\* \-y | | --- | 去掉/etc/dovecot.conf 如下行前面的\#号即可: | protocols \= imap pop3 lmtp | | --- | 1. 配置Dovecot禁止SSL,设置邮箱: | vim /etc/dovecot/conf.d/10\-ssl.confssl \= novim /etc/dovecot/conf.d/10\-auth.confdisable\_plaintext\_auth \= novim /etc/dovecot/conf.d/10\-mail.confmail\_location \= mbox:\~/mail:INBOX\=/var/mail/%u | | --- | 1. Sendmail配置完毕 Sendmail邮箱用户的建立,可以用客户端收发邮件即正常 | groupadd mailgroup useradd \-g mailgroup \-s /sbin/nologin jfeduecho 123456\|passwd \-\-stdin jfedumkdir \-p /home/jfedu/mail/.imap/INBOXchown \-R jfedu.jfedu /home/jfedu/ | | --- | | service sendmail restartservice dovecot restartservice saslauthd restart | | | ## Sendmail别名配置 Sendmail服务器中可以使用aliases机制实现邮件别名和邮件群发功能,也可以创建用户组,将用户加入某个组中,实现组邮件的群发。 /etc/下存在aliases和aliases.db的两个文件,aliases文件是文本文件,其内容是可阅读和编辑的,aliases.db是数据库文件,是由aliases文件生成而来的。/etc/aliases文件中添加如下代码: | jfedu: jf1,jf2 | | --- | 给jfedu@jfteach.com发送邮件,[则群发到jf1@jfteach.com,jf2@jfteach.com](mailto:则群发到jf1@jfteach.com,jf2@jfteach.com),设置完成之后,通过newaliases指令生成新的aliases.db文件。 ## 测试邮件收发 MAIL命令发送邮件和收取邮件如下图(前提是能ping通jfteach.com域名,可以添加hosts或者映射DNS): | echo "This first test Mail"\|mail \-s "Test Mail Postfix" [jfedu1@jfteach.com](mailto:jfedu1@jfteach.com) | | --- | 查看并收取邮件: ![](/media/202411/20241125143346486445.png) ![](/media/202411/20241125143346491755.png) 基于Foxmail邮件收发 ![](/media/202411/20241125143346497462.png) ## 配置Openwebmail 如上配置完Sendmail邮件服务器,可以通过Outlook、Foxmail收发邮件,如果需要WEB页面收发邮件,可以基于Openwebmail来实现。例如访问:http://mail.jfteach.com/,以用户名和密码登录,进行邮件的发送与收取,则需配置openwebmail软件,配置如下: 1. Openwebmail服务安装 | cd /etc/yum.repos.dwget \-q http://openwebmail.org/openwebmail/download/redhat/rpm/release/openwebmail.repoyum install openwebmail \-y | | --- | 1. Openwebmail配置: | yum install httpd httpd\-devel \-y/var/www/cgi\-bin/openwebmail/openwebmail\-tool.pl \-\-init | | --- | ![](/media/202411/20241125143346504405.png) ![](/media/202411/20241125143346509403.png) vi /var/www/cgi\-bin/openwebmail/etc/openwebmail.conf | domainnames jfteach.com default\_language zh\_CN.GB2312 default\_iconset Cool3D.Chinese.Simplified | | --- | /var/www/cgi\-bin/openwebmail/openwebmail\-tool.pl \-\-init 通过浏览器访问openwebmail,访问如图: ![](/media/202411/20241125143346514876.png) ![](/media/202411/20241125143346520437.png) ![](/media/202411/20241125143346525397.png) SendMail外网域名配置,配置方法如下: ![](/media/202411/20241125143346530428.png) ![](/media/202411/20241125143346535808.png) ![](/media/202411/20241125143346540803.png) ![](/media/202411/20241125143346547696.png) ![](/media/202411/20241125143346552932.png) 同时配置apache rewrite规则,开启访问mail.jfteach.com直接访问Openwebmail页面,规则添加如下: | RewriteEngine OnProxyPreserveHost OnRewriteRule ^/$ http://mail.jfteach.com/cgi\-bin/openwebmail/openwebmail.pl \[P,L,NC] | | --- | ![](/media/202411/20241125143346559312.png) ![](/media/202411/20241125143346564753.png) ## Postfix入门简介 Postfix是Wietse Venema在IBM的[GPL协议](http://baike.baidu.com/item/GPL%E5%8D%8F%E8%AE%AE" \t "_blank)之下开发的[MTA](http://baike.baidu.com/item/MTA" \t "_blank)(邮件传输代理)软件。Postfix是Wietse Venema想要为使用最广泛的[sendmail](http://baike.baidu.com/item/sendmail" \t "_blank)提供替代品的一个尝试。 在[Internet](http://baike.baidu.com/item/Internet" \t "_blank)世界中,大部分的电子邮件都是通过sendmail来投递的,大约有100万用户使用sendmail,每天投递上亿封邮件。这是一个让人吃惊的数字,Postfix试图更快、更容易管理、更安全,同时还与sendmail保持足够的兼容性。 ![](/media/202411/20241125143346570537.png) ## Postfix服务安装 | yum \-y install postfix\* | | --- | ![](/media/202411/20241125143346575961.png) ## Postfix服务器配置 编辑postfix主配置文件,vi /etc/postfix/main.cf 以下配置案例域名为:jfteach.com,邮件服务器主机名是mail.jfteach.com 1. **修改myhostname** myhostname \= mail.jfteach.com myhostname 参数即是邮件服务器的主机名称。 1. **修改mydomain** mydomain \= jfteach.com mydomain参数设定网域名称(Domain Name),主机名称通常都是在建立在网域名称之内,像是www.google.com则是网页服务,mail.google.com则会是邮件主机服务,通常网域名称都会是主机名称(Hostname)去掉第一个掉包含前面的文字部份,比如说www.google.com的Domain则是google.com 1. **修改myorigin** myorigin \= $mydomain myorigin是我们的邮件地址在”@”后面的文字内容,例如wugk@163\.com,163\.com则为Origin Name 1. **修改smtp监听端口** inet\_interfaces \= all inet\_interfaces 参数指定postfix系统监听的网络接口。Postfix预设只会监听来自于本机端的所传出的封包,必须使用上列设定,才可以传收所有来自于网路端的所有封包。 1. **修改 inet\_protocols** 修改Postfix的通讯协定,目前网路的协定主流有IPv4与IPv6,在大部份的情况下,我们都是利用IPv4在通讯的,如果你的Mail Server没有需要使用到IPv6,可以做以下的设定修改 inet\_protocols \= ipv4 1. **修改mydestination** mydestination \= $myhostname, localhost.$mydomain, localhost, $mydomain mydestination参数设定能够接收信件的主机名称,Postfix预设只能收到设定的Hostname与Domain Name以及本机端的信件,此步骤是再增加能收信件的网络名称。 1. **设定信任用户端** mynetworks \= 127\.0\.0\.0/8, 192\.168\.1\.0/24, hash:/etc/postfix/access mynetworks 参数设定信任的用户端,当要寄信时,会参考此值,若非信任的用户,则不会帮你的信件转到其它的MTA主机上。 1. **设定relay\_domain转发邮件域名** 规范可以relay 的MTA 主机位址(收发Mail的程序一般统称为邮件用户代理MUA(Mail User Agent)),通常这个都直接设为mydestination。 relay\_domains \= $mydestination 1. **设定邮件别名的路径** 检查”alias\_maps”设定是否为以下字串设定 alias\_maps \= hash:/etc/aliases 1. **设定指定邮件别名表资料库路径** 检查” alias\_ database”设定是否为以下字串设定 alias\_database \= hash:/etc/aliases 1. **执行以下命令** 用于设定邮件主机使用权限与过滤机制及邮件别名 \# postmap hash:/etc/postfix/access \# postalias hash:/etc/aliases 1. **重启postfix服务** 如上Postfix配置完毕,同样需要配置Dovecot及启动saslauthd服务,方可进行邮件的收发! | /etc/init.d/postfix restart/etc/init.d/saslauthd restart/etc/init.d/dovecot restart | | --- | 如下为完整Postfix邮件服务器main.cf配置代码: | queue\_directory \= /var/spool/postfixcommand\_directory \= /usr/sbindaemon\_directory \= /usr/libexec/postfixdata\_directory \= /var/lib/postfixmail\_owner \= postfixmyhostname \= mail.jfteach.com mydomain \= jfteach.com myorigin \= $mydomaininet\_interfaces \= allinet\_protocols \= ipv4 mydestination \= $myhostname, localhost.$mydomain, localhost, $mydomainunknown\_local\_recipient\_reject\_code \= 550mynetworks \= 0\.0\.0\.0/0relay\_domains \= $mydestinationalias\_maps \= hash:/etc/aliasesalias\_database \= hash:/etc/aliasesdebug\_peer\_level \= 2debugger\_command \= PATH\=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin ddd $daemon\_directory/$process\_name $process\_id \& sleep 5sendmail\_path \= /usr/sbin/sendmail.postfixnewaliases\_path \= /usr/bin/newaliases.postfixmailq\_path \= /usr/bin/mailq.postfixsetgid\_group \= postdrophtml\_directory \= nomanpage\_directory \= /usr/share/mansample\_directory \= /usr/share/doc/postfix\-2\.6\.6/samplesreadme\_directory \= /usr/share/doc/postfix\-2\.6\.6/README\_FILES | | --- | 测试邮件收发,如下图所示: ![](/media/202411/20241125143346585003.png) ![](/media/202411/20241125143346593786.png) ## Foxmail本地邮箱配置 1. Linux系统创建用户jfedu1、jfedu2,同时设置密码,命令如下: | useradd jfedu1 ;echo 123456\|passwd \-\-stdin jfedu1useradd jfedu2 ;echo 123456\|passwd \-\-stdin jfedu2mkdir \-p /home/jfedu1/mail/.imap/INBOX/mkdir \-p /home/jfedu2/mail/.imap/INBOX/chown \-R jfedu1\.jfedu1 /home/jfedu1/chown \-R jfedu2\.jfedu2 /home/jfedu2/ | | --- | 1. Dovecot Smtp验证设置: | vim /etc/dovecot/conf.d/10\-auth.confdisable\_plaintext\_auth \= novim /etc/dovecot/conf.d/10\-mail.confmail\_location \= mbox:\~/mail:INBOX\=/var/mail/%uvim /etc/dovecot/conf.d/10\-ssl.confssl \= no | | --- | 1. 重启postfix及dovecot服务: | /etc/init.d/postfix restart/etc/init.d/dovecot restart | | --- | 1. Foxmail客户端设置 ![](/media/202411/20241125143346600997.png) POP服务器及SMTP服务器:mail.jingfengjiaoyu.com ![](/media/202411/20241125143346719973.png) 发送邮件给wgkgood@163\.com,如图所示: ![](/media/202411/20241125143346738682.png) 登录wgkgood@163\.com邮箱收取邮件,如图所示: ![](/media/202411/20241125143346743855.png) 基于wgkgood@163\.com发送邮件给jfedu1@jingfengjiaoyu.com,收件如图所示: ![](/media/202411/20241125143346749009.png) ## Postfixadmin配置 Postfix一般管理均是基于命令行管理,对应运维人员来说比较麻烦,有没有postfix图形界面管理工具呢,而Postfixadmin就是为Postfix邮件服务器提供的图形界面管理工具,用它可以很方便的管理postfix服务器。 如下为Postfixadmin安装配置方法,由于Postfixadmin基于PHP语言编写,所以需要安装LAMP(LNMP、LEMP)环境,同时最新版本Postfixadmin需要PHP5\.4以上支持。 1. 安装LAMP及Postfixadmin软件; | rpm \-Uvh [http://repo.webtatic.com/yum/el6/latest.rpm](http://repo.webtatic.com/yum/el6/latest.rpm" \t "_blank)yum remove php\*yum install php56w.x86\_64 php56w\-cli.x86\_64 php56w\-common.x86\_64 php56w\-gd.x86\_64 php56w\-ldap.x86\_64 php56w\-mbstring.x86\_64 php56w\-mcrypt.x86\_64 php56w\-mysql.x86\_64 php56w\-pdo.x86\_64 \-yyum install httpd httpd\-devel httpd\-tools mysql mysql\-devel mysql\-server \-ywget [https://jaist.dl.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin\-3\.1/postfixadmin\-3\.1\.tar.gz](https://jaist.dl.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-3.1/postfixadmin-3.1.tar.gz)tar xzf postfixadmin\-3\.1\.tar.gz \-C /var/www/html/cd /var/www/html/mv postfixadmin\-3\.1/ postfixadminmkdir \-p /var/www/html/postfixadmin/templates\_cchmod \-R 777 /var/www/html/postfixadmin/templates\_cchown \-R root.root /var/www/html/ | | --- | 1. 修改Postfixadmin配置 将/var/www/html/postfixadmin/config.inc.php如下选项改成如下代码: | $CONF\['configured'] \= true; | | --- | 1. 创建postfix数据库 | create database postfix charset\=utf8;grant all on \*.\* to postfix@'localhost' identified by "postfixadmin";flush privileges; | | --- | 1. 创建postfixadmin管理员: 访问postfixadmin网页:[http://113\.209\.20\.234/postfixadmin/setup.php](http://113.209.20.234/postfixadmin/setup.php) ![](/media/202411/20241125143346757102.png) 修改config.inc.php配置文件,添加密码: | $CONF\['setup\_password'] \= 'c11c1f22771ecc03d4507f366aeead44:3300e64c1a1e11a446ca2e964dadd4468ec163d3'; | | --- | ![](/media/202411/20241125143346817475.png) ![](/media/202411/20241125143346822708.png) ![](/media/202411/20241125143346828548.png) ![](/media/202411/20241125143346834948.png) ![](/media/202411/20241125143346839923.png) ![](/media/202411/20241125143346844843.png) ## RoundCube GUI WEB配置 1. Roundcube Webmail安装配置 | wget [https://jaist.dl.sourceforge.net/project/roundcubemail/roundcubemail/1\.1\.4/roundcubemail\-1\.1\.4\-complete.tar.gz](https://jaist.dl.sourceforge.net/project/roundcubemail/roundcubemail/1.1.4/roundcubemail-1.1.4-complete.tar.gz)tar \-xzf roundcubemail\-1\.1\.4\-complete.tar.gzmv roundcubemail\-1\.1\.4 /var/www/html/webmail/yum install php56w\-dom epel\-release libmcrypt\* php56w\-intl php56w\-mbstring php56w\-ldap php56w\-mcrypt \-ysed \-i 's\#;date.timezone \=\#date.timezone \= PRC\#g' /etc/php.ini/etc/init.d/httpd restart | | --- | 1. 配置WEB MAIL: [http://113\.209\.20\.234/webmail/installer/index.php](http://113.209.20.234/webmail/installer/index.php) ![](/media/202411/20241125143346850422.png) ![](/media/202411/20241125143346855537.png) ![](/media/202411/20241125143346860626.png) ![](/media/202411/20241125143346865595.png) ![](/media/202411/20241125143346870284.png) ![](/media/202411/20241125143346875048.png) ![](/media/202411/20241125143346879961.png) ![](/media/202411/20241125143346885972.png) 1. 创建WEB MAIL数据库信息,命令如下: | create database roundcubemail charset\=utf8;grant all on \*.\* to roundcube@'localhost' identified by "roundcube";flush privileges;chmod 777 \-R temp/ logs/ | | --- | ![](/media/202411/20241125143346892387.png) ![](/media/202411/20241125143346897538.png) ![](/media/202411/20241125143346902749.png) ![](/media/202411/20241125143346907743.png) 1. 登录WEB控制台,登录失败: [http://113\.209\.20\.234/webmail/](http://113.209.20.234/webmail/) 输入jfedu1用户名和密码登录。 ![](/media/202411/20241125143346913063.png) 1. 查看Dovecot后台日志,如下错误: | Jun 30 18:34:58 imap\-login: Info: Disconnected (auth failed, 1 attempts): user\=\<jfedu1@jingfengjiaoyu.com\>, method\=PLAIN, rip\=113\.209\.20\.234, lip\=192\.168\.0\.3Jun 30 18:35:17 imap\-login: Info: Disconnected (auth failed, 1 attempts): user\=\<jfedu2@jingfengjiaoyu.com\>, method\=PLAIN, rip\=113\.209\.20\.234, lip\=192\.168\.0\.3 | | --- | 如上错误解决方法,在/etc/dovecot/dovecot.conf文件中,添加如下代码即可:(表示去掉用户后面其他信息,保留用户名称,例如jfedu1) auth\_username\_format \= %n ![](/media/202411/20241125143346918396.png) ![](/media/202411/20241125143346923878.png) 1. 创建测试邮件,如图所示: ![](/media/202411/20241125143346929559.png) 1. 登录163邮箱收取邮件,如图所示: ![](/media/202411/20241125143346936166.png) 1. 设置Roundcube Webmail界面风格: ![](/media/202411/20241125143346941218.png) ![](/media/202411/20241125143346946175.png) 1. WEBMAIL添加通讯录: ![](/media/202411/20241125143346951952.png) ![](/media/202411/20241125143346957574.png) 1. 创建垃圾邮件及已删除邮件夹: 通过RoundCube默认删除邮件,会报错,报错信息如下: UID COPY: Mailbox doesn't exist: Trash 基于Dovecot自动创建垃圾邮件及已删除邮件夹,代码如下: vim /etc/dovecot/conf.d/20\-imap.conf | mail\_plugins \= $mail\_plugins autocreateplugin { autocreate \= Trash autocreate2 \= Junk autocreate3 \= Drafts autocreate4 \= Sent autosubscribe \= Trash autosubscribe2 \= Junk autosubscribe3 \= Drafts autosubscribe4 \= Sent} | | --- | 重启dovecot服务即可。 ![](/media/202411/20241125143346964026.png) ![](/media/202411/20241125143346969762.png) 1. 删除Roundcube安装信息及设置禁止安装: | rm \-rf /var/www/html/webmail/installer/vim /var/www/html/webmail/config/config.inc.php添加如下代码:$config\['enable\_installer'] \= false;vim /etc/httpd/conf/httpd.conf加入如下代码:\<Directory "/var/www/html/webmail/installer/"\> Options Indexes FollowSymLinks AllowOverride None Order allow,deny Deny from all\</Directory\> | | --- | ![](/media/202411/20241125143346975870.png) 1. 实现域名访问邮件服务器 Apache配置文件httpd.conf末尾加入如下代码,重启apache访问webmail如图所示: | \<IfModule alias\_module\> Alias / /var/www/html/webmail/\</IfModule\> | | --- | ![](/media/202411/20241125143346982552.png) ![](/media/202411/20241125143346987805.png) ## Postfix虚拟用户配置 通过如上章节的配置,使用系统用户可以登录到postfix邮件服务器,并且进行邮件的发送和接收,为了管理的方便和系统安全,一般通过postfix虚拟用户来管理邮件用户的。 Postfix虚拟用户的原理:基于系统中创建的一个映射用户,该用户不能登录到系统,然后将其他虚拟用户全部映射到该系统用户所属目录。 对于操作系统来说所有的操作均是通过该系统用户进行的,但是对于postfix的邮件用户来说又是各自独立的。Postfix虚拟用户与Vsftpd虚拟用户相似,所有的虚拟用户或者系统用户可以通过Postfixadmin来进行管理。 1. 配置Postfix SMTP认证基于MYSQL数据库,读取MYSQL虚拟用户配置: 修改Postfix真实用户的uid和gid,命令如下: | usermod \-u 1000 postfixgroupmod \-g 1000 postfixchown \-R postfix.postfix /var/spool/mail/ | | --- | 1. 创建postfix主配置文件mail.cf内容为如下: | queue\_directory \= /var/spool/postfixcommand\_directory \= /usr/sbindaemon\_directory \= /usr/libexec/postfixdata\_directory \= /var/lib/postfixmail\_owner \= postfixmyhostname \= mail.jingfengjiaoyu.commydomain \= jingfengjiaoyu.commyorigin \= $mydomaininet\_interfaces \= allinet\_protocols \= ipv4\#mydestination \= localhost\#mydestination \= $myhostname,localhost.$mydomain,localhost,$mydomainunknown\_local\_recipient\_reject\_code \= 550\#mynetworks \= 192\.168\.0\.0/24,127\.0\.0\.0/8mynetworks \= 0\.0\.0\.0/0relay\_domains \= $mydestinationalias\_maps \= hash:/etc/aliasesalias\_database \= hash:/etc/aliasesdebug\_peer\_level \= 2debugger\_command \= PATH\=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin ddd $daemon\_directory/$process\_name $process\_id \& sleep 5sendmail\_path \= /usr/sbin/sendmail.postfixnewaliases\_path \= /usr/bin/newaliases.postfixmailq\_path \= /usr/bin/mailq.postfixsetgid\_group \= postdrophtml\_directory \= nomanpage\_directory \= /usr/share/mansample\_directory \= /usr/share/doc/postfix\-2\.6\.6/samplesreadme\_directory \= /usr/share/doc/postfix\-2\.6\.6/README\_FILES\#Config Virtual Mailbox Settings 2022virtual\_minimum\_uid \= 100virtual\_mailbox\_base \= /var/spool/mailvirtual\_mailbox\_maps \= mysql:/etc/postfix/mysql\_virtual\_mailbox\_maps.cfvirtual\_mailbox\_domains \= mysql:/etc/postfix/mysql\_virtual\_domains\_maps.cfvirtual\_alias\_domains \= $virtual\_alias\_mapsvirtual\_alias\_maps \= mysql:/etc/postfix/mysql\_virtual\_alias\_maps.cfvirtual\_uid\_maps \= static:1000virtual\_gid\_maps \= static:1000virtual\_transport \= virtualmaildrop\_destination\_recipient\_limit \= 1maildrop\_destination\_concurrency\_limit \= 1\#Config QUOTA 2022message\_size\_limit \= 52428800mailbox\_size\_limit \= 209715200virtual\_mailbox\_limit \= 209715200virtual\_create\_maildirsize \= yesvirtual\_mailbox\_extended \= yesvirtual\_mailbox\_limit\_maps \= mysql:/etc/postfix/mysql\_virtual\_mailbox\_limit\_maps.cfvirtual\_mailbox\_limit\_override \= yesvirtual\_maildir\_limit\_message \= Sorry, the user's maildir has overdrawn his diskspace quota, please try again later.virtual\_overquota\_bounce \= yes\#Config SASL 2022broken\_sasl\_auth\_clients \= yessmtpd\_recipient\_restrictions \= permit\_mynetworks,permit\_sasl\_authenticated,reject\_invalid\_hostname,reject\_non\_fqdn\_hostname,reject\_unknown\_sender\_domain,reject\_non\_fqdn\_sender,reject\_non\_fqdn\_recipient,reject\_unknown\_recipient\_domain,reject\_unauth\_pipelining,reject\_unauth\_destination,permitsmtpd\_sasl\_auth\_enable \= yessmtpd\_sasl\_type \= dovecotsmtpd\_sasl\_path \= /var/run/dovecot/auth\-clientsmtpd\_sasl\_local\_domain \= $myhostnamesmtpd\_sasl\_security\_options \= noanonymoussmtpd\_sasl\_application\_name \= smtpdsmtpd\_banner\=$myhostname SMTP "Version not Available" | | --- | 1. 创建POSTFIX读取MYSQL配置信息: | cat\>/etc/postfix/mysql\_virtual\_alias\_maps.cf\<\<EOFuser \= postfixpassword \= postfixhosts \= localhostdbname \= postfixtable \= aliasselect\_field \= gotowhere\_field \= addressEOF | | --- | | cat\>/etc/postfix/mysql\_virtual\_domains\_maps.cf\<\<EOFuser \= postfixpassword \= postfixhosts \= localhostdbname \= postfixtable \= domainselect\_field \= descriptionwhere\_field \= domainEOF | | cat\>/etc/postfix/mysql\_virtual\_mailbox\_limit\_maps.cf\<\<EOFuser \= postfixpassword \= postfixhosts \= localhostdbname \= postfixtable \= mailboxselect\_field \= quotawhere\_field \= usernameEOF | | cat\>/etc/postfix/mysql\_virtual\_mailbox\_maps.cf\<\<EOFuser \= postfixpassword \= postfixhosts \= localhostdbname \= postfixtable \= mailboxselect\_field \= maildirwhere\_field \= usernameEOF | | mysql\_virtual\_mailbox\_maps.cf:服务器邮箱文件的存储路径。mysql\_virtual\_domains\_maps.cf:邮件服务器上所有的虚拟域。mysql\_virtual\_alias\_maps.cf:邮件服务器上虚拟别名和实际邮件地址间的对应关系。mysql\_virtual\_mailbox\_limit\_maps.cf:服务器上邮箱的一些限制参数。如上配置文件可以供Postfix读取数据库表。默认是基于hash:/etc/aliases查询表,哈希文件,文件的路径是/etc/aliases。Postfix在需要的时候读取这些配置信息,然后根据这些配置信息的指示,到另外的文件或者数据库中去读取实际的数据。 | | --- | 1. 创建数据库并授权: | create database postfix charset\=utf8;grant all privileges on postfix.\* to postfix@'localhost' identified by "postfix";flush privileges; | | --- | 1. 修改postfixadmin配置文件数据库连接信息: ![](/media/202411/20241125143347000148.png) 1. 通过Postfixamin创建4个虚拟用户,如图所示: ![](/media/202411/20241125143347005443.png) 1. 配置Dovecot服务,修改dovecot.conf配置文件代码如下: | \#/etc/dovecot/dovecot.conf\#CentOS: Linux 2\.6\.32\#2022年7月1日09:53:30auth\_mechanisms \= PLAIN LOGIN\#auth\_mechanisms \= PLAIN LOGIN CRAM\-MD5 DIGEST\-MD5disable\_plaintext\_auth \= nofirst\_valid\_uid \= 1000listen \= \*mail\_location \= maildir:/var/spool/mail/%d/%nmanagesieve\_notify\_capability \= mailtomanagesieve\_sieve\_capability \= fileinto reject envelope encoded\-character vacation subaddress comparator\-i;ascii\-numeric relational regex imap4flags copy include variables body enotify environment mailbox datepassdb { args \= /etc/dovecot/mysql.conf driver \= sql}protocols \= imap pop3service auth { unix\_listener auth\-client { group \= postfix mode \= 0660 user \= postfix }}ssl \= nouserdb { args \= /etc/dovecot/mysql.conf driver \= sql} | | --- | 1. 创建Dovecot连接MYSQL认证,配置文件 /etc/dovecot/mysql.conf代码如下: | driver \= mysql connect \= host\=/var/lib/mysql/mysql.sock dbname\=postfix user\=postfix password\=postfixdefault\_pass\_scheme \= MD5password\_query \= SELECT password FROM mailbox WHERE username \= '%u'user\_query \= SELECT maildir, 1000 AS uid, 1000 AS gid FROM mailbox WHERE username \= '%u' | | --- | 1. 使用虚拟用户登录RoundCube,如图所示: ![](/media/202411/20241125143347012641.png) ![](/media/202411/20241125143347017783.png) ## Postfix\+Extmail配置实战 通过上面的部署我们已经完成了一个基本的邮件服务器系统,它能够发送、接收邮件,能够对用户进行身份验证等工作。用户可以使用Outlook、Foxmail、Roundcube等的工具来发送和接收邮件。 使用Roundcube WEB MAIL 页面功能相对比较少,可以使用Extmail实现WEB端邮件收取和发送。 Extmail 是一个以perl语言编写,面向大容量/ISP级应用,免费的高性能Webmail软件,ExtMail套件用于提供从浏览器中登录、使用邮件系统的Web操作界面,它以GPL版权释出,设计初衷是希望设计一个适应当前高速发展的IT应用环境,满足用户多变的需求,能快速进行开发、改进和升级,适应能力强的webmail系统。 对于国内的电子邮件系统来说,无论是从系统功能、易用性还是中文化等方面,ExtMail 平台都是一个相当不错的选择。Extmail 套件可以提供给普通邮件用户使用,而Extman套件可以提供给邮件系统的管理员使用。 Extmail配置 官网下载:extmail\-1\.2\.tar.gz WEB MAIL,解压安装: | tar \-zxf extmail\-1\.2\.tar.gzmkdir \-p /var/www/extsuitemv extmail\-1\.2 /var/www/extsuite/extmailcd /var/www/extsuite/extmail/cp webmail.cf.default webmail.cfyum install perl\-devel perl perl\-Unix\-Syslog \-y | | --- | 修改webmail.cf主配置文件 vim /var/www/extsuite/extmail/webmail.cf,配置代码如下: | SYS\_CONFIG \= /var/www/extsuite/extmail/SYS\_LANGDIR \= /var/www/extsuite/extmail/langSYS\_TEMPLDIR \= /var/www/extsuite/extmail/htmlSYS\_HTTP\_CACHE \= 0SYS\_SMTP\_HOST \= mail.jingfengjiaoyu.com SYS\_SMTP\_PORT \= 25SYS\_SMTP\_TIMEOUT \= 5SYS\_SPAM\_REPORT\_ON \= 0SYS\_SPAM\_REPORT\_TYPE \= dspamSYS\_SHOW\_WARN \= 0SYS\_IP\_SECURITY\_ON \= 1SYS\_PERMIT\_NOQUOTA \= 1SYS\_SESS\_DIR \= /tmpSYS\_UPLOAD\_TMPDIR \= /tmpSYS\_LOG\_ON \= 1SYS\_LOG\_TYPE \= syslogSYS\_LOG\_FILE \= /var/log/extmail.logSYS\_SESS\_TIMEOUT \= 0SYS\_SESS\_COOKIE\_ONLY \= 1SYS\_USER\_PSIZE \= 10SYS\_USER\_SCREEN \= autoSYS\_USER\_LANG \= en\_USSYS\_APP\_TYPE \= WebMailSYS\_USER\_TEMPLATE \= defaultSYS\_USER\_CHARSET \= utf\-8SYS\_USER\_TRYLOCAL \= 1SYS\_USER\_TIMEZONE \= \+0800SYS\_USER\_CCSENT \= 1SYS\_USER\_SHOW\_HTML \= 1SYS\_USER\_COMPOSE\_HTML \= 1SYS\_USER\_CONV\_LINK \=1SYS\_USER\_ADDR2ABOOK \= 1SYS\_MESSAGE\_SIZE\_LIMIT \= 5242880SYS\_MIN\_PASS\_LEN \= 2SYS\_MFILTER\_ON \= 1SYS\_NETDISK\_ON \= 1SYS\_SHOW\_SIGNUP \= 1SYS\_DEBUG\_ON \= 1SYS\_AUTH\_TYPE \= mysqlSYS\_MAILDIR\_BASE \= /var/spool/mail/SYS\_AUTH\_SCHEMA \= virtualSYS\_CRYPT\_TYPE \= md5cryptSYS\_MYSQL\_USER \= postfix SYS\_MYSQL\_PASS \= postfixSYS\_MYSQL\_DB \= postfixSYS\_MYSQL\_HOST \= localhostSYS\_MYSQL\_SOCKET \= /var/lib/mysql/mysql.sockSYS\_MYSQL\_TABLE \= mailboxSYS\_MYSQL\_ATTR\_USERNAME \= usernameSYS\_MYSQL\_ATTR\_DOMAIN \= domainSYS\_MYSQL\_ATTR\_PASSWD \= passwordSYS\_MYSQL\_ATTR\_CLEARPW \= clearpwdSYS\_MYSQL\_ATTR\_QUOTA \= quotaSYS\_MYSQL\_ATTR\_NDQUOTA \= netdiskquotaSYS\_MYSQL\_ATTR\_HOME \= homedirSYS\_MYSQL\_ATTR\_MAILDIR \= maildirSYS\_MYSQL\_ATTR\_DISABLEWEBMAIL \= disablewebmailSYS\_MYSQL\_ATTR\_DISABLENETDISK \= disablenetdiskSYS\_MYSQL\_ATTR\_DISABLEPWDCHANGE \= disablepwdchangeSYS\_MYSQL\_ATTR\_ACTIVE \= activeSYS\_MYSQL\_ATTR\_PWD\_QUESTION \= questionSYS\_MYSQL\_ATTR\_PWD\_ANSWER \= answerSYS\_LDAP\_BASE \= o\=extmailAccount,dc\=example.comSYS\_LDAP\_RDN \= cn\=Manager,dc\=example.comSYS\_LDAP\_PASS \= secretSYS\_LDAP\_HOST \= localhostSYS\_LDAP\_ATTR\_USERNAME \= mailSYS\_LDAP\_ATTR\_DOMAIN \= virtualDomainSYS\_LDAP\_ATTR\_PASSWD \= userPasswordSYS\_LDAP\_ATTR\_CLEARPW \= clearPasswordSYS\_LDAP\_ATTR\_QUOTA \= mailQuotaSYS\_LDAP\_ATTR\_NDQUOTA \= netdiskQuotaSYS\_LDAP\_ATTR\_HOME \= homeDirectorySYS\_LDAP\_ATTR\_MAILDIR \= mailMessageStoreSYS\_LDAP\_ATTR\_DISABLEWEBMAIL \= disablewebmailSYS\_LDAP\_ATTR\_DISABLENETDISK \= disablenetdiskSYS\_LDAP\_ATTR\_DISABLEPWDCHANGE \= disablePasswdChangeSYS\_LDAP\_ATTR\_ACTIVE \= activeSYS\_LDAP\_ATTR\_PWD\_QUESTION \= questionSYS\_LDAP\_ATTR\_PWD\_ANSWER \= answerSYS\_AUTHLIB\_SOCKET \= /var/spool/authdaemon/socketSYS\_G\_ABOOK\_TYPE \= fileSYS\_G\_ABOOK\_LDAP\_HOST \= localhostSYS\_G\_ABOOK\_LDAP\_BASE \= ou\=AddressBook,dc\=example.comSYS\_G\_ABOOK\_LDAP\_ROOTDN \= cn\=Manager,dc\=example.comSYS\_G\_ABOOK\_LDAP\_ROOTPW \= secretSYS\_G\_ABOOK\_LDAP\_FILTER \= objectClass\=OfficePersonSYS\_G\_ABOOK\_FILE\_PATH \= /var/www/extsuite/extmail/globabook.cfSYS\_G\_ABOOK\_FILE\_LOCK \= 1SYS\_G\_ABOOK\_FILE\_CONVERT \= 0SYS\_G\_ABOOK\_FILE\_CHARSET \= utf\-8 | | --- | 常用配置文件参数详解: | SYS\_MESSAGE\_SIZE\_LIMIT \= 5242880用户可以发送的最大邮件SYS\_USER\_LANG \= en\_US语言选项,可改作:SYS\_USER\_LANG \= zh\_CNSYS\_MAILDIR\_BASE \= /home/domains此处即为您在前文所设置的用户邮件的存放目录,可改作:SYS\_MAILDIR\_BASE \= /var/spool/mail/SYS\_MYSQL\_USER \= postfixSYS\_MYSQL\_PASS \= db\_pass以上两句句用来设置连接数据库服务器所使用用户名、密码和邮件服务器用到的数据库,这里修改为:SYS\_MYSQL\_USER \= postfixSYS\_MYSQL\_PASS \= postfixSYS\_MYSQL\_HOST \= localhost指明数据库服务器主机名,这里默认即可SYS\_MYSQL\_TABLE \= mailboxSYS\_MYSQL\_ATTR\_USERNAME \= usernameSYS\_MYSQL\_ATTR\_DOMAIN \= domainSYS\_MYSQL\_ATTR\_PASSWD \= password以上用来指定验正用户登录里所用到的表,以及用户名、域名和用户密码分别对应的表中列的名称;这里默认即可 | | --- | Apache配置文件httpd.conf设置方式一: | User postfixGroup postfix\<VirtualHost \*:80\>ServerName mail.jingfengjiaoyu.comDocumentRoot /var/www/extsuite/extmail/html/ScriptAlias /extmail/cgi /var/www/extsuite/extmail/cgiAlias /extmail /var/www/extsuite/extmail/html\</VirtualHost\> | | --- | Apache配置文件httpd.conf设置方式二: 由于Extmail要进行本地邮件的投递操作,须将运行apache服务器用户的身份修改为邮件投递代理的用户,本案例为postfix;开启apache服务器的suexec功能,使用如下方法实现虚拟主机运行身份的指定。 | \<VirtualHost \*:80\>ServerName mail.jingfengjiaoyu.comDocumentRoot /var/www/extsuite/extmail/html/ScriptAlias /extmail/cgi /var/www/extsuite/extmail/cgiAlias /extmail /var/www/extsuite/extmail/htmlSuexecUserGroup postfix postfix\</VirtualHost\> | | --- | 浏览器访问Extmail,截图如下: ![](/media/202411/20241125143347029811.png) ![](/media/202411/20241125143347035046.png) ![](/media/202411/20241125143347039873.png) ## Postfix\+Extman配置实战 Extmail [WebMail](http://wiki.extmail.org/webmail" \o "webmail)推出之后,缺少一个与之配套的邮件虚拟域和账号管理的后台。虽然目前已经有不少类似的软件,其中也不乏非常优秀的产品,例如postfixadmin等,但是没有任何一款可以不经修改的为我所用,再加上编程语言和系统兼容性方面的考虑,我们推出了Extman系统。顾名思义,Extman就是Extmail Management的意思。有了他,Extmail Webmail的用户可以方便的管理Extmail邮件系统。后来由于需要,又增加了图形化日志监控等等新的功能,从而形成了今天大家看到的Extman。 Extman是Extmail项目组在推出Extmail [WebMail](http://wiki.extmail.org/webmail" \o "webmail)之后,推出的一个用来管理Extmail虚拟账号的管理软件。 使用Perl语言编写,目前支持[MySQL](http://wiki.extmail.org/mysql" \o "mysql)和[OpenLDAP](http://wiki.extmail.org/openldap" \o "openldap)作为账号信息存储源,新的存储源支持正在开发之中。 它可以使你通过浏览器轻松的管理您在Extmail系统中的虚拟域和账号信息。同时还加入了图形化日志监控工具,使邮局的管理更加方便。 | tar xzf extman\-1\.1\.tar.gz \-C /var/www/extsuite/cd /var/www/extsuite/mv extman\-1\.1 extmanchown \-R postfix.postfix /var/www/extsuite/extman/cgi/cd extman/cp webman.cf.default webman.cfmkdir \-p /tmp/extmanchown postfix.postfix /tmp/extmanyum install perl\-rrdtool\* \-y | | --- | 创建extman所需数据库: | cd /var/www/extsuite/extman/docsmysql \-uroot \-p \<extmail.sql mysql \-uroot \-p \<init.sql进入mysql命令行执行:grant all on extmail.\* to webman@'localhost' identified by "webman";flush privileges; | | --- | vim /var/www/extsuite/extman/webmail.cf,配置代码如下: | SYS\_CONFIG \= /var/www/extsuite/extman/SYS\_LANGDIR \= /var/www/extsuite/extman/langSYS\_TEMPLDIR \= /var/www/extsuite/extman/htmlSYS\_MAILDIR\_BASE \= /var/spool/mailSYS\_SHOW\_WARN \= 0SYS\_SESS\_DIR \= /tmp/extman/SYS\_CAPTCHA\_ON \= 1SYS\_CAPTCHA\_KEY \= r3s9b6a7SYS\_CAPTCHA\_LEN \= 6SYS\_PURGE\_DATA \= 0SYS\_PSIZE \= 20SYS\_APP\_TYPE \= ExtManSYS\_TEMPLATE\_NAME \= defaultSYS\_DEFAULT\_EXPIRE \= 1ySYS\_GROUPMAIL\_SENDER \= postmaster@extmail.orgSYS\_DEFAULT\_SERVICES \= webmail,smtpd,smtp,pop3,netdiskSYS\_ISP\_MODE \= noSYS\_DOMAIN\_HASHDIR \= yesSYS\_DOMAIN\_HASHDIR\_DEPTH \= 2x2SYS\_USER\_HASHDIR \= yesSYS\_USER\_HASHDIR\_DEPTH \= 2x2SYS\_MIN\_UID \= 500SYS\_MIN\_GID \= 100SYS\_DEFAULT\_UID \= 1000SYS\_DEFAULT\_GID \= 1000SYS\_QUOTA\_MULTIPLIER \= 1048576SYS\_QUOTA\_TYPE \= courierSYS\_DEFAULT\_MAXQUOTA \= 500SYS\_DEFAULT\_MAXALIAS \= 100SYS\_DEFAULT\_MAXUSERS \= 100SYS\_DEFAULT\_MAXNDQUOTA \= 500SYS\_USER\_DEFAULT\_QUOTA \= 5SYS\_USER\_DEFAULT\_NDQUOTA \= 5SYS\_USER\_DEFAULT\_EXPIRE \= 1ySYS\_BACKEND\_TYPE \= mysqlSYS\_CRYPT\_TYPE \= md5cryptSYS\_MYSQL\_USER \= webmanSYS\_MYSQL\_PASS \= webmanSYS\_MYSQL\_DB \= extmailSYS\_MYSQL\_HOST \= localhostSYS\_MYSQL\_SOCKET \= /var/lib/mysql/mysql.sockSYS\_MYSQL\_TABLE \= managerSYS\_MYSQL\_ATTR\_USERNAME \= usernameSYS\_MYSQL\_ATTR\_PASSWD \= passwordSYS\_LDAP\_BASE \= dc\=extmail.orgSYS\_LDAP\_RDN \= cn\=Manager,dc\=extmail.orgSYS\_LDAP\_PASS \= secretSYS\_LDAP\_HOST \= localhostSYS\_LDAP\_ATTR\_USERNAME \= mailSYS\_LDAP\_ATTR\_PASSWD \= userPasswordSYS\_RRD\_DATADIR \= /var/libSYS\_RRD\_TMPDIR \= /tmp/viewlogSYS\_RRD\_QUEUE\_ON \= yesSYS\_CMDSERVER\_SOCK \= /tmp/cmdserver.sock SYS\_CMDSERVER\_MAXCONN \= 5SYS\_CMDSERVER\_PID \= /var/run/cmdserver.pidSYS\_CMDSERVER\_LOG \= /var/log/cmdserver.logSYS\_CMDSERVER\_AUTHCODE \= your\_auth\_code\_hereSYS\_IGNORE\_SERVER\_LIST \= web | | --- | 修改httpd.conf配置文件代码如下: | User postfixGroup postfix\<VirtualHost \*:80\>ServerName mail.jingfengjiaoyu.comDocumentRoot /var/www/extsuite/extmail/html/ScriptAlias /extmail/cgi /var/www/extsuite/extmail/cgiAlias /extmail /var/www/extsuite/extmail/htmlScriptAlias /extman/cgi /var/www/extsuite/extman/cgiAlias /extman /var/www/extsuite/extman/html\</VirtualHost\> | | --- | 使用默认用户名/密码登录 Extman后台管理员:root@extmail.org Extman后台管理员初始密码:extmail\*123\* Postmaster用户密码:extmail 浏览器访问:<http://mail.jingfengjiaoyu.com/extman/> ![](/media/202411/20241125143347049515.png) ![](/media/202411/20241125143347054509.png) ## MailGraph\_ext安装配置: 安装MailGraph\_ext之前,必须要安装他所依赖的一些软件包,否则MailGraph\_ext就不能正常工作。 \*rrdtool 及rrdtool的perl包,地址: http://people.ee.ethz.ch/\~oetiker/webtools/rrdtool/ \*File::Tail (还需要Time::HiRes模块) | cp \-r /var/www/extsuite/extman/addon/mailgraph\_ext/ /usr/local/mailgraph\_ext//usr/local/mailgraph\_ext/mailgraph\-init start/var/www/extsuite/extman/daemon/cmdserver \-\-daemon | | --- | 将MailGraph\_ext及cmdserver加入系统自启动 | echo "/usr/local/mailgraph\_ext/mailgraph\-init start" \>\> /etc/rc.d/rc.localecho "/var/www/extsuite/extman/daemon/cmdserver \-v \-d" \>\> /etc/rc.d/rc.local | | --- | ![](/media/202411/20241125143347061815.png) ![](/media/202411/20241125143347068571.png) ## 基于Postfix\+Extman虚拟用户注册 ![](/media/202411/20241125143347074275.png) ![](/media/202411/20241125143347079053.png) ## 基于Extman自动注册并登陆 1. 通过extman自动注册用户和设置密码之后,发现用户无法登陆extmail WEB平台,提示用户名和密码错误,如图所示所示: ![](/media/202411/20241125143347083906.png) 问题分析步骤: 由于extman数据库连接的是extmail库,而虚拟用户读取的库postfix,导致数据不同步。解决方法可以同步数据,或者合并库; | mysqldump \-uroot \-p postfix \>postfix.sqlmysqldump \-uroot \-p extmail \>extmail.sql进入mysql命令行:drop database extmail;use postfix;source /tmp/extmail.sql; | | --- | 修改webman.cf配置文件数据库连接信息: | SYS\_MYSQL\_USER \= postfixSYS\_MYSQL\_PASS \= postfixSYS\_MYSQL\_DB \= postfix | | --- | 重新登录Extmail访问,使用用户名jfedu888登录如图所示: ![](/media/202411/20241125143347089916.png) 重新注册虚拟用户,验证登录,注册用户jfedu999,密码jfedu999 ![](/media/202411/20241125143347095431.png) ![](/media/202411/20241125143347100462.png) 1. Postfixadmin无法登陆,报错如下: | PHP Warning: Unknown: Failed to write session data (files). Please verify that the current setting of session.save\_path is correct (/var/lib/php/session) in Unknown on line 0, referer: http://mail.jingfengjiaoyu.com/postfixadmin/login.php\[Sat Jul 01 23:24:42 2022] \[error] \[client 36\.102\.227\.109] PHP Warning: session\_destroy(): Session object destruction failed in /var/www/html/postfixadmin/common.php on line 30, referer: http://mail.jingfengjiaoyu.com/postfixadmin/main.php | | --- | ![](/media/202411/20241125143347105733.png) Apache配置文件添加如下代码: | User postfixGroup postfix\<VirtualHost \*:80\>ServerName mail.jingfengjiaoyu.comDocumentRoot /var/www/extsuite/extmail/html/ScriptAlias /extmail/cgi /var/www/extsuite/extmail/cgiAlias /extmail /var/www/extsuite/extmail/htmlScriptAlias /extman/cgi /var/www/extsuite/extman/cgiAlias /extman /var/www/extsuite/extman/htmlAlias /postfixadmin /var/www/html/postfixadmin/\</VirtualHost\> | | --- | 重启Apache服务,访问如图所示: ![](/media/202411/20241125143347111611.png) ![](/media/202411/20241125143347116302.png) 无法登录postfixadmin,查看maillog日志如图所示: tail \-fn 100 /var/log/httpd/error\_log ![](/media/202411/20241125143347121703.png) 解决方法:chmod 757 \-R /var/lib/php/session/ ![](/media/202411/20241125143347126883.png) # 自动化运维发展前景 随着企业服务器数量越来越多,当到达几百台,上千台服务器之后,服务器日常管理也逐渐繁杂,每天如果通过人工去频繁的更新或者部署及管理这些服务器,势必会浪费大量的时间,而且有可能人为的操作也会造成某些疏忽而遗漏。那我们来看一下传统的运维以及今后运维的发展方向。 本章向读者介绍如何构建企业自动化运维之路、传统运维方案及自动化运维方案、如何建立高效的IT自动化运维平台以及自动化运维体系各种工具等。 ## 传统运维方式简介 传统的IT运维仍然是等到IT故障出现后再由运维人员采取相应的补救措施。这种被动、孤立、半自动式的IT运维管理模式经常让IT部门疲惫不堪,主要表现在以下三个方面: 1. 运维人员被动、效率低 在IT运维过程中,只有当事件已经发生并已造成业务影响时才能发现和着手处理,这种被动“救火”不但使IT运维人员终日忙碌,也使IT运维本身质量很难提高,导致IT部门和业务部门对IT运维的服务满意度都不高。 1. 缺乏一套高效的IT运维机制 许多企业在IT运维管理过程中缺少自动化的运维管理模式,也没有明确的角色定义和责任划分,使到问题出现后很难快速、准确地找到根本原因,无法及时地找到相应的人员进行修复和处理,或者是在问题找到后缺乏流程化的故障处理机制,而在处理问题时不但欠缺规范化的解决方案,也缺乏全面的跟踪记录。 1. 缺乏高效的IT运维技术工具 随着信息化建设的深入,企业IT系统日趋复杂,林林总总的网络设备、服务器、中间件、业务系统等让IT运维人员难以从容应对,即使加班加点地维护、部署、管理也经常会因设备出现故障而导致业务的中断,严重影响企业的正常运转。 出现这些问题部分原因是企业缺乏事件监控和诊断工具等IT运维技术工具,因为在没有高效的技术工具的支持下故障事件很难得到主动、快速的处理。 ## 自动化运维简介 IT运维已经在风风雨雨中走过了十几个春秋,如今它正以一种全新的姿态摆在我们面前,运维自动化\-这是IT技术发展的必然结果,现在IT系统的复杂性已经客观上要求IT运维必须能够实现数字化、自动化维护。 运维自动化是指将IT运维中日常的、大量的重复性工作自动化,把过去的手工执行转为自动化操作。自动化是IT运维工作的升华,IT运维自动化不单纯是一个维护过程,更是一个管理的提升过程,是IT运维的最高层次,也是未来的发展趋势。 ## 运维自动化的具体内容 日常IT运维中大量的重复性工作(小到简单的日常检查、配置变更和软件安装,大到整个变更流程的组织调度)由过去的手工执行转为自动化操作,从而减少乃至消除运维中的延迟,实现“零延时”的IT运维。 简单的说,IT运维自动化是指基于流程化的框架,将事件与IT流程相关联,一旦被监控系统发生性能超标或宕机,会触发相关事件以及事先定义好的流程,可自动启动故障响应和恢复机制。 ## 建立高效的IT自动化运维管理 建立高效的IT自动化运维管理步骤主要包括以下几点: 1. 建立自动化运维管理平台 IT运维自动化管理建设的第一步是要先建立IT运维的自动化监控和管理平台。通过监控工具实现对用户操作规范的约束和对IT资源进行实时监控,包括服务器、数据库、中间件、存储备份、网络、安全、机房、业务应用和客户端等内容,通过自动监控管理平台实现故障或问题综合处理和集中管理。 1. 建立故障事件自动触发流程,提高故障处理效率 所有IT设备在遇到问题时要会自动报警,无论是系统自动报警还是使用人员报的故障,应以红色标识显示在运维屏幕上。然后IT运维人员只需要按照相关知识库的数据,一步一步操作就可以。 1. 建立规范的事件跟踪流程,强化运维执行力度 需要建立故障和事件处理跟踪流程,利用表格工具等记录故障及其处理情况,以建立运维日志,并定期回顾从中辨识和发现问题的线索和根源。 1. 设立IT运维关键流程,引入优先处理原则 设置自动化流程时还需要引入优先处理原则,例行的事按常规处理,特别事件要按优先级次序处理,也就是把事件细分为例行事件和例外关键事件。 ## IT自动化运维工具 对于企业来说,要特别关注两类自动化工具:一是IT运维监控和诊断优化工具;二是运维流程自动化工具。这两类工具主要应用于: 1. 监控自动化:是指对重要的IT设备实施主动式监控,如路由器、交换机、防火墙等。 2. 配置变更检测自动化:是指IT设备配置参数一旦发生变化,将触发变更流程转给相关技术人员进行确认,通过自动检测协助IT运维人员发现和维护配置。 3. 维护事件提醒自动化:是指通过对IT设备和应用活动的时时监控,当发生异常事件时系统自动启动报警和响应机制,第一事件通知相关责任人。 4. 系统健康检测自动化:是指定期自动地对IT设备硬件和应用系统进行健康巡检,配合IT运维团队实施对系统的健康检查和监控。 5. 维护报告生成自动化:是指定期自动的对系统做日志的收集分析,记录系统运行状况,并通过阶段性的监控、分析和总结,定时提供IT运维的可用性、性能、系统资源利用状况分析报告。 ## IT自动化运维体系 一个完善的自动化运维体系包括系统预备、配置管理以及监控报警三种环节,每个环节实现的功能也各不相同,具体功能如下: 1. 系统预备类: * 自动化安装操作系统; * 自动初始化系统; * 自动安装各种软件包。 1. 配置管理类: * 自动化部署业务系统软件包并完成配置; * 远程管理服务器; * 配置文件、自动部署Jenkins、网站代码变更回滚。 1. 监控报警类: * 服务器可用性、性能、安全监控; * 向管理员发送报警信息。 根据提供的功能不同,自动化运维工具软件分为以下 3 类,如下19\-1表所示: | 编号 | 预备类工具 | 配置管理类 | 监控报警类 | | --- | --- | --- | --- | | 1 | Kickstart | Puppet | Nagios | | 2 | Cobbler | Saltstack | Cacti | | 3 | OpenQRM | Func | Ganglia | | 4 | Spacewalk | Ansible | Zabbix | 表19\-1 自动化运维工具分类 # Puppet自动运维企业实战 Puppet是目前互联网主流三大自动化运维工具(Puppet、Ansible、Saltstack)之一,Puppet是一种Linux、Unix平台的集中配置管理系统,所谓配置管理系统,就是管理机器里面诸如文件、用户、进程、软件包等资源,其设计目标是简化对这些资源的管理以及妥善处理资源间的依赖关系。 本章向读者介绍Puppet工作原理、Puppet安装配置、企业资源案例讲解、Puppet高可用集群配置、Puppet批量更新部署网站、Puppet\+SVN实现代码自动部署等。 ## Puppet入门简介 Puppet使用一种描述性语言来定义配置项,配置项中被称为”资源”,描述性语言可以声明你的配置的状态,比如声明一个软件包应该被安装或者一个服务应该被启动用。 Puppet可以运行一台服务器端,每个客户端通过ssl证书连接服务器,得到本机器的配置列表,然后更加列表的来完成配置工作,所以如果硬件性能比较高,维护个管理上千上万台机器是非常轻松的,前提是客户端机器的配置、服务器路径、软件需要保持一致。 在企业级大规模的生成环境中,如果只有一台puppet master压力会非常大,因为puppet是用ruby语言编写,ruby是解析型语言,每个客户端来访问都要解析一次,当客户端服务器很多,会操作服务器端压力很多,所以需要扩展成一个服务器集群组。 Puppet master可以看作一个web服务器,实际上也是由ruby提供的web服务器模块来做的。因此可以利用web代理软件来配合puppet master做集群设置,一般使用Nginx\+Puppet Master整合构建大型企业自动化运维管理工具,puppet项目主要开发者是Luke Kanies,目前为puppet labs CEO,Puppet遵循GPLv2版权协议。 从1997年开始Kanies参与UNIX的系统管理工作,Puppet的开发源于这些经验。因为对已有的配置工具不甚满意,从2001年到2005年间,Kanies开始在Reductive实验室从事工具的开发。很快Reductive实验室发布了他们新的旗舰产品。 Puppet是开源的基于Ruby的系统配置管理工具,Puppet工作流程为:puppet是一个C/S结构,所有的puppet客户端同一个服务器端的puppet通讯,每个puppet客户端每半小时(可以设置)连接一次服务器端,下载最新的配置文件,并且严格按照配置文件来配置服务器,配置完成以后puppet客户端可以反馈给服务器端一个消息,如果报错会给服务器端反馈一个消息。 ## Puppet工作原理 要熟练掌握Puppet在企业生产环境中的应用,需要深入理解Puppet服务端与客户端详细的工作流程及原理,如图20\-1(a)、20\-1(b)所示,为Puppet Master与Agent完整工作流程图: ![](/media/202411/20241125143347135574.png)图20\-1(a) Puppet工作原理图 ![http://img.educity.cn/img_16/333/2014031819/14217194215.jpg](/media/202411/20241125143347141412.jpeg)图20\-1(b) Puppet工作原理图 Puppet工作原理详解如下: * 客户端puppetd调用本地facter,facter会探测出该主机的常用变量,例如主机名、内存大小、IP地址等。然后puppetd把这些信息发送到Puppet服务端。 * Puppet服务端检测到客户端的主机名,然后会检测manifest中对应的node配置,并对这段内容进行解析,facter发送过来的信息可以作为变量进行处理。 * Puppet服务端匹配Puppet客户端相关联的代码才进行解析,其它的代码不解析,解析分几个过程:语法检查、然后会生成一个中间的伪代码,然后再把伪代码发给Puppet客户端。 * Puppet客户端接收到伪代码之后就会执行,执行完后会将执行的结果发送给Puppet服务端。 * Puppet服务端再把客户端的执行结果写入日志。 ## Puppet安装配置 由于Puppet为C/S模式,构建Puppet平台需安装Puppet Sserver端和Client端,安装之前准备好系统环境,如下: | 操作系统版本:CentOS 6\.5 x64服务端ip 192\.168\.149\.128 hostname:192\-168\-149\-128\-jfedu.net客户端ip 192\.168\.149\.130 hostname:192\-168\-149\-130\-jfedu.net | | --- | 1. Puppet服务端安装 由于Puppet主要是基于hostname来检测的,所以Puppet服务器端需修改主机名称为:192\-168\-149\-128\-jfedu.net,并且在hosts文件添加主机名和本机IP的对应关系,如果本地局域网有DNS服务器,可以无需修改hosts文件,修改主机名及配置hosts代码如下: | hostname \`ifconfig eth0 \|grep Bcast\|awk '{print $2}'\|cut \-d: \-f 2 \|sed 's/\\./\\\-/g'\`\-jfedu.netcat \>\>/etc/hosts\<\<EOF 192\.168\.149\.128 192\-168\-149\-128\-jfedu.net 192\.168\.149\.130 192\-168\-149\-130\-jfedu.netEOF | | --- | Puppet服务端除了需要安装Puppet\-server外,还需要Ruby的支持,需要安装Ruby相关软件包,默认YUM安装Puppet Server,会自动下载并安装Ruby相关软件,如图20\-2所示: | rpm \-Uvh http://yum.puppetlabs.com/el/6/products/x86\_64/puppetlabs\-release\-6\-1\.noarch.rpm yum install puppet\-server \-y /etc/init.d/puppetmaster start /etc/init.d/iptables stop sed \-i '/SELINUX/S/enforce/disabled/' /etc/selinux/configsetenforce 0 | | --- | ![](/media/202411/20241125143347147643.png)图20\-2 Puppet\-server服务端安装 1. Puppet客户端安装 Puppet主要是基于hostname来检测的,所以Puppet客户端也需要修改主机名称为:192\-168\-149\-130\-jfedu.net,并且在hosts文件添加主机名和本机IP的对应关系,如果本地局域网有DNS服务器,可以无需修改hosts文件,修改主机名及配置hosts代码如下: | hostname \`ifconfig eth0 \|grep Bcast\|awk '{print $2}'\|cut \-d: \-f 2 \|sed 's/\\./\\\-/g'\`\-jfedu.netcat \>\>/etc/hosts\<\<EOF 192\.168\.149\.128 192\-168\-149\-128\-jfedu.net 192\.168\.149\.130 192\-168\-149\-130\-jfedu.netEOF | | --- | Puppet客户端除了需要安装puppet外,还需要Ruby的支持,需要安装Ruby相关软件包,默认YUM安装Puppet,会自动下载并安装Ruby相关软件,如图20\-3所示: | rpm \-Uvh http://yum.puppetlabs.com/el/6/products/x86\_64/puppetlabs\-release\-6\-1\.noarch.rpm yum install puppet \-y /etc/init.d/puppetmaster start /etc/init.d/iptables stop sed \-i '/SELINUX/S/enforce/disabled/' /etc/selinux/configsetenforce 0 | | --- | ![](/media/202411/20241125143347155115.png)图20\-3 Puppet客户端服务安装 1. Puppet客户端申请证书 由于Puppet客户端与Puppet服务端是通过SSL隧道通信的,客户端安装完成后,首次使用需向服务器端申请Puppet通信证书, Puppet客户端第一次连接服务器端会发起证书申请,在Puppet客户端执行命令如下,返回结果如图20\-4所示: | puppet agent \-\-server 192\-168\-149\-128\-jfedu.net \-\-test | | --- | ![](/media/202411/20241125143347160868.png)图20\-4 Puppet客户端发起证书申请 1. Puppet服务端颁发证书 Puppet客户端向服务器发起证书申请,服务器端必须审核证书,如果不审核,客户端与服务器端无法进行后续正常通信,Puppet服务端颁发证书命令代码如下,返回结果如图20\-5所示: | puppet cert \-\-list 查看申请证书的客户端主机名;puppet cert \-s 192\-168\-149\-130\-jfedu.net 颁发证书给客户端; puppet cert \-s 为特定的主机颁发证书;puppet cert \-s and \-a 给所有的主机颁发证书;puppet cert \-\-list \-\-all 查看已经颁发的所有证书。 | | --- | ![](/media/202411/20241125143347165981.png) 图20\-5 Puppet服务端颁发证书 ## Puppet企业案例演示 Puppet是基于C/S架构,服务器端保存着所有对客户端服务器的配置代码,在puppet服务端该配置文件叫manifest,客户端下载manifest之后,可以根据manifest对客户端进行配置,例如软件包管理、用户管理、文件管理、命令管理、脚本管理等,Puppet主要基于各种资源或者模块来管理客户端。 默认Puppet服务器端manifest目录在/etc/puppet/manifests/下,只需要在该目录下创建一个site.pp文件,然后写入相应的配置代码,Puppet客户端跟Puppet服务端同步时,会检查客户端node配置文件,匹配之后会将该代码下载至客户端,对代码进行解析,然后在客户端执行。 如下为在Puppet客户端创建test.txt文件,并在该文件中写入测试内容,操作方法如下: 1. Puppet服务端创建node代码,创建或者编辑vi /etc/puppet/manifests/site.pp文件,在文件中加入如下代码: | node default { file { "/tmp/test.txt": content \=\> "Hello World,jfedu.net 2022"; } } | | --- | manifests site.pp配置文件代码详解如下: | node default 新建node节点,default表示所有主机,可修改为特定主机名;file 基于file资源模块管理客户端文件或者目录操作; "/tmp/test.txt": 需在客户端文件创建的文件名; content 客户端服务器文件内容。 | | --- | 1. 客户端执行同步命令,获取Puppet服务端node配置,代码如下,如图20\-6所示,执行报错: | puppet agent \-\-server\=192\-168\-149\-128\-jfedu.net \-\-test | | --- | ![](/media/202411/20241125143347172003.png) 图20\-6 Puppet客户端同步服务端配置 报错原因是因为服务器端与客户端时间不同步导致,需要同步时间,然后再次执行puppet agent命令,如图20\-7所示: | ntpdate pool.ntp.orgpuppet agent \-\-server\=192\-168\-149\-128\-jfedu.net \-\-test | | --- | ![](/media/202411/20241125143347176955.png)图20\-7 Puppet客户端获取服务端node配置 Puppet客户端执行同步效果,执行日志如下,会在/tmp/目录创建test.txt文件,内容为:“Hello World,jfedu.net”,即证明Puppet客户端成功获取服务端node配置。 | Info: Caching certificate\_revocation\_list for caWarning: Unable to fetch my node definition, but the agent run will continue:Warning: undefined method \`include?' for nil:NilClassInfo: Retrieving pluginfactsInfo: Retrieving pluginInfo: Caching catalog for 192\-168\-149\-130\-jfedu.netInfo: Applying configuration version '1496805041'Notice: /Stage\[main]/Main/Node\[default]/File\[/tmp/test.txt]/ensure: defined content as '{md5}d1c2906ad0b249a330e936e3bc1d38d9'Info: Creating state file /var/lib/puppet/state/state.yamlNotice: Finished catalog run in 0\.04 seconds | | --- | ## Puppet常见资源及模块 Puppet主要基于各种资源模块管理客户端,目前企业主流Puppet管理客户端资源模块如下: | file 主要负责管理文件;package 软件包的安装管理;service 系统服务的管理;cron 配置自动任务计划;exec 远程执行运行命令。 | | --- | 通过命令puppet describe \-l可以查看puppet支持的所有资源和模块,如图20\-8(a)、20\-8(b)所示: ![](/media/202411/20241125143347183448.png) 图20\-8(a) Puppet支持的资源及模块 ![](/media/202411/20241125143347188205.png)图20\-8(b) Puppet支持的资源及模块 通过命令puppet describe \-s file可以查看puppet file资源所有的帮助信息,如图20\-9(a)、20\-9(b)所示: ![](/media/202411/20241125143347193123.png)图20\-9(a) Puppet file资源模块详情 ![](/media/202411/20241125143347200360.png)图20\-9(b) Puppet file资源模块详情 ## Puppet file资源案例 Puppet file资源主要用于管理客户端文件,包括文件的内容、所有权和权限,其可管理的文件类型包括:普通文件、目录以及符号链接等。 类型应在“确保”属性中指定,如果是文件内容可以直接用'content属性来管理,或者使用source属性从远程源下载;后者也可以用recurse服务目录(当recurse属性设置为“true”或“local”。Puppet file资源支持参数如下: | ensure 默认为文件或目录; backup 通过filebucket备份文件; checksum 检查文件是否被修改的方法; ctime 只读属性,文件的更新时间; mtime 只读属性,文件的修改时间; content 文件的内容,与source和target互斥 ;force 强制执行删除文件、软链接机目录的操作; owner 用户名或用户ID;group 指定文加年的用户组或组id;link 软链接;mode 文件权限配置,通常采用数字符号;path 文件路径;Parameters backup, checksum, content, ctime, ensure, force, group, ignore, links, mode, mtime, owner, path, purge, recurse, recurselimit, replace, selinux\_ignore\_defaults, selrange, selrole, seltype, seluser, show\_diff, source, source\_permissions, sourceselect, target, type, validate\_cmd, validate\_replacementProviders:posix, windows | | --- | 1. 从Puppet服务器下载nginx.conf文件至客户端/tmp目录,首先需要将nginx.conf文件cp至/etc/puppet/files目录,然后在/etc/puppet/fileserver.conf中添加如下三行代码,并重启Puppetmaster即可: | \[files]path /etc/puppet/files/allow \* | | --- | 创建site.pp文件,文件代码如下: | node default {file { '/tmp/nginx.conf': mode \=\> '644', owner \=\> 'root', group \=\> 'root', source \=\> 'puppet://192\-168\-149\-128\-jfedu.net/files/nginx.conf', }} | | --- | 客户端同步配置,如图20\-10所示: ![](/media/202411/20241125143347208192.png)图20\-10 Puppet file资源远程下载文件 1. 从Puppet服务器下载sysctl.conf,如果客户端该文件存在则备份为sysctl.conf.bak,然后再覆盖原文件,site.pp代码如下,如图20\-11所示: | node default {file { "/etc/sysctl.conf": source \=\> "puppet://192\-168\-149\-128\-jfedu.net/files/sysctl.conf", backup \=\> ".bak\_$uptime\_seconds", }} | | --- | ![](/media/202411/20241125143347214249.png)图20\-11 Puppet file资源备份文件 1. 在Agent上创建/export/docker的软连接为/var/lib/docker/,site.pp代码如下,如图20\-12所示: | node default {file { "/var/lib/docker": ensure \=\> link, target \=\> "/export/docker", } | | --- | ![](/media/202411/20241125143347219561.png)图20\-12 Puppet file资源备份文件 1. 在Agent上创建目录/tmp/20501212,site.pp代码如下,如图20\-13所示: | node default {file { "/tmp/20501212": ensure \=\> directory; }} | | --- | ![](/media/202411/20241125143347224934.png)图20\-13 Puppet file创建目录 ## Puppet package资源案例 Puppet package资源主要用于管理客户端服务器的软件包,yum源为/etc/yum.repo.d/安装和升级操作,通过puppet基于yum自动安装软件包,所以需要先配置好yum源。 常见的操作可以对软件包进行安装、卸载以及升级操作。Puppet package资源支持参数如下: | Parameters adminfile, allow\_virtual, allowcdrom, category, configfiles, description, ensure, flavor, install\_options, instance, name, package\_settings, platform, responsefile, root, source, status, uninstall\_options, vendorProviders aix, appdmg, apple, apt, aptitude, aptrpm, blastwave, dpkg, fink, freebsd, gem, hpux, macports, msi, nim, openbsd, opkg, pacman, pip, pkg, pkgdmg, pkgin, pkgutil, portage, ports, portupgrade, rpm, rug, sun,sunfreeware, up2date, urpmi, windows, yum, zipperensure \=\> {installed\|absent\|pureged\|latest} present 检查软件是否存在,不存在则安装;installed 表示安装软件;absent 删除(无依赖),当别的软件包依赖时,不可删除;pureged 删除所有配置文件和依赖包,有潜在风险,慎用;latest 升级到最新版本;version 指定安装具体的某个版本号。 | | --- | 1. 客户端安装ntpdate及screen软件,代码如下,执行结果如图20\-14所示: | node default {package { \["screen","ntp"]: ensure \=\> "installed"; } | | --- | ![](/media/202411/20241125143347231514.png)图20\-14 Puppet package安装软件 1. 客户端卸载ntpdate及screen软件,代码如下,执行结果如图20\-15所示: | node default {package { \["screen","ntp"]: ensure \=\> "absent"; } | | --- | ![](/media/202411/20241125143347236924.png)图20\-15 Puppet package卸载软件 ## Puppet service资源案例 Puppet service资源主要用于启动、重启和关闭客户端的守护进程,同时可以监控进程的状态,还可以将守护进程加入到自启动中。Puppet service资源支持参数如下: | Parameters binary, control, enable, ensure, flags, hasrestart, hasstatus, manifest, name, path, pattern, restart, start, status, stopProviders base, bsd, daemontools, debian, freebsd, gentoo, init, launchd, openbsd, openrc, openwrt, redhat, runit, service, smf, src, systemd, upstart,windowsenable 指定服务在开机的时候是否启动,可以设置true和false;ensure 是否运行服务,running表示运行,stopped表示停止服务;name 守护进程的名字;path 启动脚本搜索路径;provider 默认为init;hasrestart 管理脚本是否支持restart参数,如果不支持,就用stop和start实现restart效果;hasstatus 管理脚本是否支持status参数,puppet用status参数来判断服务是否已经在运行了,如果不支持status参数,puppet利用查找运行进程列表里面是否有服务名来判断服务是否在运行。 | | --- | 1. 启动Agent httpd服务,停止nfs服务,代码如下,结果如图20\-16(a)、20\-16(b)所示: | node default {service { "httpd": ensure \=\> running; "nfs": ensure \=\> stopped; } | | --- | ![](/media/202411/20241125143347243524.png)图20\-16(a) Puppet service重启服务 ![](/media/202411/20241125143347249933.png)图20\-16(b) Puppet service重启服务 1. 启动Agent httpd服务并且开启启动,停止nfs服务,开启不启动,代码如下,结果如图20\-17(a)、20\-17(b)所示: | node default {service { "httpd": ensure \=\> running, enable \=\> true; "nfs": ensure \=\> stopped, enable \=\> false;} | | --- | ![](/media/202411/20241125143347255451.png) 图20\-17(a) Puppet service开启启动 ![](/media/202411/20241125143347260179.png)图20\-17(b) Puppet service开启启动 ## Puppet exec资源案例 Puppet exec资源主要用于客户端远程执行命令或者软件安装等,相当于shell的调用,exec是一次性执行资源,在不同类里面exec名字可以相同。Puppet exec资源支持参数如下: | Parameters command, creates, cwd, environment, group, logoutput, onlyif, path, refresh, refreshonly, returns, timeout, tries, try\_sleep, umask, unless, userProvidersposix, shell, windowscommand 指定要执行的系统命令;creates 指定命令所生成的文件;cwd 指定命令执行目录,如果目录不存在,则命令执行失败; group 执行命令运行的账户组;logoutput 是否记录输出;onlyif exec只会在onlyif设定的命令返回0时才执行;path 命令执行的搜索路径;refresh \=\>true\|false 刷新命令执行状态;refreshonly \=\>true\|false 该属性可以使命令变成仅刷新触发的,returns 指定返回的代码;timeout 命令运行的最长时间;tries 命令执行重试次数,默认为1;try\_sleep 设置命令重试的间隔时间,单位为秒;user 指定执行命令的账户;provider shell和windows;environment 为命令设定额外的环境变量;要注意的是如果设定PATH,PATH的属性会被覆盖。 | | --- | 1. Agent服务器执行tar解压nginx软件包,代码如下,结果如图20\-18所示: | node default {exec { 'Agent tar xzf nginx\-1\.12\.0\.tar.gz': path \=\> \["/usr/bin","/bin"], user \=\> 'root', group \=\> 'root', timeout \=\> '10', command \=\> 'tar \-xzf /tmp/nginx\-1\.12\.0\.tar.gz',}} | | --- | ![](/media/202411/20241125143347268012.png)图20\-18 Puppet exec远程执行命令 1. Agent服务器远程执行auto\_install\_nginx.sh脚本,代码如下,结果如图20\-19所示: | node default {file { "/tmp/auto\_install\_nginx.sh": source \=\>"puppet://192\-168\-149\-128\-jfedu.net/files/auto\_install\_nginx.sh", owner \=\> "root", group \=\> "root", mode \=\> 755, }exec { "/tmp/auto\_install\_nginx.sh": cwd \=\> "/tmp", user \=\> root, path \=\> \["/usr/bin","/usr/sbin","/bin","/bin/sh"],} | | --- | ![](/media/202411/20241125143347273564.png) 图20\-19 Puppet exec执行Nginx安装脚本 1. Agent服务器更新sysctl.conf,如果该文件发生改变,则执行命令sysctl \-p,代码如下,结果如图20\-20(a)、20\-20(b)所示: | node default {file { "/etc/sysctl.conf": source \=\>"puppet://192\-168\-149\-128\-jfedu.net/files/sysctl.conf", owner \=\> "root", group \=\> "root", mode \=\> 644, }exec { "sysctl refresh kernel config": path \=\> \["/usr/bin", "/usr/sbin", "/bin", "/sbin"], command \=\> "/sbin/sysctl \-p", subscribe \=\> File\["/etc/sysctl.conf"], refreshonly \=\> true }} | | --- | ![](/media/202411/20241125143347279232.png)图20\-20(a) Puppet exec更新执行触发命令 ![](/media/202411/20241125143347284122.png)图20\-20(b) Puppet exec更新执行触发命令 ## Puppet cron资源案例 Puppet cron资源主要用于安装和管理crontab计划任务,每一个cron资源需要一个command属性和user属性以及至少一个周期属性(hour,minute,month,monthday,weekday)。 Crontab计划任务的名字不是计划任务的一部分,它是puppet用来存储和检索该资源。假如你指定了一个除了名字其他的都和一个已经存在的计划任务相同,那么这两个计划任务被认为是等效的,并且新名字将会永久地与该计划任务相关联。Puppet cron资源支持参数如下: | Parameters command, ensure, environment, hour, minute, month, monthday, name, special, target, user, weekdayProviders crontabuser 加某个用户的crontab任务,默认是运行puppet的用户;command 要执行的命令或脚本路径,可不写,默认是title名称;ensure 定该资源是否启用,可设置成true或false;environment crontab环境里面指定环境变量;hour 设置crontab的小时,可设置成0\-23;minute 指定crontab的分钟,可设置成0\-59;month 指定crontab运行的月份,1\-12;monthday 指定月的天数1\-31;name crontab的名字,区分不同的crontab;provider 可用的provider有crontab默认的crontab程序;target crontab作业存放的位置;weekday 行crontab的星期数,0\-7,周日是为0。 | | --- | 1. Agent服务器添加ntpdate时间同步任务,代码如下,结果如图20\-21所示: | node default {cron{ "ntpdate": command \=\> "/usr/sbin/ntpdate pool.ntp.org", user \=\> root, hour \=\> 0, minute \=\> 0, }} | | --- | ![](/media/202411/20241125143347292606.png)图20\-21 Puppet cron创建任务计划 1. Agent服务器删除ntpdate时间同步任务,代码如下,结果如图20\-22所示: | node default {cron{ "ntpdate": command \=\> "/usr/sbin/ntpdate pool.ntp.org", user \=\> root, hour \=\> 0, minute \=\> 0, ensure \=\> absent, }} | | --- | ![](/media/202411/20241125143347298144.png)图20\-22 Puppet cron删除任务计划 ## Puppet日常管理与配置 Puppet平台构建完毕,能够简单实用Puppet去管理客户端,对文件、服务、脚本、各种配置的变更,如果要管理批量服务器,还需要进行一些步骤的配置。 ### Puppet自动认证 企业新服务器通过kickstart自动安装Linux操作系统,安装完毕,可以自动安装puppet相关软件包,Puppet客户端安装完毕,需向Puppet服务端请求证书,然后Puppet服务端颁发证书给客户端,默认需要手动颁发,可以通过配置让Puppet服务端自动颁发证书。 自动颁发证书前提是服务端与客户端能ping通彼此的主机名方可,配置自动颁发证书需Puppet服务器端的puppet.conf配置文件main段加入如下代码,如图20\-23所示: | \[main]autosign \= true | | --- | ![](/media/202411/20241125143347303566.png)图20\-23 Puppet 服务端添加自动颁发证书 重启puppetmaster服务,并且删除192\.168\.149\.130证书: | /etc/init.d/puppetmaster restartpuppet cert \-\-clean 192\-168\-149\-130\-jfedu.net | | --- | 删除Puppet客户端SSL文件,重新生成SSL文件,执行如下命令自动申请证书: | rm \-rf /var/lib/puppet/ssl/puppet agent \-\-server\=192\-168\-149\-128\-jfedu.net \-\-test | | --- | Puppet服务端会自动认证,即服务器端不必手动颁发证书,减轻人工的干预和操作,如图20\-24所示: ![](/media/202411/20241125143347308661.png)图20\-24 Puppet客户端自动获取证书 ### Puppet客户端自动同步 Puppet客户端安装完,并且认证完之后,如果在Puppet服务端配置了node信息,客户端启动服务,默认30分钟自动与服务端同步信息,如何修改同步的时间频率呢,修改puppet客户端配置信息即可: Puppet客户端配置puppet相关参数和同步时间,修改/etc/sysconfig/puppet配置文件,最终代码如下: | \# The puppetmaster serverPUPPET\_SERVER\=192\-168\-149\-128\-jfedu.net\# If you wish to specify the port to connect to do so herePUPPET\_PORT\=8140\# Where to log to. Specify syslog to send log messages to the system log.PUPPET\_LOG\=/var/log/puppet/puppet.log\# You may specify other parameters to the puppet client herePUPPET\_EXTRA\_OPTS\=\-\-waitforcert\=500 | | --- | /etc/sysconfig/puppet配置文件参数详解: | PUPPET\_SERVER\=192\-168\-149\-128\-jfedu.net 指定Puppet master主机名;PUPPET\_PORT\=8140 指定puppet master端口;PUPPET\_LOG\=/var/log/puppet/puppet.log puppet客户端日志路径;PUPPET\_EXTRA\_OPTS\=\-\-waitforcert\=500 获取Puppet master证书返回等待时间。 | | --- | 重启puppet客户端服务,户端会半个小时跟服务器同步一次配置信息: | /etc/init.d/puppet restart | | --- | 可以修改与服务器端同步配置信息的时间,修改vi /etc/puppet/puppet.conf文件,在\[agent]段加入如下语句,表示60秒于puppet master同步一次配置信息,重启puppet,同步结果如图20\-25所示: | \[agent] runinterval \= 60 | | --- | ![](/media/202411/20241125143347315070.png)图20\-25 Puppet客户端自动同步服务端配置 ### Puppet服务端主动推送 如上puppet客户端配置每60秒与服务端同步配置信息,如果服务器端更新了配置信息,想立刻让客户端同步,如何通知客户端来获取最新的配置信息呢,可以使用Puppet master主动推送的方式,让客户端更新服务端最新的配置信息。 Puppet服务器端使用puppet run命令可以给客户端发送一段信号,告诉客户端立刻跟服务器同步配置信息,配置方法如下: 修改Puppet客户端配置文件/etc/puppet/puppet.conf,在agent段加入如下代码: | \[agent] listen \= true | | --- | 修改Puppet客户端配置文件/etc/sysconfig/puppet指定puppet master端主机名: | PUPPET\_SERVER\=192\-168\-149\-128\-jfedu.net | | --- | 创建Puppet客户端配置文件namespaceauth.conf,写入如下代码: | \[puppetrunner]allow \* | | --- | 修改Puppet客户端配置文件auth.conf,在path /前添加如下代码: | path /runmethod saveallow \* | | --- | 重启Puppet客户端: /etc/init.d/puppet restart Puppet服务端执行如下命令,通知客户端来同步配置,也可以批量通知其他客户端,只需将客户端的主机名写入host.txt文件,如图20\-26所示: | puppet kick \-d 192\-168\-149\-130\-jfedu.net\#puppet kick \-d 'cat host.txt' | | --- | ![](/media/202411/20241125143347321274.png)图20\-26 Puppet主动通知客户端同步配置 ## Puppet批量部署案例 随着IT行业的迅猛发展,传统的运维方式靠大量人力比较吃力,近几年自动化运维管理快速的发展,得到了很多IT运维人员的青睐,一个完整的自动化运维包括系统安装、配置管理、服务监控三个方面。如下为Puppet生成环境中应用案例。 某互联网公司新到100台硬件服务器,要求统一安装Linux系统,并部署上线以及后期的管理配置。对于Linux系统安装,需采用批量安装,批量安装系统主流工具为Kickstart和Cobbler,任选其一即可。 如果采用自动安装的话,我们可以自动初始化系统、内核简单优化、及常见服务、软件客户端等安装。当然puppet客户端也可以放在kickstart中安装并配置完毕。 当Linux操作系统安装完成后,需要对服务器进行相应的配置,方可在应对高并发网站,例如修改动态IP为静态IP、安装及创建Crontab任务计划、同步操作系统时间、安装Zabbix客户端软件、优化内核参数等,可以基于Puppet统一调整: ### Puppet批量修改静态IP案例 现需要修改100台Linux服务器原Dhcp动态获取的IP为Static IP地址,首先需有修改IP脚本,将该脚本推送到客户端,然后执行脚本并重启网卡即可,步骤如下: 1. 修改IP为静态IP的Shell脚本代码如下: | \#!/bin/bash\#auto Change ip netmask gateway scripts \#By author jfedu.net 2022\#Define Path variablesETHCONF\=/etc/sysconfig/network\-scripts/ifcfg\-eth0DIR\=/data/backup/\`date \+%Y%m%d\`IPADDR\=\`ifconfig\|grep inet\|grep 192\|head \-1\|cut \-d: \-f2\|awk '{print $1}'\`NETMASK\=255\.255\.255\.0grep dhcp $ETHCONFif \[ $? \-eq 0 ];then sed \-i 's/dhcp/static/g' $ETHCONF echo \-e "IPADDR\=$IPADDR\\nNETMASK\=$NETMASK\\nGATEWAY\=\`echo $IPADDR\|awk \-F. '{print $1"."$2"."$3}'\`.2" \>\>$ETHCONF echo "The IP configuration success. !" service network restartfi | | --- | 1. Puppet master 执行kick推送配置至Agent服务器远程,Puppet 客户端修改IP脚本代码如下,结果如图20\-27(a)、20\-27(b)所示: | node default {file { "/tmp/auto\_change\_ip.sh": source \=\>"puppet://192\-168\-149\-128\-jfedu.net/files/auto\_change\_ip.sh", owner \=\> "root", group \=\> "root", mode \=\> 755, }exec { "/tmp/auto\_change\_ip.sh": cwd \=\> "/tmp/", user \=\> root, path \=\> \["/usr/bin","/usr/sbin","/bin","/bin/sh"],}} | | --- | ![](/media/202411/20241125143347328024.png)图20\-27(a) Puppet主动通知客户端同步配置 ![](/media/202411/20241125143347333300.png)图20\-26 Puppet客户端IP自动配置为Static方式 ### Puppet批量配置NTP同步服务器 在100台Linux服务器上配置crontab任务,修改ntpdate与ntp服务端同步时间,操作步骤如下: 1. Puppet master上创建客户端node配置,可以编写NTP模块,使用class可以定义模块分组,对不同业务进行分组管理,/etc/puppet/modules/ntp/manifests/init.pp配置文件代码如下,将原ntpdate同步时间从0:0分改成每5分钟同步一次时间,并且修改原pool.ntp.org服务器为本地局域网NTP时间服务器的IP地址: | class ntp { Exec { path \=\>"/bin:/sbin:/bin/sh:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"} exec { "auto change crontab ntp config": command \=\>"sed \-i \-e '/ntpdate/s/0/\*\\/5 /2' \-e 's/pool.ntp.org/10\.1\.1\.21/' /var/spool/cron/root", } } | | --- | 1. 在/etc/puppet/manifests目录创建两个文件,分别为modules.pp和nodes.pp,模块入口文件以及node配置段。 modules.pp配置文件内容如下: | import "ntp" | | --- | nodes.pp配置文件内容如下: | node default {include ntp} | | --- | 1. 在site.pp 中加载导入modules.pp 和nodes.pp名称,site.pp代码如下: | import "modules.pp"import "nodes.pp" | | --- | 1. Puppet master 执行kick推送配置至Agent服务器远程,Puppet 客户端最终结果如图20\-28(a)、20\-28(b)所示: ![](/media/202411/20241125143347339405.png)图20\-28(a) Puppet服务端class模块配置 ![](/media/202411/20241125143347344201.png)图20\-28(b) Puppet主动通知客户端修改NTP同步配置 当服务器分组之后,为了更好的管理和配置,可以使用正则表达式来进行定义node,在定义一个node节点时,要指定节点的名字,并使用单引号将名字引起来,然后在大括号中指定需要应用的配置。 客户端节点名字可以是主机名也可以是客户端的正式域名,目前Puppet版本还不能使用通配符来指定节点,例如不能用\*.jfedu.net,可以使用正则表达式,如下代码: | node /^Beijing\-IDC\-web0\\d\+\\\-jfedu\\.net { include ntp} | | --- | 如上规则会匹配所有在jfedu.net域并且主机名以Beijing\-IDC开头,紧跟web01、web02、web03\...web100\...等节点,由此可以进行批量服务器的分组管理。 ### Puppet自动部署及同步网站 企业生产环境100台服务器,所有服务器要求要求数据一致,可以采用rsync同步,配置rsync服务器端,客户端执行脚本命令即可,同样可以使用Puppet\+Shell脚本来同步,这样比较快捷,也可以使用Puppet rsync模块。 1. Puppet服务器端配置,/etc/puppet/modules/www/manifests/init.pp代码如下: | class www { Exec { path \=\>"/bin:/sbin:/bin/sh:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"} file { "/data/sh/rsync\_www\_client.sh": source \=\>"puppet://192\-9\-117\-162\-tdt.com/files/www/rsync\_www\_client.sh", owner \=\>"root", group \=\>"root", mode \=\>"755", } file { "/etc/rsync.pas": source \=\>"puppet://192\-9\-117\-162\-tdt.com/files/www/rsync.pas", owner \=\>"root", group \=\>"root", mode \=\>"600", } exec { "auto backup www data": command \=\>"mkdir \-p /data/backup/\`date \+%Y%m%d\`;mv /data/index /data/backup/www/\`date \+%Y%m%d\` ; /bin/sh /data/sh/rsync\_www\_client.sh ", user \=\>"root", subscribe \=\>File\["/data/sh/rsync\_www\_client.sh"],refreshonly \=\>"true", } } | | --- | 1. 在/etc/puppet/manifests目录创建两个文件,分别为modules.pp和nodes.pp,模块入口文件以及node配置段。 modules.pp配置文件内容如下: | import "www" | | --- | nodes.pp配置文件内容如下: | node /^Beijing\-IDC\-web0\\d\+\\\-jfedu\\.net {include www} | | --- | 1. 在site.pp 中加载导入modules.pp 和nodes.pp名称,site.pp代码如下: | import "modules.pp"import "nodes.pp" | | --- | Puppet master端批量执行通知客户端来同步配置,命令如下: | puppet kick \-d \-\-host \`cat hosts.txt\` | | --- | 1. cat hosts.txt内容为需要同步的客户端的主机名: | Beijing\-IDC\-web01\-jfedu.net Beijing\-IDC\-web02\-jfedu.net Beijing\-IDC\-web03\-jfedu.net Beijing\-IDC\-web04\-jfedu.net | | --- | # 企业级Docker虚拟化平台实战 ## 虚拟化技术概述及简介 IT行业发展到今天,已经从传统技术、传统运维发展到当下的主流技术、自动化运维,未来掌握核心技术是赶上时代变化,拉开跟别人差距的最关键因素。当下主流的IT三大技术:虚拟化、云计算、大数据之一的虚拟化技术。虚拟化技术也越来越广泛的应用在企业中,例如百度、阿里巴巴、腾讯、京东、Google等。 通俗的说,虚拟化就是把物理资源转变为逻辑上可以管理的资源,以打破物理结构间的壁垒,计算元件运行在虚拟的基础上而不是真实的基础上,可以扩大硬件的容量,简化软件的重新配置过程。 虚拟化技术允许一个平台同时运行多个操作系统,并且应用程序都可以在相互独立的空间内运行而互不影响,从而显著提高计算机的工作效率,是一个为了简化管理,优化资源的解决方案。 虚拟化解决方案的底部是要进行虚拟化的物理机器,这台机器可能直接支持虚拟化,也可能不会直接支持虚拟化,那么就需要系统管理程序层的支持。虚拟机管理程序(Virtual machine monitor),或称为 VMM,可以看作是平台硬件和操作系统的抽象化,VMM本质是我们常说的虚拟化技术软件。 ## 互联网虚拟化技术种类 * KVM * ESXI * XEN * Docker * Hyper\-V * Open\-vz ## KVM虚拟化概念 KVM虚拟化全称为kernel\-based Virtual Machine,是一个开源的系统虚拟化模块,基于内核的虚拟机 (KVM) 是针对包含虚拟化扩展(Intel VT 或 AMD\-V)的 x86 硬件上的 Linux 的完全原生的虚拟化解决方案。 KVM是目前早期互联网广泛使用的虚拟化软件之一,最早由以色列的公司开发,现在已经被RedHat公司斥资1\.07亿美元收购了KVM虚拟化管理程序厂商Qumranet,KVM虚拟化技术严格来讲,不是一个软件,而是Linux 内核里面的一种加速虚拟机的功能扩展。 自Linux 2\.6\.20之后集成在Linux的各个主要发行版本中。KVM的虚拟化需要硬件支持(如Intel VT技术或者AMD V技术)属于完全虚拟化。了解KVM之前,我们就需要了解KVM和QEMU、Libvirt有什么关系呢? KVM是一款支持虚拟机的技术,是Linux内核中的一个功能模块。它在Linux2\.6\.20之后的任何Linux分支中都被支持。它还有一个条件,对硬件要求的条件,必须达到一定标准的硬件架构。 Qemu是什么呢。其实它也是一款虚拟化技术,就算不使用kvm,单纯的qemu也可以完全实现一个虚拟机。 那为何还会有Qemu\-kvm这个名词呢?虽然kvm的技术已经相当成熟而且可以对很多东西进行隔离,但是在某些方面还是无法虚拟出真实的机器。比如对网卡的虚拟,这个时候就需要另外的技术来做补充,而qemu\-kvm则是这样一种技术。它补充了kvm技术的不足,而且在性能上对kvm进行了优化。 Libvirt又是什么呢。它是一系列提供出来的库函数,用以其他技术调用,来管理机器上的虚拟机。包括各种虚拟机技术,kvm、xen与lxc等,不同虚拟机技术就可以使用不同驱动,都可以调用libvirt提供的api对虚拟机进行管理。我们创建的各种虚拟机都是基于libvirt库及相关命令去管理的。 ![IMG_257](/media/202411/20241125143347352676.png) ## ESXI虚拟化技术概念 Vmware 服务器虚拟化第一个产品命名为:ESX,后来Vmware在第4版本的时候推出了ESXI,ESXI和ESX的版本最大的技术区别是内核的变化。 从第4版本开始VMware把ESX及ESXi产品统称为vSphere,但是VMware从5版本开始以后取消了原来的ESX版本,所以现在VMware虚拟化产品vSphere其实本质是ESXI,只是两种叫法而已。官方称为vSphere虚拟化技术,个人也可以称为ESXI虚拟化技术。 VMware vSphere 是业界领先且最可靠的虚拟化平台。vSphere将应用程序和操作系统从底层硬件分离出来,从而简化了 IT操作。您现有的应用程序可以看到专有资源,而您的服务器则可以作为资源池进行管理。因此,您的业务将在简化但恢复能力极强的 IT 环境中运行。 VMware、vSphere、Essentials 和 Essentials Plus 套件专为工作负载不足 20 台服务器的 IT 环境而设计,只需极少的投资即可通过经济高效的服务器整合和业务连续性为小型企业提供企业级 IT 管理。结合使用 vSphere Essentials Plus 与 vSphere Storage Appliance软件,无需共享存储硬件即可实现业务连续性。 VMware ESXI虚拟化特点如下: * 确保业务连续性和始终可用的 IT; * 降低 IT 硬件和运营成本; * 提高应用程序质量; * 增强安全性和数据保护能力。 ## XEN虚拟化技术概念 XEN是一个基于X86架构、发展最快、性能最稳定、占用资源最少的开源虚拟化技术。Xen可以在一套物理硬件上安全的执行多个虚拟机,与 Linux 是一个完美的开源组合,Novell SUSE Linux Enterprise Server 最先采用了XEN虚拟技术。它特别适用于服务器应用整合,可有效节省运营成本,提高设备利用率,最大化利用数据中心的IT基础架构。 实际上XEN出现的时间要早于KVM虚拟化,它是由剑桥大学开发的,严格来讲,XEN是一个开源的虚拟机监视器,属于半虚拟化技术,其架构决定了它注定不是真正的虚拟机,只是自己运行了一个内核的例子。 XEN虚拟化,同时区分Xen\+pv\+和Xen\+hvm,其中pv只支持Linux,而hvm则支持Windows系统。除此之外,XEN还拥有更好的可用资源、平台支持、可管理性、实施、支持动态迁移和性能基准等优势。 ## Docker虚拟化技术概念 Docker是一款轻量级、高性能的虚拟化技术,是目前互联网使用最多的虚拟化技术,Docker虚拟化技术的本质类似集装箱机制,最早集装箱没有出现的时候,码头上有许多搬运的工人在搬运货物,集装箱出现以后,码头上看到更多的不是工人,而且集装箱的搬运模式更加单一,更加高效,还有其他的好处。 将货物多打包在集装箱里面,可以防止货物之间相互影响。并且到了另外一个码头需要转运的话,有了在集装箱以后,直接把它运送到另一个码头即可,完全可以保证里面的货物是整体的搬迁,并且不会损坏货物本身。 Docker技术机制跟集装箱类似,Docker虚拟化 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化。 Docker容器是完全使用沙箱机制,相互之间不会有任何接口,几乎没有性能开销,可以很容易地在机器和数据中心中运行。最重要的是,他们不依赖于任何语言、框架或包括系统。 Docker应该是近年最火爆的技术之一,如果没有听说过,那么你就out了,2019年将开启新的跨越。 Docker 自开源后受到广泛的关注和讨论,以至于 dotCloud 公司后来都改名为 Docker Inc。 Redhat 已经在其 RHEL6\.5 中集中支持Docker; Google 也在其 PaaS 产品中广泛应用,Docker 项目的目标是实现轻量级的操作系统虚拟化解决方案。 Docker的基础是 Linux 容器(LXC)等技术。在LXC的基础上 Docker 进行了进一步的封装,让用户不需要去关心容器的管理,使得操作更为简便。用户操作 Docker 的容器就像操作一个快速轻量级的虚拟机一样简单。 下面对比了Docker 和传统虚拟化(KVM、XEN、Hyper\-V、ESXI)结构层级方式的不同之处, 图为传统虚拟化结构图: ![IMG_258](/media/202411/20241125143347359218.png) 图为Docker虚拟化结构图:![IMG_259](/media/202411/20241125143347364447.png) * Docker虚拟化技术概念\&总结: Docker虚拟化技术是在硬件的基础上,基于现有的操作系统层面上实现虚拟化,直接复用本地主机的操作系统,直接虚拟生成Docker容器,而Docker容器上部署相关的APP应用(Apache、MYSQL、PHP、JAVA)。 * 传统虚拟化技术概念\&总结: KVM、XEN、ESXI传统虚拟化(完全、半虚拟化)是在硬件的基础上,基于现有的操作系统层面上实现虚拟化,但是不能复用本地主机的操作系统,而是必须虚拟出自己的Guest OS系统,然后在Guest OS系统上部署相关的APP应用(Apache、MYSQL、PHP、JAVA)。 Docker虚拟化跟传统VM比较具有如下优点: * 操作启动快: 运行时的性能可以获取极大提升,管理操作(启动,停止,开始,重启等等) 都是以秒或毫秒为单位的。 * 轻量级虚拟化: 你会拥有足够的“操作系统”,仅需添加或减小镜像即可。在一台服务器上可以布署100\~1000个Containers容器。但是传统虚拟化,你虚拟10\-20个虚拟机就不错了。 * 开源免费: 开源的,免费的,低成本的。由现代Linux内核支持并驱动。注\* 轻量的Container必定可以在一个物理机上开启更多“容器”,注定比VMs要便宜。 * 前景及云支持; 正在越来越受欢迎,包括各大主流公司都在推动docker的快速发展,性能有很大的优势。随着Go语言越来越被人熟知,Docker的使用也越来越广泛。 ## 虚拟化技术实现方式 * 完全拟化技术 通过软件实现对操作系统的资源再分配,比较成熟,完全虚拟化代表技术:KVM、ESXI、Hyper\-V; * 半虚拟化技术 通过代码修改已有的系统,形成一种新的可虚拟化的系统,调用硬件资源去安装多个系统,整体速度上相对高一点,半虚拟化代表技术:Xen; * 轻量级虚拟化: 介于完全虚拟化、半虚拟化之间,轻量级虚拟化代表技术:Docker。 ## Docker虚拟化特点 跟传统VM比较具有如下优点: * 操作启动快 运行时的性能可以获取极大提升,管理操作(启动,停止,开始,重启等等) 都是以秒或毫秒为单位的。 * 轻量级虚拟化 你会拥有足够的“操作系统”,仅需添加或减小镜像即可。在一台服务器上可以布署100\~1000个Containers容器。但是传统虚拟化,你虚拟10\-20个虚拟机就不错了。 * 开源免费 开源的,免费的,低成本的。由现代Linux内核支持并驱动。注\* 轻量的Container必定可以在一个物理机上开启更多“容器”,注定比VMs要便宜。 * 前景及云支持 正在越来越受欢迎,包括各大主流公司都在推动docker的快速发展,性能有很大的优势。 * 跟传统VM比较具有如下缺点: 目前知道的人比较少; 相关的中文技术资料欠缺; Go语言还未完全成熟。 ## 为什么使用Docker Docker 在如下几个方面具有较大的优势: * 更快速的交付和部署 Docker在整个开发周期都可以完美的辅助你实现快速交付。Docker允许开发者在装有应用和服务本地容器做开发。可以直接集成到可持续开发流程中。 开发者可以使用一个标准的镜像来构建一套开发容器,开发完成之后,运维人员可以直接使用这个容器来部署代码。 Docker 可以快速创建容器,快速迭代应用程序,并让整个过程全程可见,使团队中的其他成员更容易理解应用程序是如何创建和工作的。 Docker 容器很轻很快!容器的启动时间是秒级的,大量地节约开发、测试、部署的时间。 * 高效的部署和扩容 Docker 容器几乎可以在任意的平台上运行,包括物理机、虚拟机、公有云、私有云、个人电脑、服务器等。 这种兼容性可以让用户把一个应用程序从一个平台直接迁移到另外一个。 Docker的兼容性和轻量特性可以很轻松的实现负载的动态管理。你可以快速扩容或方便的下线的你的应用和服务,这种速度趋近实时。 * 更高的资源利用率 Docker 对系统资源的利用率很高,一台主机上可以同时运行数千个 Docker 容器。容器除了运行其中应用外,基本不消耗额外的系统资源,使得应用的性能很高,同时系统的开销尽量小。传统虚拟机方式运行 10 个不同的应用就要起 10 个虚拟机,而Docker 只需要启动 10 个隔离的应用即可。 * 更简单的管理 使用 Docker,只需要小小的修改,就可以替代以往大量的更新工作。所有的修改都以增量的方式被分发和更新,从而实现自动化并且高效的管理。 ## Docker引擎架构 docker引擎是一个C/S结构的应用,组件如图所示: ![http://hainiubl.com/images/2016/engine-components-flow.png?_=6822905](/media/202411/20241125143347371464.png) Server是一个常驻进程; REST API 实现了client和server间的交互协议; CLI 实现容器和镜像的管理,为用户提供统一的操作界面。 Docker使用C/S架构,Client 通过接口与Server进程通信实现容器的构建,运行和发布。client和server可以运行在同一台集群,也可以通过跨主机实现远程通信,架构如图所示: ![1](/media/202411/20241125143347376886.png) ## Docker镜像\&容器\&仓库 熟悉了Docker虚拟化简介、组件和工作原理之后,还需要掌握Docker虚拟化镜像原理\&引擎架构等知识。 Docker虚拟化技术有三个基础概念:Docker镜像、Docker容器、Docker仓库,三个概念详解如下: 1)Docker镜像 Docker虚拟化最基础的组件为镜像,镜像跟我们常见的Linux ISO镜像类似,但是Docker镜像是分层结构的,是由多个层级组成,每个层级分别存储各种软件实现某个功能,Docker镜像是静止的、只读的,不能对镜像进行写操作。 2)Docker容器: Docker容器是Docker虚拟化的产物,也是最早在生产环境使用的对象,Docker容器的底层是Docker镜像,是基于镜像运行,并且在镜像最上层添加一层容器层之后的实体,容器层是可读、可写的,容器层如果需用到镜像层中的数据,可以通过JSON文件读取镜像层中的软件和数据,对整个容器进行修改,只能作用于容器层,不能直接对镜像层进行写操作。 3)Docker仓库: Docker仓库是用于存放Docker镜像的地方,Docker仓库分为两类,分别是:公共仓库(Public)和私有仓库(Private),国内和国外有很多默认的公共仓库,对外开放、免费或者付费使用,企业测试环境和生产环境推荐自建私有仓库,私有仓库的特点:安全、可靠、稳定、高效,能够更加自身的业务体系进行灵活升级和管理。 ## CentOS6\.x(6\.5\+)Linux Docker平台实战 掌握了Docker虚拟化概念和原理之后,最重要的就是要在生产环节中落地Docker,Docker虚拟化平台最早期只支持Linux操作系统,现在最新版Windows操作系统也慢慢支持Docker虚拟化。 本章节将选择不同的发行版本来构建Docker虚拟化平台,Linux操作系统主流发行版本包括:Red Hat Linux、CentOS、Ubuntu、SUSE Linux、Fedora Linux等,如下简要介绍即将部署Docker虚拟化平台的两个系统:CentOS和Ubuntu。 Docker官方要求Linux内核版本在3\.8\+以上,生产环境中尽量推荐使用3\.10\+的Linux内核版本,Docker从1\.13版本起,采用时间线的方式作为版本号,Docker版本现在基于YY.MM,分为社区版(Community Edition)和企业版( Enterprise Edition),社区版是免费提供给个人开发者和小型团体使用的,而企业版会提供额外的收费服务。 社区版按照Stable和Edge两种方式发布,每个季度更新Stable版本,如17\.06,17\.09,每个月份更新Edge版本,如17\.09,17\.10。 虚拟化\&Docker虚拟化技术本质的用途: 为了最大化的利用高配物理机的资源,提高硬件设备服务器的资源利用率,淘汰一些老、旧服务器,对老、旧服务器进行资源的重组、重用,满足企业飞快的发展。 虚拟化落地实施硬件设备选配上,尽量使用高配物理机资源,参考配置如下: * 服务器品牌:Dell R730、R820; * CPU配置:Intel 至强E5\-2600系列; * MEM配置:ECC DDR3 256G; * DISK配置:SAS 12TB(最大支持24T); * NET配置:Intel四端口千兆网卡/双端口万兆网卡; 1. 安装步骤和命令如下: | \#安装Epel扩展源;yum install epel\-release \-y\#安装Docker\-io版本;yum install docker\-io lxc cgroup device\-mapper\* \-y\#查Docker版本是否安装;rpm \-qa\|grep \-E "docker\|lxc\|device\-mapper"\#启动Docker引擎服务;service docker restart\#查看Docker服务进程;ps \-ef\|grep docker | | --- | 1. 安装完成,如图所示: ![I6DC]%3]3~$1%11TL@W[A9Q](/media/202411/20241125143347384327.png) 1. 查看启动进程如图所示: ![$VCCY{I5D5L1YUZ96]1E7KJ](/media/202411/20241125143347389404.png) 1. 查看docker info信息,如图所示: ![{42UCHGEF]I$ZMRL98NKX1H](/media/202411/20241125143347394392.png) 1. 从Docker仓库下载Nginx镜像: ![B_[RWXE111NV{Z$)B@}5DQB](/media/202411/20241125143347399497.png) ## CentOS7\.x(7\.0\+)Linux Docker平台实战 1. 安装步骤和命令如下: | \#安装国内阿里源;wget \-P /etc/yum.repos.d/ http://mirrors.aliyun.com/docker\-ce/linux/centos/docker\-ce.repo \#安装Docker\-CE版本;yum install docker\-ce\* \-y\#查Docker版本是否安装;rpm \-qa\|grep \-E "docker"\#启动Docker引擎服务;service docker restartsystemctl restart docker.service\#查看Docker服务进程;ps \-ef\|grep docker | | --- | 1. 安装完成,如图所示: ![EQXWUU%W4P)4I`5GAR0UDM8](/media/202411/20241125143347404975.png) 1. 查看启动进程如图所示: ![K$ZI)FHJ(Z6VPEK7@XOWQGF](/media/202411/20241125143347409979.png) 1. 查看docker info信息,如图所示: ![I}DG6}RP)3G~IK1HR@Y$GVG](/media/202411/20241125143347415023.png) 1. 从Docker仓库下载Nginx镜像: ![}[`BX7S~EL9O[YO$80OC`BQ](/media/202411/20241125143347421610.png) ## Ubuntu(16\.04\+)Linux Docker平台实战 1. 安装步骤和命令如下: | \#更新apt源;apt\-get update | | --- | ![[T`A_@JHGH$P_2YUM7V)8ZA](/media/202411/20241125143347426838.png) \#APT源使用 HTTPS 以确保软件下载过程中不被篡改。需要添加使用HTTPS 传输的软件包以及 CA 证书。 | apt\-get install \\apt\-transport\-https \\ca\-certificates \\curl \\software\-properties\-common | | --- | \#默认APT访问国外源,网络非常慢,此处建议使用国内源,需要添加软件源的 GPG 密钥; | curl \-fsSL [https://mirrors.ustc.edu.cn/docker\-ce/linux/ubuntu/gpg](https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg) \| sudo apt\-key add \-\#curl \-fsSL <https://download.docker.com/linux/ubuntu/gpg> \| sudo apt\-key add \- | | --- | \#向 source.list 中添加 Docker 软件源; | add\-apt\-repository \\"deb \[arch\=amd64] [https://mirrors.ustc.edu.cn/docker\-ce/linux/ubuntu](https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu) $(lsb\_release \-cs) stable"\#官方源\#add\-apt\-repository "deb \[arch\=amd64] <https://download.docker.com/linux/ubuntu> $(lsb\_release \-cs) stable" | | --- | \#更新 apt 软件包缓存; apt\-get update \#基于apt\-get 安装docker\-ce社区版本; apt\-get install docker\-ce ![XUEEQ`1Q{72UV}8NUKZ5M)6](/media/202411/20241125143347434057.png) \#查Docker版本是否安装; dpkg \-s docker\-ce ![Y}8A4`7UW2CGJSENRL{{DL2](/media/202411/20241125143347438946.png) \#启动Docker引擎服务; service docker restart systemctl restart docker \#查看Docker服务进程; ps \-ef\|grep docker 1. 安装完成,如图所示: ![YVJ5AZB}R5J$}0OVLH$K_XI](/media/202411/20241125143347444397.png) 1. 查看启动进程如图所示: ![@$W@AW2E{((Y}TCW3}8DGGT](/media/202411/20241125143347449590.png) 1. 查看docker info信息,如图所示: ![@5NKD%F$S}Q`4UDSD6)1Q$3](/media/202411/20241125143347454443.png) 1. 从Docker仓库下载Nginx镜像: ![ZO})XTKTC(CGT6QFTR[JX`R](/media/202411/20241125143347459388.png) ## Docker仓库源更新实战 Docker默认连接的国外官方镜像,通常根据网络情况不同,访问时快时慢,大多时候获取速度非常慢,为了提示效率可以自建仓库或者先修改为国内仓库源,提升拉取镜像的速度。 Docker可以配置的国内镜像有很多可供选择,例如:Docker中国区官方镜像、阿里云、网易蜂巢、DaoCloud等,这些都是国内比较快的镜像仓库。 从国外官网下载Docker Tomcat镜像,访问速度慢,如图所示: ![](/media/202411/20241125143347464626.png) Docker镜像修改方法,vim /etc/docker/daemon.json,执行如下命令即可: | cat\>/etc/docker/daemon.json\<\<EOF{"registry\-mirrors":\["https://registry.docker\-cn.com"]}EOFservice docker restart | | --- | 重启Docker服务即可,修改仓库地址为国内仓库后,获取镜像速度非常快,如图所示: ![](/media/202411/20241125143347469959.png) ## Docker典型命令演练 Docker虚拟化平台部署完成,默认没有图形界面管理,作为运维人员、测试人员、开发人员来讲,需要通过Docker\-Client命令行操作,如下为Docker平台下30\+操作指令,熟练指令的操作能够帮助我们对Docker进行高效的管理和维护,从而提高自己的技能。 ### docker search命令实战 \#从Docker仓库中搜索Nginx镜像; docker search nginx \#从Docker仓库中搜索Tomcat镜像; docker search tomcat ### docker pull命令实战 \#从Docker仓库下载nginx镜像; docker pull docker.io/nginx \#从Docker仓库下载tomcat镜像; docker pull docker.io/tomcat ![@WU(U(S(0PP8GOJ}~{3I4ZU](/media/202411/20241125143347478066.png) ### docker images命令实战 \#查看已下载的本地Docker镜像列表 docker images ![$Q5}HQ98F5SI%83@]S9NX_J](/media/202411/20241125143347483827.png) ### docker run命令实战 \#基于docker run启动nginx镜像,并且启动到/bin/bash解释器; docker run \-itd docker.io/nginx /bin/bash \-i表示:interactive交互; \-t表示:tty终端; d表示:daemon后台启动; \#基于docker run启动nginx镜像,启动到/bin/bash解释器,同时映射本地80端口至容器80端口; docker run \-p 80:80 \-itd docker.io/nginx /bin/bash \#\-p端口映射,第一个80宿主机监听端口,第二个80端口为容器监听; \#浏览器输入宿主机IP\+80端口,即可访问容器中的80端口所在服务; ![@SC}F%(`0$6$2(V7XIXI29H](/media/202411/20241125143347489715.png) ### docker ps命令实战 \#查看当前正在运行中的容器; docker ps \#查看当前Linux系统所有容器,包括运行和已经停止、其他容器(所有容器) docker ps \-a ![9}]~@264BMS{]@F00J{J7H8](/media/202411/20241125143347495264.png) ### docker inspect命令实战 \#查看容器详细信息; docker inspect 55e339c80051 \#查看容器详细信息,并且从信息中过滤IP地址; docker inspect 55e339c80051\|grep \-i ipaddr ![``UXIQ$IJ[36)6KI2Q~OWSY](/media/202411/20241125143347501210.png) ### docker exec命令实战 \#在Docker中容器运行指令:df \-h; docker exec 55e339c80051 df \-h \#在Docker中容器/tmp目录创建jfedu.txt文件; docker exec 55e339c80051 touch /tmp/test.txt \#进入Docker容器/bin/bash终端,然后执行df \-h指令; docker exec \-it 55e339c80051 /bin/bash df \-h ![YE1XIYPOCLH6D2E2AFCK{IY](/media/202411/20241125143347506663.png) ### docker stop\|start命令实战 \#基于stop停止正在运行中的容器; docker stop 55e339c80051 \#基于start启动已经停止的容器; docker start 55e339c80051 ![$YRG83UD6[C7{`LNLV359K8](/media/202411/20241125143347512463.png) ### docker kill命令实战 \#Kill掉正在运行中某个容器; docker kill 55e339c80051 ![]5O`$JJUH(OW3C5MZS4P6UB](/media/202411/20241125143347518143.png) ### docker rm命令实战 \#删除某个指定的已经停止Docker容器; docker rm dc455c12ca7d \#强制删除某个指定的正在运行中的Docker容器; docker rm \-f 55e339c80051 ![SHG62WC58%[_O$%]H_@YYZC](/media/202411/20241125143347523828.png) ### docker rmi命令实战 \#从Docker images列表中删除某个镜像; docker rmi 78b258e36eed \#从Docker images列表中删除多个镜像; docker rmi e81eb098537d 415381a6cb81 ![3RU567T0PFVRCUQ@}$P8]NJ](/media/202411/20241125143347528993.png) ## CentOS6\.x Docker桥接网络实战 基于CentOS6\.x构建Docker桥接网络,案例方法如下: Docker0桥接网络可以自定义,如下为自定义桥接网络的设置: | /etc/init.d/docker stop关掉docker0ifconfig docker0 down删除dockerbrctl delbr docker0增加网桥br0yum install bridge\-utilsCentOS6\.5下的配置:vim /etc/sysconfig/dockerother\_args\="\-b\=br0" | | --- | ![](/media/202411/20241125143347534829.png) 除此之外,配置bridge桥接网络可以直接设置网卡配置文件: /etc/sysconfig/network\-scripts/下,修改ifcfg\-eth0网卡配置,同时增加ifcfg\-br0桥接网卡配置,操作流程如下: vi ifcfg\-eth0内容修改为如下: | DEVICE\=eth0BOOTPROTO\=noneNM\_CONTROLLED\=noONBOOT\=yesTYPE\=EthernetBRIDGE\="br0"IPADDR\=192\.168\.43\.81NETMASK\=255\.255\.255\.0GATEWAY\=192\.168\.43\.1USERCTL\=no | | --- | vi ifcfg\-br0内容如下: | DEVICE\="br0"BOOTPROTO\=noneIPV6INIT\=noNM\_CONTROLLED\=noONBOOT\=yesTYPE\="Bridge"IPADDR\=192\.168\.43\.81NETMASK\=255\.255\.255\.0GATEWAY\=192\.168\.43\.1USERCTL\=no | | --- | ![](/media/202411/20241125143347542195.png) 启动docker服务 /etc/init.d/docker start 查看服务器网卡信息如下: ![](/media/202411/20241125143347550423.png) 启动一个新的docker客户端,查看客户端ip如下: 进入已经启动过的容器命令:docker attach 容器ID 即可。 ![](/media/202411/20241125143347555578.png) 从外网下载nginx包: ![](/media/202411/20241125143347560434.png) ## CentOS7\.x Docker桥接网络实战 基于CentOS7\.x构建Docker桥接网络,案例方法如下: 配置bridge桥接网络可以直接设置网卡配置文件: /etc/sysconfig/network\-scripts/下,修改ifcfg\-ens33网卡配置,同时增加ifcfg\-br0桥接网卡配置,操作流程如下: vi ifcfg\-ens33内容修改为如下: | DEVICE\=ens33BOOTPROTO\=noneNM\_CONTROLLED\=noONBOOT\=yesTYPE\=EthernetBRIDGE\="br0"IPADDR\=192\.168\.43\.81NETMASK\=255\.255\.255\.0GATEWAY\=192\.168\.43\.1USERCTL\=no | | --- | vi ifcfg\-br0内容如下: | DEVICE\="br0"BOOTPROTO\=noneIPV6INIT\=noNM\_CONTROLLED\=noONBOOT\=yesTYPE\="Bridge"IPADDR\=192\.168\.43\.81NETMASK\=255\.255\.255\.0GATEWAY\=192\.168\.43\.1USERCTL\=no | | --- | 启动docker服务,即可; service docker start Docker默认提供了一个隔离的内网环境,启动时会建立一个docker0的虚拟网卡,每个容器都是连接到docker0网卡上的。而docker0的ip段为172\.17\.0\.1,如果想让容器与宿主机同一网段的其他机器访问,就必须在启动docker的时候将某个端口映射到宿主机的端口。 KVM的桥接网络非常方便,其实docker也比较方便,至少不是自带的桥接而已,上次课程我们讲解了docker容器在centos6\.5下的实现方法,今天我们来讲解centos7下如果快速实现docker容器桥接网络,并为容器分配外网IP。如下为通过pipework工具配置容器IP方法: | 安装pipeworkgit clone https://github.com/jpetazzo/pipeworkcp \~/pipework/pipework /usr/local/bin/启动容器并设置网络docker run \-itd \-\-net\=none \-\-name\=lamp2 centos7 /bin/bashpipework br0 lamp2 192\.168\.1\.11/24@192\.168\.1\.88进入容器查看ipdocker exe lamp2 ifconfig | | --- | ![](/media/202411/20241125143347567103.png) ## 基于Docker构建JAVA服务器实战 Tomcat是由Apache软件基金会下属的[Jakarta项目](http://zh.wikipedia.org/wiki/Jakarta项ç®" \o "Jakarta项目)开发的一个[Servlet](http://zh.wikipedia.org/wiki/Servlet" \o "Servlet)容器,按照[Sun Microsystems](http://zh.wikipedia.org/wiki/Sun_Microsystems" \o "Sun Microsystems)提供的技术规范,实现了对[Servlet](http://zh.wikipedia.org/wiki/Servlet" \o "Servlet)和[JavaServer Page](http://zh.wikipedia.org/wiki/JavaServer_Page" \o "JavaServer Page)([JSP](http://zh.wikipedia.org/wiki/JSP" \o "JSP))的支持,Tomcat本身也是一个HTTP服务器,可以单独使用,apache是一个以C语言编写的HTTP服务器。Tomcat主要用来解析JSP语言。目前最新版本为8\.0。 Tomcat安装配置 安装tomcat之前需要安装jdk (Java Development Kit) 是 Java 语言的软件开发工具包(SDK)),这里选择jdk\-6u18\-linux\-x64\-rpm.bin,bin文件安装跟sh文件方法一样,sh ./jdk\-6u18\-linux\-x64\-rpm.bin,回车即可,默认安装到/usr/java/jdk1\.6\.0\_18目录下。 配置java环境变量,vi /etc/profile 添加如下代码: | export JAVA\_HOME\=/usr/java/jdk1\.6\.0\_18 export CLASSPATH\=$CLASSPATH:$JAVA\_HOME/lib:$JAVA\_HOME/jre/lib export PATH\=$JAVA\_HOME/bin:$JAVA\_HOME/jre/bin:$PATH:$HOMR/bin | | --- | 使环境变量立刻生效; source /etc/profile 查看java版本,显示版本为1\.6\.0\_18,证明安装成功; java \-version 官网下载tomcat相应版本:apache\-tomcat\-6\.0\.30\.tar.gz,执行如下命令部署Tomcat: | tar \-xzf apache\-tomcat\-6\.0\.30\.tar.gzmv apache\-tomcat\-6\.0\.30 /usr/local/tomcat/usr/local/tomcat/bin/startup.sh | | --- | 查看ps \-ef \|grep tomcat 进程及端口是否存在; 通过页面访问Tomcat默认测试页面如下: ![](/media/202411/20241125143347574283.jpeg) 如何创建自定义的网站页面呢,定义自己的发布目录,方法如下: server.xml配置文件末尾加入代码: | \<Context path\="/" docBase\="/data/webapps/www" reloadable\="true"/\> | | --- | ![](/media/202411/20241125143347581445.jpeg) /data/webapps/www创建自己的jsp代码,重启tomcat即可访问。 ## 基于Docker WEB管理Docker容器 通常来讲,开发人员和管理人员默认通过命令行来创建及运行Docker容器,但Docker的Remote API让他们可以通过充分利用REST(代表性状态传输协议)的API,运行相同的命令。 DockerUI也是基于API方式管理宿主机的Docker引擎。Docker UI Web前端程序让你可以处理通常通过Web浏览器的命令行来管理的许多任务。 主机上的所有容器都可以通过仅仅一条连接来处理,该项目几乎没有任何依赖关系。该软件目前仍在大力开发之中,但是它采用麻省理工学院(MIT)许可证,所以可以免费地重复使用。 Docker UI不包含任何内置的身份验证或安全机制,所以务必将任何公之于众的DockerUI连接放在用密码来保护的系统后面。 1. 下载Docker UI镜像; 只需要在宿主机pull相关的镜像即可,指令如下: docker pull uifd/ui\-for\-docker docker images ![](/media/202411/20241125143347588650.png) 1. 启动docker\-UI服务,并且映射9090至容器9090; docker run \-it \-d \-\-name docker\-web \-p 9000:9000 \-v /var/run/docker.sock:/var/run/docker.sock docker.io/uifd/ui\-for\-docker ![](/media/202411/20241125143347593926.png) 1. 如果启动Docker端口映射,报错信息如下: docker0: iptables: No chain/target/match by that name. 解决方法: 如上报错信息是因为本地iptables规则策略没有匹配的链表,解决方案如下: pkill docker iptables \-t nat \-F ifconfig docker0 down yum install \-y bridge\* \-y brctl delbr docker0 service docker restart ![](/media/202411/20241125143347599761.png) 1. 通过docker ps 查看Docker UI状态; ![](/media/202411/20241125143347605334.png) 1. 通过浏览器登录WEB 9000端口访问如图所示: ![](/media/202411/20241125143347611138.png) ![](/media/202411/20241125143347616861.png) ![](/media/202411/20241125143347622206.png) 1. 选择WEB界面images镜像列表,如图所示: ![](/media/202411/20241125143347628805.png) 1. 基于镜像启动Docker容器虚拟机,并且实现端口映射,如图所示: ![](/media/202411/20241125143347634201.png) ![](/media/202411/20241125143347639455.png) ![](/media/202411/20241125143347644566.png) 1. 创建Docker容器之后,通过浏览器实现访问81端口,如图所示: ![](/media/202411/20241125143347649533.png) 1. Docker容器资源WEB监控如图所示: ![](/media/202411/20241125143347656231.png) ![](/media/202411/20241125143347661053.png) ## Docker Tomcat性能优化 线上环境使用默认tomcat配置文件,性能很一般,为了满足大量用户的访问,需要对tomcat进行参数性能优化,具体优化的地方如下: * Linux内核的优化; * 服务器资源配置的优化; * Tomcat参数优化; * 配置负载集群优化; Tomcat参数的优化:Server.xml文件,关闭DNS查询、配置最大并发等参数。 | maxThreads:tomcat起动的最大线程数,即同时处理的任务个数,默认值为200acceptCount:当tomcat起动的线程数达到最大时,接受排队的请求个数,默认值为100当然这些值都不是越大越好,需要根据实际情况来设定。可以基于测试的基础上来不断的调优分析。Server.xml里面优化如下:\<Connector port\="8080" protocol\="org.apache.coyote.http11\.Http11NioProtocol" connectionTimeout\="20000" redirectPort\="8443" maxThreads\="5000" minSpareThreads\="20" acceptCount\="1000" disableUploadTimeout\="true" enableLookups\="false" URIEncoding\="UTF\-8" /\>Catalina.sh JVM参数优化,添加如下内容:CATALINA\_OPTS\="$CATALINA\_OPTS –Xms4000M –Xmx4000M –Xmn1000M \-XX:SurvivorRatio\=4 \-XX:\+UseConcMarkSweepGC \-XX:CMSInitiatingOccupancyFraction\=82 \-DLOCALE\=UTF\-16LE \-DRAMDISK\=/ \-DUSE\_RAM\_DISK\=ture \-DRAM\_DISK\=true"配置多个tomcat实例,方法也很简单,只需要在服务器上cp多个tomcat,然后修改三个端口和发布目录即可,然后分别启动即可。为了提升整个网站的性能,还需要在tomcat前面架设nginx web反向代理服务器,用以提高用户高速访问。 | | --- | ![](/media/202411/20241125143347667599.png) ## Docker生产环境资源监控方案\&监控实战 Docker虚拟化平台自带了Docker容器(虚拟机)资源监控的功能,通过对docker容器的资源监控,我们可以随时掌握容器进行相关的资源性能,对容器性能进行更好的评估。通常而言,监控容器资源的指标,主要包括以下方面: * 容器的CPU情况和使用量; * 容器的内存情况和使用量; * 容器的本地镜像情况; * 主机的容器运行情况; 例如:使用docker ps \-a ,docker images命令查看容器的本地镜像、容器运行的情况,使用docker stats命令可以监控相关容器实例情况。 ### docker stats监控工具 1)查看本地镜像和容器列表,命令如下: docker images docker ps ![IMG_257](/media/202411/20241125143347673967.png) 2)通过docker stats查看所有运行的容器的资源,如图所示: docker stats ![IMG_258](/media/202411/20241125143347678963.png) 3)通过docker stats 容器id,查看指定容器的资源,如图所示: docker stats 1d1c1a547f98 ![IMG_259](/media/202411/20241125143347684135.png) 4)通过docker stats 容器id,\-\-nostream非流式查看容器资源: docker stats 1d1c1a547f98 \-\-no\-stream 获取容器CPU的信息; docker stats 1d1c1a547f98 \-\-no\-stream\|awk 'NR\>1 {print $1,"CPU:"$3}' 获取容器MEM的信息; docker stats 1d1c1a547f98 \-\-no\-stream\|awk 'NR\>1 {print $1,"MEM:"$4}' 获取容器IO读写的信息; docker stats 1d1c1a547f98 \-\-no\-stream\|awk 'NR\>1 {print $1,"IO:"$(NF\-1\)}' 如果想看到更为详细的容器属性,还可以通过netcat,使用Docker远程API来查看。发送一个HTTP GET请求/containers/\[CONTAINER\_NAME],其中CONTAINER\_NAME是你想要统计的容器名称。你可以从这里看到一个容器stats请求的完整响应信息。在上述的例子中你会得到CPU、IO以及内存的详细信息。 当然这种方式并不会令人接受,大家还是希望能够看到非常直观,详细的可视化界面。 ### CAdvisor监控工具 CAdvisor 是 google 开发的容器监控工具,CAdvisor是一个易于设置并且非常有用的工具,我们不用SSH到服务器才能查看资源消耗,而且它还给我们生成了图表。此外当集群需要额外的资源时,压力表(pressure gauges )提供了快速预览。而且,CAdvisor是免费的,并且还开源。 它的资源消耗也比较低。但是它有它的局限性,它只能监控一个Docker主机。因此如果你是多节点的话,那就比较麻烦,我们需要在所有的主机上都安装一个CAdvisor。值得注意的是,如果你使用的是Kubernetes,你可以使用heapster来监控多节点集群。在图表中的数据仅仅是时长一分钟的移动窗口,并没有方法来查看长期趋势。如果资源使用率在危险水平,它却没有生成警告的机制。 如果在Docker节点的资源消耗方面,你没有任何可视化界面,那么CAdvisor是一个不错的开端来带你步入容器监控,然而如果你打算在你的容器中运行任何关键任务,那你就需要一个更强大的工具或者方法。 ### CAdvisor部署配置 1)下载cadvisor镜像,命令如下: docker pull google/cadvisor 2)基于镜像启动cadvisor容器,命令如下: docker run \-v /var/run:/var/run:rw \-v /sys:/sys:ro \-v /var/lib/docker:/var/lib/docker:ro \-p 8080:8080 \-d \-\-name cadvisor google/cadvisor 3)通过浏览器访问cadviosr 8080端口,如图所示: [http://106\.12\.133\.186:8080/containers/](http://106.12.133.186:8080/containers/) ![2NB_49B%IATGC{CHVIW0W(V](/media/202411/20241125143347690187.png) 4)查看某个容器的详细资源,如图所示: ![RJSJV[J$(GE$77IZNY[(PLI](/media/202411/20241125143347695052.png) ![CST~KSC43]A3R[G`YGJHSKS](/media/202411/20241125143347700085.png) ### 构建Cadvisor\+InfluxDB\+Grafana平台 1. CAdvisor简介 CAdvisor提供的操作界面略显简陋,而且需要在不同页面之间跳转,模拟只能监控一台服务器,这不免会让人质疑它的实用性。但 cAdvisor 的一个亮点是它可以将监控到的数据导出给第三方工具,由这些工具进一步加工处理。 我们可以把 cAdvisor 定位为一个监控数据收集器,收集和导出数据是它的强项,而非展示数据。 1. InfluxDB简介 InfluxDB是用Go语言编写的一个开源分布式时序、事件和指标数据库,无需外部依赖。类似的数据库有Elasticsearch、Graphite等。 1. Grafana Grafana是一个可视化面板(Dashboard),有着非常漂亮的图表和布局展示,功能齐全的度量仪表盘和图形编辑器,支持Graphite、zabbix、InfluxDB、Prometheus和OpenTSDB作为数据源。Grafana主要特性:灵活丰富的图形化选项;可以混合多种风格;支持白天和夜间模式,多个数据源。 1. Cadvisor\+InfluxDB\+Grafana部署 Cadvisor\+InfluxDB\+Grafana单独部署方式比较繁琐,此处采用Docker\-compose方式部署,首先编写compose.yml文件,然后启动compose相关容器服务即可。 1. Docker\-compose.yml文件代码如下: | version: '3'services: influxdb: image: tutum/influxdb:0\.9 container\_name: influxdb restart: always environment: \- PRE\_CREATE\_DB\=cadvisor ports: \- "8083:8083" \- "8086:8086" expose: \- "8090" \- "8099" volumes: \- influxdbData:/data cadvisor: image: google/cadvisor container\_name: cadvisor links: \- influxdb:influxsrv command: \-storage\_driver\=influxdb \-storage\_driver\_db\=cadvisor \-storage\_driver\_host\=influxsrv:8086 restart: always ports: \- "8080:8080" volumes: \- /:/rootfs:ro \- /var/run:/var/run:rw \- /sys:/sys:ro \- /var/lib/docker/:/var/lib/docker:ro grafana: image: grafana/grafana container\_name: grafana restart: always links: \- influxdb:influxsrv ports: \- "3000:3000" environment: \- HTTP\_USER\=admin \- HTTP\_PASS\=admin \- INFLUXDB\_HOST\=influxsrv \- INFLUXDB\_PORT\=8086 \- INFLUXDB\_NAME\=cadvisor \- INFLUXDB\_USER\=root \- INFLUXDB\_PASS\=rootvolumes: influxdbData: | | --- | 启动Docker\-compose,命令如下: docker\-compose up \-d ![_QV`BXM80T~HJXQCN8LL99J](/media/202411/20241125143347710048.png) 7)Docker\-compose默认会启动三个类别容器,分别为:grafana、cadvisor、influxdb,对外访问IP\+端口如下: * Grafana:[http://106\.12\.133\.186:3000/](http://106.12.133.186:3000/) * Cadvisor:[http://106\.12\.133\.186:8080/](http://106.12.133.186:8080/) * Influxdb:[http://106\.12\.133\.186:8086/](http://106.12.133.186:8086/) 8)通过浏览器访问Grafana WEB界面,默认用户名和密码:admin/admin,然后选择add\-database source,填写Influxdb数据库的IP和端口,数据库名:cadvisor,用户名和密码:admin/admin,如图所示: [http://106\.12\.133\.186:3000/login](http://106.12.133.186:3000/login) ![1A}L9V85U@DN$JE{]FA9AZN](/media/202411/20241125143347716378.png) ![BPXAZVN%N7VU`0MIV5VN8GL](/media/202411/20241125143347721637.png) ![M)~%NTK}2KB[RP8OJP245O1](/media/202411/20241125143347726717.png) 9)创建Grafana图像,设置监控项目,例如添加MEM内存使用监控,操作方法如下: ![AK6R7]N}Q9X8E]AN60GN%KE](/media/202411/20241125143347731863.png) ![[9[17W${)4VI20[~0W5DEON](/media/202411/20241125143347736849.png) 10)创建Grafana图像,设置监控项目,例如添加CPU使用监控,操作方法如下: ![J0B)(Y}CI]$CEZ9RZ(`DUZR](/media/202411/20241125143347742294.png) ![27GD`(EKL4PQI7BO)0Y8SCQ](/media/202411/20241125143347747085.png) ## Docker构建Nginx服务器实战 Nginx \[engine x]是[Igor Sysoev](http://sysoev.ru/en/)编写的一个HTTP和反向代理服务器,另外它也可以作为邮件代理服务器。 它已经在众多流量很大的俄罗斯网站上使用了很长时间,这些网站包括[Yandex](http://www.yandex.ru/)、[Mail.Ru](http://www.mail.ru/)、[VKontakte](http://www.vkontakte.ru/),以及[Rambler](http://www.rambler.ru/)。 据Netcraft统计,在2012年8月份,[世界上最繁忙的网站中有11\.48%](http://news.netcraft.com/archives/2012/08/02/august-2012-web-server-survey.html)使用Nginx作为其服务器或者代理服务器。目前互联网主流公司360、百度、新浪、腾讯、阿里等都在使用nginx作为自己的WEB服务器。 Nginx由内核和模块组成,其中,内核的设计非常微小和简洁,完成的工作也非常简单,仅仅通过查找配置文件将客户端请求映射到一个location block(location是Nginx配置中的一个指令,用于URL匹配),而在这个location中所配置的每个指令将会启动不同的模块去完成相应的工作。 Nginx相对于Apache优点: * 高并发响应性能非常好,官方Nginx处理静态文件并发5w/s * 反向代理性能非常好。(可用于负载均衡) * 内存和cpu占用率低。(为Apache的1/5\-1/10) * 功能较Apache少(常用功能均有) * 对php可使用cgi方式和fastcgi方式。 Nginx WEB安装 首先需要安装pcre库,然后再安装Nginx: \#安装pcre支持rewrite库,也可以安装源码,注\*安装源码时,指定pcre路径为解压 源码的路径,而不是编译后的路径,否则会报错 (make\[1]: \*\*\* \[/usr/local/pcre/Makefile] Error 127 错误) yum install pcre\-devel pcre \-y \#下载Nginx源码包 cd /usr/src ;wget \-c [http://nginx.org/download/nginx\-1\.4\.2\.tar.gz](http://nginx.org/download/nginx-1.4.2.tar.gz) \#解压Nginx源码包 tar \-xzf nginx\-1\.4\.2\.tar.gz \#进入解压目录,然后sed修改Nginx版本信息为WS cd nginx\-1\.4\.2 ; sed \-i \-e 's/1\.4\.2//g' \-e 's/nginx\\//WS/g' \-e 's/"NGINX"/"WS"/g' src/core/nginx.h \#预编译Nginx useradd www ;./configure \-\-user\=www \-\-group\=www \-\-prefix\=/usr/local/nginx \-\-with\- http\_stub\_status\_module \-\-with\-http\_ssl\_module \#.configure预编译成功后,执行make命令进行编译 make \#make执行成功后,执行make install 正式安装 make install \#自此Nginx安装完毕 /usr/local/nginx/sbin/nginx \-t 检查nginx配置文件是否正确,返回OK即正确。 \[root@localhost \~]\# /usr/local/nginx/sbin/nginx \-t nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful \[root@localhost \~]\# 然后启动nginx,/usr/local/nginx/sbin/nginx 回车即可。查看进程是否已启动: \[root@localhost \~]\# ps \-ef \|grep nginx nobody 5381 30285 0 May16 ? 00:04:31 nginx: worker process root 30285 1 0 2014 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx root 32260 32220 0 12:34 pts/0 00:00:00 grep nginx \[root@localhost \~]\# 然后我们可以通过docker 的ip去访问即可。 ## Docker构建LNAMP架构实战 LNAMP(Linux\+Nginx\+Apache\+Mysql\+PHP)架构受到很多IT企业的青睐,取代了原来认为很好的LNMP(Linux\+Nginx\+Mysql\+PHP)架构,那我们说LNAMP到底有什么优点呢,还得从Nginx和apache的优缺点说起。 Nginx处理静态文件能力很强,Apache处理动态文件很强而且很稳定,把二者综合在一块,性能提升很多倍。可能很多Linux SA在从事LNMP运维中,会发现PHP(fastcgi)模式会出现一些502错误的现象,这是因为Nginx\+PHP(fastcgi)组合不稳定的原因造成的。 YUM 安装LAMP方式: yum install httpd httpd\-tools mysql mysql\-server mysql\-devel php php\-devel php\-mysql \-y 源码安装LNAMP之Nginx yum install prce\-devel \-y ;cd /usr/src ;wget [http://nginx.org/download/nginx\-1\.6\.0\.tar.gz](http://nginx.org/download/nginx-1.6.0.tar.gz) ;cd nginx\-1\.6\.0 ;./configure \-prefix\=/usr/local/nginx \&\& make \&\&make install 源码安装LNAMP之Apache yum install apr\-devel apr\-util\-devel –y; cd /usr/src ; wget [http://mirror.bit.edu.cn/apache/httpd/httpd\-2\.2\.27\.tar.gz](http://mirror.bit.edu.cn/apache/httpd/httpd-2.2.27.tar.gz) ;tar xzf httpd\-2\.2\.27\.tar.gz ;cd httpd\-2\.2\.27 ;./configure \-\-prefix\=/usr/local/apache \-\-enable\-so \-\-enable\-rewrite \&\&make \&\&make install 源码安装LNAMP之MySQL cd /usr/src ;wget [http://downloads.mysql.com/archives/mysql\-5\.1/mysql\-5\.1\.63\.tar.gz](http://downloads.mysql.com/archives/mysql-5.1/mysql-5.1.63.tar.gz) ;tar xzf mysql\-5\.1\.63\.tar.gz ;cd mysql\-5\.1\.63 ;./configure \-\-prefix\=/usr/local/mysql \-\-enable\-assembler \&\&make \&\&make install ![](/media/202411/20241125143347755611.png)配置Mysql服务为系统服务: cp /usr/local/mysql/share/mysql/my\-medium.cnf /etc/my.cnf cp /usr/local/mysql/share/mysql/mysql.server /etc/rc.d/init.d/mysqld chkconfig \-\-add mysqld chkconfig \-\-level 345 mysqld on cd /usr/local/mysql useradd mysql chown \-R mysql.mysql /usr/local/mysql /usr/local/mysql/bin/mysql\_install\_db \-\-user\=mysql chown \-R mysql var /usr/local/mysql/bin/mysqld\_safe \-\-user\=mysql \& 源码安装LNAMP之PHP cd /usr/src ;wget [http://mirrors.sohu.com/php/php\-5\.3\.28\.tar.bz2](http://mirrors.sohu.com/php/php-5.3.28.tar.bz2) ;tar jxf php\-5\.3\.28\.tar.bz2 ;cd php\-5\.3\.28 ;./configure \-\-prefix\=/usr/local/php5 \-\-with\-config\-file\-path\=/usr/local/php/etc \-\-with\-apxs2\=/usr/local/apache/bin/apxs \-\-with\-mysql\=/usr/local/mysql/ ![](/media/202411/20241125143347762184.png) 源码安装Apache\+PHP整合 整合apache\+php环境,修改httpd.conf配置文件,然后加入如下语句: LoadModule php5\_module modules/libphp5\.so (默认已存在) AddType application/x\-httpd\-php .php DirectoryIndex index.php index.html (把index.php加入index.html之前) 然后在/usr/local/apache/htdocs目录下创建index.php测试页面,执行如下命令: cat \>\>/usr/local/apache/htdocs/index.php \<\<EOF \<?php phpinfo(); ?\> EOF 重新启动apache服务,通过IP访问界面如下图,即代表LAMP环境搭建成功。 ![](/media/202411/20241125143347767722.png) 源码安装DISCUZ论坛 下载discuz源码包文件,然后解压: cd /usr/src ;wget [http://download.comsenz.com/DiscuzX/3\.1/Discuz\_X3\.1\_SC\_UTF8\.zip](http://download.comsenz.com/DiscuzX/3.1/Discuz_X3.1_SC_UTF8.zip) 解压discuz程序包:unzip Discuz\_X3\.1\_SC\_UTF8\.zip \-d /usr/local/apache/htdocs/ 重命名程序文件:cd /usr/local/apache/htdocs/ ;mv upload/\* . 赋予discuz目录完全访问权限:cd /usr/local/apache/htdocs/ ;chmod 777 \-R data/ uc\_server/ config/ uc\_client/ 然后访问IP安装discuz论坛,如下图,选择“我同意” ![](/media/202411/20241125143347773194.png) 进入如下界面,数据库安装,如果不存在则需要新建数据库并授权。 ![](/media/202411/20241125143347778267.png) 数据库创建及授权命令如下: create database discuz charset\=utf8; grant all on discuz.\* to root@'localhost' identified by "123456"; ![](/media/202411/20241125143347783556.png) 点击下一步,直至安装完成,进入等待已久的论坛画面: ![](/media/202411/20241125143347788668.png) 自此LAMP环境整合并搭建成功,那如何使用Nginx来整合LAMP呢? ## Docker自动化部署二 生产环境中,由于Docker指令过多,操作比较繁琐,可以编写SHELL自动安装并配置Docker虚拟化及桥接网络,同时使用pipework脚本来配置容器IP,能够实现容器的批量管理,此脚本适用于CentOS7\.x系统; CentOS7\.x系列Docker批量管理脚本代码如下: | \#!/bin/bash\#auto install docker and Create VM\#by jfedu.net 2022\#Define PATH VarabliesIPADDR\=\`ifconfig\|grep \-E "\\\<inet\\\>"\|awk '{print $2}'\|grep "192\.168"\|head \-1\`GATEWAY\=\`route \-n\|grep "UG"\|awk '{print $2}'\|grep "192\.168"\|head \-1\`IPADDR\_NET\=\`ifconfig\|grep \-E "\\\<inet\\\>"\|awk '{print $2}'\|grep "192\.168"\|head \-1\|awk \-F. '{print $1"."$2"."$3"."}'\`LIST\="/root/docker\_vmlist.csv"if \[ ! \-f /usr/sbin/ifconfig ];then yum install net\-tools\* \-yfifor i in \`seq 1 253\`;do ping \-c 1 ${IPADDR\_NET}${i} ;\[ $? \-ne 0 ]\&\& DOCKER\_IPADDR\="${IPADDR\_NET}${i}" \&\&break;done \>\>/dev/null 2\>\&1echo "\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#"echo \-e "Dynamic get docker IP,The Docker IP address\\n\\n$DOCKER\_IPADDR"NETWORK\=( HWADDR\=\`ifconfig eth0\|grep ether\|awk '{print $2}'\` IPADDR\=\`ifconfig eth0\|grep \-E "\\\<inet\\\>"\|awk '{print $2}'\` NETMASK\=\`ifconfig eth0\|grep \-E "\\\<inet\\\>"\|awk '{print $4}'\` GATEWAY\=\`route \-n\|grep "UG"\|awk '{print $2}'\`)if \[ \-z "$1" \-o \-z "$2" ];then echo \-e "\\033\[32m\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\\033\[0m" echo \-e "\\033\[32mPlease exec $0 CPU(C) MEM(G),example $0 4 8\\033\[0m" exit 0fi\#CPU\=\`expr $2 \- 1\`if \[ ! \-e /usr/bin/bc ];then yum install bc \-y \>\>/dev/null 2\>\&1fiCPU\_ALL\=\`cat /proc/cpuinfo \|grep processor\|wc \-l\`if \[ ! \-f $LIST ];then CPU\_COUNT\=$1 CPU\_1\="0" CPU1\=\`expr $CPU\_1 \+ 0\` CPU2\=\`expr $CPU1 \+ $CPU\_COUNT \- 1\` if \[ $CPU2 \-gt $CPU\_ALL ];then echo \-e "\\033\[32mThe System CPU count is $CPU\_ALL,not more than it.\\033\[0m" exit fielse CPU\_COUNT\=$1 CPU\_1\=\`cat $LIST\|tail \-1\|awk \-F"," '{print $4}'\|awk \-F"\-" '{print $2}'\` CPU1\=\`expr $CPU\_1 \+ 1\` CPU2\=\`expr $CPU1 \+ $CPU\_COUNT \- 1\` if \[ $CPU2 \-gt $CPU\_ALL ];then echo \-e "\\033\[32mThe System CPU count is $CPU\_ALL,not more than it.\\033\[0m" exit fifiMEM\_F\=\`echo $2 \\\* 1024\|bc\`MEM\=\`printf "%.0f\\n" $MEM\_F\`DISK\=20USER\=$3REMARK\=$4ping $DOCKER\_IPADDR \-c 1 \>\>/dev/null 2\>\&1if \[ $? \-eq 0 ];then echo \-e "\\033\[32m\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\\033\[0m" echo \-e "\\033\[32mThe IP address to be used,Please change other IP,exit.\\033\[0m" exit 0fiif \[ ! \-e /usr/bin/docker ];then yum install docker\* device\-mapper\* lxc \-y mkdir \-p /export/docker/ cd /var/lib/ ;rm \-rf docker ;ln \-s /export/docker/ . mkdir \-p /var/lib/docker/devicemapper/devicemapper dd if\=/dev/zero of\=/var/lib/docker/devicemapper/devicemapper/data bs\=1G count\=0 seek\=2000 service docker start if \[ $? \-ne 0 ];then echo "Docker install error ,please check." exit fifi cd /etc/sysconfig/network\-scripts/ mkdir \-p /data/backup/\`date \+%Y%m%d\-%H%M\` yes\|cp ifcfg\-eth\* /data/backup/\`date \+%Y%m%d\-%H%M\`/if \[ \-e /etc/sysconfig/network\-scripts/ifcfg\-br0 ];then echoelse cat \>ifcfg\-eth0\<\<EOF DEVICE\=eth0 BOOTPROTO\=none ${NETWORK\[0]} NM\_CONTROLLED\=no ONBOOT\=yes TYPE\=Ethernet BRIDGE\="br0" ${NETWORK\[1]} ${NETWORK\[2]} ${NETWORK\[3]} USERCTL\=noEOF cat \>ifcfg\-br0 \<\<EOF DEVICE\="br0" BOOTPROTO\=none ${NETWORK\[0]} IPV6INIT\=no NM\_CONTROLLED\=no ONBOOT\=yes TYPE\="Bridge" ${NETWORK\[1]} ${NETWORK\[2]} ${NETWORK\[3]} USERCTL\=noEOF /etc/init.d/network restartfiecho 'Your can restart Ethernet Service: /etc/init.d/network restart !'echo '\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-'cd \-\#\#\#\#\#\#\#create docker containerservice docker status \>\>/dev/nullif \[ $? \-ne 0 ];then service docker restartfiNAME\="Docker\_\`echo $DOCKER\_IPADDR\|awk \-F"." '{print $(NF\-1\)"\_"$NF}'\`"IMAGES\=\`docker images\|grep \-v "REPOSITORY"\|grep \-v "none"\|grep "centos"\|head \-1\|awk '{print $1}'\`if \[ \-z $IMAGES ];then echo "Plesae Download Docker Centos Images,you can to be use docker search centos,and docker pull centos6\.5\-ssh,exit 0" if \[ ! \-f jfedu\_centos68\.tar ];then echo "Please upload jfedu\_centos68\.tar for docker server." exit fi cat jfedu\_centos68\.tar\|docker import \- jfedu\_centos6\.8fiIMAGES\=\`docker images\|grep \-v "REPOSITORY"\|grep \-v "none"\|grep "centos"\|head \-1\|awk '{print $1}'\`CID\=$(docker run \-itd \-\-privileged \-\-cpuset\-cpus\=${CPU1}\-${CPU2} \-m ${MEM}m \-\-net\=none \-\-name\=$NAME $IMAGES /bin/bash)echo $CIDdocker ps \-a \|grep "$NAME"pipework br0 $NAME $DOCKER\_IPADDR/24@$IPADDRdocker exec $NAME /etc/init.d/sshd startif \[ ! \-e $LIST ];then echo "编号,容器ID,容器名称,CPU,内存,硬盘,容器IP,宿主机IP,使用人,备注" \>$LISTfi\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#NUM\=\`cat $LIST \|grep \-v CPU\|tail \-1\|awk \-F, '{print $1}'\`if \[\[ $NUM \-eq "" ]];then NUM\="1"else NUM\=\`expr $NUM \+ 1\`fi\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\#\# echo \-e "\\033\[32mCreate virtual client Successfully.\\n$NUM \`echo $CID\|cut \-b 1\-12\`,$NAME,$CPU1\-$CPU2,${MEM}M,${DISK}G,$DOCKER\_IPADDR,$IPADDR,$USER,$REMARK\\033\[0m"if \[ \-z $USER ];then USER\="NULL" REMARK\="NULL"fiecho $NUM,\`echo $CID\|cut \-b 1\-12\`,$NAME,$CPU1\-$CPU2,${MEM}M,${DISK}G,$DOCKER\_IPADDR,$IPADDR,$USER,$REMARK \>\>$LISTrm \-rf /root/docker\_vmlist\_\*iconv \-c \-f utf\-8 \-t gb2312 $LIST \-o /root/docker\_vmlist\_\`date \+%H%M\`.csv | | --- |
admin
2024年11月25日 14:34
130
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
Word文件
PDF文档
PDF文档(打印)
分享
链接
类型
密码
更新密码
有效期