linux-基础知识

1、Bash shell

Bash是一个程序,将输入的命令输入给linux能够读懂,全名叫GNU Bourne-Again Shell

Bash是Bourne shell de改进版本

普通用户的输入提示符是$,超级用户root的提示符是#

2、查看bash程序本身

输入which bash,可以看到程序存在/usr/bin/bash下

输入file /usr/bin/bash后,可以看到是一个应用程序  

输入ll  /usr/bin/bash后,可以看到程序的大小1.2M

3、用户的家目录

~ 这个波浪号就是用户的家目录,也就是用户的起始目录   #可以理解为windows的桌面,就是开机默认的目录

4、在linux中root是超级管理员,可以执行一切权限   # 上帝

5、linux哲学,一切皆文件,txt类型的文件和binary二进制文件

每一条命令高效的完成一个任务,每条命令只完成一个任务

避免图形化限制,使用命令高效简洁灵活完成图形化难以完成的任务

例:使用命令创建一个备份目录并且以日期拼接

mkdir backup-$(date + %Y%m%d)  # mkdir是创建文件夹的命令,date命令可以用来查询日期,+ 后面是显示的格式定义

6、命令的组成

shell命令由三部分组成:命令+选项+参数  # command + option + argument

什么是选项:就是ls命令后面跟一个 -l或--list这种方式,命令后面跟的就是选项

什么是参数:ls -l /temp  # 选项后面跟的目录就是参数

PS:命令可以独立存在,但是选项和参数必须跟在命令后面,选项可以有一个或者多个,参数也可以有一个或者多个

7、命令中选项的组合  # 可以看到l这个选项后面又跟了一个d选项

ls -ld /temp  #  -d,--directory  表示目录列出目录本身,而不是目录的内容,查看当前目录自身的的详细信息

8、命令中参数的组合  # 可以看到第一个参数back.tgz后面又跟了一个参数/back

cp -a back.tgz /back  # -a就是携带全部权限,本条命令就是将back.tgz这个文件以及全部的权限拷贝至根目录下的back文件夹

9、terminal 就是终端,用户输入指令的地方,运行shell的地方

10、ctrl + shift + p  # 打开一个新的terminal

11、alt 1  # 切换到第一个,把1变成任意数值可以切换到对应的terainal

12、Ctrl + + # 放大字体,加 - 减小字体

13、ctrl + alt +  F1 ~ F6  #console切换,F1是登录界面,F2是登录后的界面,F3~F6是文字界面(就是输入指令的界面)

14、redhat8使用的是Standard主题,比较简洁,省去很多功能和菜单,redhat7使用classic主题,菜单功能全,切换的地方在输入密码的界面,Sign In 的边上有一个齿轮的图表,点开切换

15、redhat8 使用GNOME3图形化的桌面环境,这个图形化环境基于Wayland,而VNC不支持Wayland,所以需要切换X Windows System图形框架

16、linux文件系统中,一个 . 代表当前目录, 两个 .. 代表上一级目录

17、命令可以用 ; 分割多个命令,一次执行多条命令  # cp backup.cfg /temp/ ; ls /temp ,这个是不管前面的命令有没有成功,后面的命令都会执行

PS:也可以这样写,cp backup.cfg /temp/ && ls /temp  就是前一个命令执行成功后再执行后面的命令

18、命令嵌套命令,使用mkdir back_$ (date +%Y:%m:%d),在命令后面用$链接命令

19、一条命令太长,需要放到下一行,则使用   反斜杠 将enter转义,如果没有 则表示命令结束就会执行

20、linux的目录结构是一个树形结构,根(/)目录是一个斜杠,根目录里面是一级目录,一级目录下还有子目录

21、linux中根目录下的子目录详解

usr  # 安装的软件,共享的库,重要的子目录包括(/usr/bin:用户命令、/usr/sbin:系统管理命令、/usr/local:本地自定义一软件)

etc  # 配置文件

var  # 可变数据,重启后也会永久保存,包含动态的文件(如数据库、缓存目录、日志文件)

run  # 这是一个特殊的目录,这个目录运行在内存中,自系统启动以来启动的进程运行时的数据,包括进程ID文件和锁定文件等,此目录中的内容在重启时重新创建。

PS:此目录合并了早期版本的/var/run 和/var/lock

proc  #  进程存放的目录

home  # 用户的家目录,用户的文件都存放在这个目录中,~ 波浪号表示家目录(cd ~直接进入家目录)

root  # 超级用户的家目录

tmp  # 供临时文件使用的全局可写空间,10天内未访问、未更改或者未修改的文件将自动从改目录中删除,另一个/var/tmp该目录中的文件在30天内未曾访问、更改或修改过将自动删除

boot  # 系统启动过程所需的文件

dev  #  包含特殊的设备文件,供系统访问,包括系统启动的配置文件

PS:以下目录在Redhat7后的版本中已经合并仅保存软连接 ,/bin 和 usr/bin , /sbin 和 /usr/sbin , /lib 和 /usr/lib, /lib64 和 /usr/lib64   #   binlibliblib64 已经变成快捷方式了

22、绝对路径和相对路径

绝对路径:  /etc/sysconfig/network-scripts/ifcfg-ens33 ,这个就是绝对路径

相对路径:  etc/sysconfig/network-scripts/ifcfg-ens33 ,这个就是相对路径

PS:区别就是在路径的前面有/就是绝对路径,没有就是相对路径,写脚本就是要用绝对路径,拷贝到上级目录就是用相对目录 比较方便,还有创建目录的时候用相对路径就是在当前目录创建

23、linux中严格区分大小写

24、生成2048位的秘钥

dd if=/dev/uradom of=pass.txt bs=2048 count=1  # 

25、文件前面有一个 .  就表示隐藏文件

26、一个文件有3个时间戳

Access  # 最后一次访问时间

Modify   # 修改时间

Change  # 修改用户权限的时间

27、硬链接和软连接

硬链接:ln haha.txt heihei.txt  # 左边是源文件,右边是新文件,权限(-rw------,2)后面的数字代表有几个链接,只能链接到文件,无法对目录做链接

软连接:ln -s haha.txt heihei.txt  # 用ll可以看到haha.txt是一个软连接,权限前面l表示是软连接(l-rw------),后面可以看到haha.txt名字是高亮并且使用 -> 符号后面到heihei.txt,表示haha.txt软连接到heihei.txt

PS:链接做好后是指向内存中的同一数据块,优点硬链接删除任何一个文件,其他的文件都会在,缺点无法指向目录。软连接缺点删除原文件后软连接就会黑色高亮,链接文件是红色跳闪,链接失效,优点可以链接目录

28、man命令   # 查询帮助

man命令分8个章节

1 : 用户命令  # 如果man passwd,出现的是passwd(1)就说明查询的是针对命令的

2:  系统调用(从用户空间调用的内核例程)

3:  库函数(由程序提供)

4:  特殊文件(如设备文件)

5:     文件格式(用于许多配置文件和结构 )

6:  游戏(过去的有趣程序章节)

7:  惯例、标准 其他(协议、文件系统)

8:  系统管理 特权命令(维护任务)

9:  Linux内核API(内核调用)

如何使用man帮助,man + 命令 / man + number + 命令

例:查询命令  man ls , / -i  ,没有找到,再按小写n继续搜索,直到找到  # shift + n 向上翻

例:查询文件  man  5 filename  # 文件必须指定章节,5就是针对文件格式的

例:关键字查询  man -k passwd  # 系统就会列出所有可以查询包含passwd的信息

例:在man所有的文件中查询关键字  man -K drop  #  当-k查询不到的时候可以尝试-K,如果没有则输入q回车继续下一个文件打开,查看man帮助敲回车,如果没有继续q退出,ctrl+d下一个文件

PS:man帮助不能使用,man数据库没有创建,使用mandb指令创建后即可使用

29、rpm命令

rpm -q httpd  # 查询这个软件包是否安装

rpm -qi httpd  # 查询这个软件包的摘要信息

rpm -qd  httpd  # q就是查询 d就是指文档,查询这个软件包中所有文档

rpm -ql  httpd   # 列出这个软件包中所有的文件安装路径,系统会列出这个软件下所有的文件,包括man帮助

rpm -qc httpd   # 列出这个软件包的所有配置文件路径

rpm -q --scripts httpd  # 显示软件包的脚本,查看脚本执行哪些操作

rpm -q --changelog httpd   #  显示软件包每次制作添加的功能

30、文件的重定向 #最大的用处就是写脚本时候使用重定向

linux中有三个通道,标准输入、标准输出、标准错误

标准输入:channel 0  # 读取键盘输入

标准输出:channel 1  # 将正确输出的发送到terminal

标准错误:channel 2  # 将错误输出发送到terminal

例:将输出重定向到文件

find / etc/ -name *.conf  1>ok.txt 2>err.txt   # 查找etc目录下所有文件后缀为err.txt的文件,正确的放入ok.txt文件中,错误的放入err.txt文件中

find /etc/ -name *.conf  2>/dev/null  # 只在屏幕上输出正确的,错误的放入黑洞文件null

find /etc/ -name *.conf 1>/dev/null  # 只在屏幕上输出错误的信息,正确的放入黑洞文件null

find /etc/ -name *.conf 1>/dev/null 2>>err.txt  # 两个>>就是追加的意思

find /etc/ -name *.conf &>/dev/null  # & 表示正确和错误都放入相同的文件中

ls -l | tee /tmp/test.txt | less  #列出当前目录的所有文件写入文件中,然后又在屏幕上显示查询的内容,需要使用tee

31、管道  #使用 | 分割,含多个命令

PS:命令中 ^ 表示一行的开始,$表示一行的结束

什么是管道,就是左边的命令结果输出后交给右边的命令继续执行,命令与命令之间使用 | 分割,这个就是管道

例:cat httpd.conf | grep ^#  #读取httpd.conf文件的内容交给右边的grep(筛选)出所有#开头的内容

例:cat httpd.conf | grep  -v ^#  #读取httpd.conf文件的内容交给右边的grep(筛选)出所有不是#开头的内容,v就是反向筛选

例:cat httpd.conf | grep -v ^# | grep -v ^$  #读取httpd.conf文件的内容交给右边的grep(筛选)出所有不是#开头内容,然后交给后面的命令继续筛选出非空行的内容

例:cat httpd.conf | grep -v ^# | grep -v ^$  | grep -v ^"    #" # 读取httpd.conf文件的内容交给右边的grep(筛选)出所有不是#开头内容,然后交给后面的命令继续筛选出非空行的内容,再讲结果继续过滤出空格和#号的内容(需要过滤的空格有几个,就在命令的" "内输入几个空格和字符)

例: ls -l /etc | wc -l  # 计算一个目录下有多少个文件,有多少行就是有多少个

32、vi是一个模式编辑器,vi和vim的关系

所有unix中都有vi编辑器,包括手机

vim是根据linux和unix的vi编辑器改进版,具有分屏编辑、颜色格式突出、突出显示编辑等功能

vi分三种模式

1、command  # 命令模式,进入vi默认就是模式1

2、edit  # 编辑模式,按 i(a)键进入编辑模式

3、ex  #  扩展模式

PS:vi和vim来自于不同的软件包,使用which vi 查看vi的安装路径,然后使用rpm -qf /usr/bin/vi 查看来自于哪个安装包

PS:vimtutor 是vim的使用说明书

PS:ID > 200的用户vi等于vim,因为系统默认做了一个软连接,小于200的用户没有软连接

PS:编辑模式下使用ctrl +v 进入块选模式,使用上下左右键选中所有需要删除的字符,使用del键删除

 33、用户名和UID的关系和优先级

vim /etc/passwd

root:x:0:0:root:/root:/bin/bash  # 红色的就是UID

admin:x:1000:1000:admin:/home/admin:/bin/bash  # 普通用户的UID就是1000

在linux中用户登录时基于用户名登录,而操作的权限是基于UID

PS:系统用户的UID是低于200,1000以上的就是普通用户,201-999就是系统用户

 34、etc/passwd  # 这个文件存储了用户和UID对应关系

在这可以提升账户的等级,系统识别root就是从UID是否是0来判断

admin:x:1000:1000:admin:/home/admin:/bin/bash  # 账户信息分为7段,1就是用户名、2就是密码位,在etc/shadow中就是对应的、3就是UID、4就是GID组的ID、5就是用户的简要说明、6就是家目录,默认登录进来的目录、7就是运行的第一个程序

PS:为什么UID和GID是一样的,通常在创建用户的时候,会同时创建一个同名的用户组

35、关于服务账户  # 有些账户是用来给程序提供服务的,所以不需要登录,通过账户密码登录是无法登录的

apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin  # 没有bash就是没有shell环境的账户就是服务账户

给服务账户提供shell环境就可以使用此账户进行登录

su - apache - s /bin/bash 

36、etc/shadow  # 这个文件中存储着账户的密码,只有root可读

①admin:②$6$p21D5Jl5$OPgHUL9BkfeuzR.UkTOZHE2kkO12t1mWp7LHpIwiLP0ZYjxnOlPtEpu2TSLPc3WzlQFyRU7APuqq.ixcQVnvM.:③18295:④0:⑤99999:⑥7:::

1、用户名  2、hash后的密码   3、用户上次发生更改时候的时间,计算就是从1970年1月1号到现在的天数   4、密码的最小生命周期(就是改好密码必须使用的时长才能再次更改)   5、密码最长生命周期   6、密码过期前多少天提示

密码是由三个$构成,第一个$6就是表示密码的hash是用sha512做的,第二个$是一个盐的值,第三个$是最终的密码

加密的过程就是先用盐做一次加密,然后在通过hash值得到最终的密码值

盐的值是从 /dev/urandom中获得随机数

37、账户有三种类型,超级用户、系统用户和普通用户

超级用户(superuser)就是UID为0得账户root,可以做一切事情

UID 0 永远分配给root

UID 1-200 分配给红帽的系统服务

UID 201-999分配给安装需要的软件时使用

38、给文件添加特殊标记,防止root用户删除  # 此操作必须是root用户才能执行

chattr +i filename  # 给文件添加特殊标记

chattr -i filename  # 将特殊标记去除

PS:此操作均由ROOT用户执行,所以根本上root用户还是能够删除文件,只是多了一步操作

39、关于用户组  # vim /etc/group

root:x:0  # 组的名字:x:组的ID

特殊组wheel  # 红帽6和之前的版本都没有wheel组

wheel:x:10:student  # 一个用户可以属于多个组,或者一个组可以属于多个用户,所以这里就可以看到这个wheel组中还有一个student用户

属于自己的组称为主组,同时有其他的组就成为附属组

40、sudo,root用户给普通用户开启权限  # 会在/var/log/secure中记录日志

如在admin账户下输入passwd admin,会提示passwd:只有根用户才能指定用户名。此时使用sudo passwd admin,会要求输入一个sudo的密码,这个密码就是自己本身的密码,前提是这个账户必须在wheel组

如果新建一个用户,可以发现这个用户默认组就是自己的组,没有属于wheel组

visudo  # 必须以root用户来执行,而且命令比较特殊不能有空格而且不能使用vim,搜索wheel

## Allows people in group wheel to run all commands
%wheel    ALL=(ALL)    ALL

PS:可以来自于一切客户端,一切用户,执行一切命令

## Same thing without a password
# %wheel    ALL=(ALL)      NOPASSWD: ALL

PS:这行参数就是在sudo时候不需要密码 

PS:visudo 就是etc/sudors文件

41、普通用户不加入wheel组使用sudo权限

## Allows people in group wheel to run all commands
%wheel    ALL=(ALL)    ALL

%admin   ALL=(ALL)    ALL  # 直接在sudo配置文件中加入需要提权的用户组即可

42、linux文件的权限

目录是特殊的文件权限

r(读取)、w(写入)、x(执行)

-rw-r--r--. 1 root root 0 2月 5 10:33 test  # 第一个 - 就是普通文件(目录就是d),红色的就是对应root用户的权限,蓝色的就是对应组的权限,黑色的就是其他用户组的权限

权限有优先匹配原则,优先匹配用户(user)权限,再匹配用户组(group)的权限,最后匹配其他组(other)的权限匹配,只要有一个匹配上,则后面的权限忽略想

目录的权限高于文件权限(文件的权限跟着父目录走),就是目录的权限所属用户和组,目录下的文件用户和组没有权限,但是这个用户和组依旧可以删除这个目录下的文件

二进制数权限对应表

r(读)

w(写)

x(执行)

二进制数

对应权限

0

0

0

0

---

0

0

1

1

--x

0

1

0

2

-w-

0

1

1

3

-wx

1

0

0

4

r--

1

0

1

5

r-x

1

1

0

6

rw-

1

1

1

7

rwx

权限的组合对应表

1

1=1

--x

2

2=2

-w-

3

3=2+1

-wx

4

4=4

r--

5

5=4+1

r-x

6

6=4+2

rw-

7

7=4+2+1

rwx

权限组合解读

owner     groupowner   other

6              6           4

owner的权限是6,就是4+2,就是rw-

groupowner权限是6,就是4+2,就是rw-

other的权限是4,就是4,就是r--

组合起来就是664,-rw-rw-r--

43、权限的设置

权限分user位,group位,other位

局部设置法:chmod  u+x  filename.txt   # 这个设置只设置了user位的权限

局部设置法同时设置三位的权限:chmod  ugo+x  filename.txt

全局设置法:chmod  744  filename.txt  # 这个同时设置了三位的权限

PS:日常中对于单位设置权限使用局部法方便,需要增加或去除相对的r、w、x权限,只要直接增加或去除对应位的权限即可,chmod  u+x  filename.txt或者chmod  ugo-x  filename.txt,不需要进行十进制计算,如果需要同时设置多位多个权限,则效率上全局法快不用一个一个去设置如chmod  777  filename.txt 改成其他权限 chmod  744  filename.txt即可

局部设置法设置目录权限:chmod  -R ugo+x  dirname   #  目录一定要跟一个R这个参数

44、环境变量的定义

定义环境变量有四个文件,etc下的是全局的(登录的用户和未登录的用户都能使用),~是家目录的(只有用户登录了才能使用的)

PS:profile就是正常的环境变量,bashrc就是和命令相关的环境变量

1、/etc/profile   # 正常的环境变量

2、/etc/bashrc  # 和命令相关的环境变量

3、~/.bashrc  # 用户和命令相关的环境变量配置

4、~/.bash_profile  # 用户的环境变量

alias test="ps axo pid,ppid,comn"  # 设置命令别名,有时候命令太长但是使用率高,设置别名有利于记忆和使用

将命令的别名给全局使用,vim /etc/bashrc,打开后在最后一行加入alias test="ps axo pid,ppid,comn"(设置别名的命令),这样所有用户都可以使用别名使用命令

45、关于前台进程放到后台运行,这个功能针对显示器键盘接设备时候,只有一个屏幕,没办法开terminal一样多窗口

将一个作业放到后台的步骤

md5sum /dev/urandom  # urandom是一个不断变化的值,所以会一直在前台运行

ctrl + z  # 快捷键将前台进程暂停放到后台,可以看到后台号,[1]+ 已停止 md5sum /dev/urandom

bg 1  # bg + 后台号进行后台运行

jobs  # 查看后台运行的作业

fg 1  # 将后台作业放到前台运行

md5sum /dev/urandom &  这个直接在运行的同时放到后台并运行

46、关于进程号

进程有几个常用信号可以发给进程

1  # 1号信号,从新加载配置文件,rload,不中断服务的链接,配置做更新

15 # 正常退出

9  # 强制杀死进程

19  # ctrl + c

20  # 等同于ctrl + z

47、监控进程的活动,top命令

top查看系统的负载

top - 17:33:32  # 系统启动的时间

up 43 min  # 系统运行的时长

2 users  # 几个用户登录

load average: 0.00(1分钟负载), 0.20(5分钟负载), 0.44(15分钟负载)  # 负载取决于三个子系统,IO/CUP/内存,任何一个负载达到上限就是1,三个子系统加起来就是3

Tasks: 210 total  # 有多少个任务

1 running  # 多少个任务在运行

209 sleeping  # 睡眠进程数量

0 stopped  # 停止进程数量

0 zombie #  僵尸进程数量

%Cpu(s):  0.5 us,  0.3 sy,  0.0 ni, 99.2 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st  # CPU的使用情况,红色的是空闲情况

KiB Mem :  1863252 total  # 总内存   

71812 free  # 使用内存

711528 used  # 剩余内存

1079912 buff/cache  # 缓存数,buff写缓存,cache读缓存

top中常用的按键

?或h

交互式的帮助信息

1、t、m

切换到负载、线程和内存标题行

1

标题中切换显示单独cpu信息或所有cpu信息

S

更改刷新率,默认5秒,输入值可以是0.x,也可以是整数

b

切换反向突出显示运行中的进程,默认仅为粗体

Shift + b

在现实中使用粗体,用于标题以及运行中的进程

Shift + h

切换线程,显示进程摘要或单独线程

u / shift + u

过滤任何用户名称(有效、真实)

Shift + m

按照内存使用率,以降序方式对进程列表排序

Shift + p

按照处理器使用频率,以降序方式对进程列表排序

k

中断进程,若有提示,输入pid,再输入signal

r

调整进程的nice值,若有提示,输入pid,再输入nice_value

Shift + w

写入(保存)当前的显示配置,以便在下一次重新启动top时使用

q

退出

f

通过启用或禁用字段的方式来管理列,同时还允许您为top设置排序字段

注:如果top在安全模式中启动,则不可用

48、文件的权限

文件的权限分为3段  -r-xr-xr-x所属用户权限,所属用户组权限,其他用户权限,r(读) w(写) x(执行)

文件和文件夹的权限区别

文件file中:r(读) w(写) x(执行)

文件夹dir中:r(读) w(写) x(可以进入目录)

PS:对文件夹(目录)设置权限的时候 X 必须要大写的 X ,这样不会影响目录下文件的权限,目录要求进入,但是文件不一定需要可执行

权限前第一位d表示目录,b表示块设备,c开头是字符设备,l开头的是链接类型, - 表示文件

特殊权限

在权限中,有一个s 如lrwsxrwxrwx. 这就是特殊权限,特殊权限分三种 suid sgid sbit

PS:特殊权限s变成大写的S,就表示这个特殊权限无效

sudi   lrwsrwxrwx.   # 就是在owner位的,这个就是suid,就是任何用户可以以owner用户去执行,只能用于文件,对于目录无效

sgid   lrwxrwsrwx.   # 在group位的,对于文件是以组的权限去执行,对于目录会将目录变成共享目录,带有s权限,属于用户组中的所有用户都可以访问此目录中的文件包括相互修改文件,通常用于共享文件夹

sbit    lrwsxrwxrwt.  #  在other位的,表示不是s,是t,和另外两个特殊权限的表示不一样。而且只能针对目录,文件无法使用,所有用户都可以在里面进行读写,但是权限只能属于自己,其他人不能修改。主要用于临时目录

设置的命令 

chmod u + s # 文件设置suid

chmod u - s  # 文件取消suid

chmod g + s  # 文件 / 文件夹 设置sgid

chmod g - s  # 文件 / 文件夹取消sgid

chmod 0 + t  # 文件设置sbit

 49、关于默认权限

root用户是 755,文件是644

使用umask命令查看得出值是0022,计算公式就是777-022=755得出的值就是root用户的权限值,然后使用权限值755-111就得出644,就是文件的权限

普通用户就是775,文件是664

使用umask命令查看得出值是0002,计算公式就是777-002=775得出的值就是root用户的权限值,然后使用权限值775-111就得出664,就是文件的权限

umask可以在 /etc/profile中自定义

50、ssh远程连接

ssh基于公钥私钥做身份认证,对称的加密方式进行数据传输

ssh username@ip(hostname) # 指定用户和地址(域名)进行ssh链接

ssh servera  # 直接默认用户进行ssh链接

PS:ssh username@ip(hostname)后面也可以直接跟命令,实现登录后直接显示结果

如果没有username,直接 ssh ip(hostname)则是以当前用户身份远程连接,当前用户身份使用的就是uid,所以登录后会默认是1000的uid账户,而不是登录前的用户身份

例:主机A的用户名是admin1,在passwd文件中指向了1000的uid,主机B中的用户名是admin2,在passwd文件中指向了1000的uid,所以当主机A使用ssh hostname登录的时候,账户变成了admin2,而不是默认的admin1,这就是系统在ssh登录时候使用的是默认账户的uid,而不是默认账户名称

首次链接会出现以下提示

The authenticity of host 'ynca (192.168.5.30)' can't be established.  # 这里提示还不能链接
ECDSA key fingerprint is SHA256:UbG/BZSwMK0S+nCAYKt2K2/aIIDCdbv64I53RnKGSGU.  # 这里给出了一个指纹信息
ECDSA key fingerprint is MD5:ac:9e:16:d4:6b:e6:1e:0f:91:19:fe:b1:da:ca:62:d7.
Are you sure you want to continue connecting (yes/no)?  # 是否需要继续,yes后才会让你输入密码

当前用户的家目录下,使用ls -a  查看隐藏的目录文件

cd .ssh  # 进入隐藏目录

cat  known_hosts  # 这个文件中存储的就是本机的公钥和访问主机的公钥信息

cd /etc/ssh # 在初始化环境的时候会在这个目录下生成密钥对,ssh_host_ecdsa_key这个是私钥,ssh_host_ecdsa_key.pub这个是公钥,基于不同的加密算法

PS:私钥的权限比较低,公钥的权限高

例:servaera 通过ssh访问了serverb,这时候servera的家目录下的.ssh目录中的known_hosts就会存储serverb的公钥信息

cd ~

cd .ssh

cat  known_hosts可以看到公钥信息

serverb,fe80::2ff1:d368:4fda:2de5%ens33 ecdsa-sha2-nistp256   # ecdsa 就这个就是在其他主机中生成公私钥的名称

 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBM9PBeFxJtm8kPzKGNA4Xn3fp+Wh5EWZ5rFGaj72fW7h3Z+GGR/qvZGnj7R/liMZNsOsKoMviqcGxCZEiBFQURo=

再进入/etc/ssh,看到对应的名称公私钥 ssh_host_ecdsa_key 和ssh_host_ecdsa_key.pub

PS:公钥就相当于钥匙,/etc/ssh下的公钥文件就是锁,两者匹配上就可以直接登录,所以首次登录会提示验证指纹信息,成功后就不会在需要验证,为什么验证身份不用私钥,私钥的加解密工作量太大耗费资源太多,所以使用公钥

 每次访问都要输入密码比较麻烦,在可信的主机上设置ssh直接访问,不需要输入密码,servera生成公私钥发送给serverb实现

1、ssh-keygen  # 在servera的服务器上生成root用户(用哪个账户自定)的公私钥,直接回车

2、cd ~/.ssh  # 可以看到自己的公私钥文件,id_rsa和id_rsa.pub

3、ssh-copy-id root@serverb  # 将公私钥文件拷贝至serverb服务器,这里ssh登录必须要指定用户和主机id或hostname,输入用户的密码即可

4、cd ~/.ssh  # serverb下可以看到authorized_keys,这个是验证过的文件,查看这个文件最后一个 / 后面的就是后缀,此时查看servera的公钥文件,后缀和serverb中authorized_keys的后缀是一样的

5、此时使用本账户进行ssh登录不在需要输入密码

servera访问serverb不需要密码,作为跳板机会有安全问题,srvera如果被劫持,是非常严重的问题,针对这个问题,使用ssh-agent程序实现ssh链接不输入密码

1、ssh-keygen  # 在servera的服务器上生成用户的公私钥,提示是否加密密码的时候输入密码

2、ssh-agent bash

3、ssh-add  # 执行这项指令后需要输入密码,这个密码就是在生成公私钥的时候输入的加密密码(保护密码)

此时在进行ssh链接依旧是不需要输入密码的,但是已经交给ssh-agent 去帮你输入密码,在后端程序替你输入了保护密码,但是只对当前的terminal有效,退出后失效

ssh连接禁用root用户,目的是为了防止暴利破解密码直接获取系统最高权限

1、vim /etc/ssh/sshd_config

2、找到PermitRootLogin yes 改成no即可

3、systemctl restart sshd  # 重启服务

ssh连接不允许使用密码,只允许使用公私钥登录

1、vim /etc/ssh/sshd_config

2、PasswordAuthentication yes 改成no  # 这项设置后ssh远程连接无法使用密码

PS:配置一旦开启无公私钥即无法访问,所以讲本机公私钥也无法发送到需要连接的主机上

51、linux系统日志

日志分8个级别:

0是emerg  # 系统不可用,终端上会直接显示,必须要处理的

1是alert   #  报警信息

2是crit  # 临界情况

3是err  # 非严重错误,就是报错,这个级别到1就必须要处理了

4是warning  # 警告

5是notice  # 通知

6是info  # 轻微信息

7是debug  # 调试信息

系统日志路径:/var/log

常用的就是message日志,关于安全的日志secure

rsyslogd 这个服务就是管理日志的

/etc/rsyslog.conf  # 日志配置文件,全局的配置文件

0~6级别的日志都会写到  /var/log/message 中,在全局配置文件中可以看到,其中mail.none邮件日志,authpriv.none身份认证相关日志,cron.none计划任务日志不记录到message中

配置文件中mail.*后面的 * 就表示所有级别,然后都会有对应的日志文件,比如邮件相关的路径 -/var/log/maillog

新的日志在红帽7以后出现的,服务名是systemd-journald  

systemctl status systemd-journald  #查看日志进程运行情况

这个日志收集系统启动时候早期的信息,优先级比rsyslog高,记录在数据库中而不是文件中,能够做结构化的查询

PS:日志的目录是 /run/log 下的 journal目录下,这个目录指向的是内存,所以在内存中生成数据库,一旦重启就清除生成新的日志无法查看,只能使用journalctl读取

1、journalctl  # 显示所有启动时候早期的日志,包括硬件初始化的日志

2、journalctl -e  #查看数据库中最后的日志

3、journalctl  -f  # 动态刷新日志

4、journalctl  -p  err / debuf / info / notice / warning / crit / alert / emerg # 查看系统中指定级别以上的日志,err日志以红色表示

5、journalctl  -u  sshd  # 查看相关服务的日志

6、journalctl  -p  err -u  sshd # 日志筛选,结构化的查询

7、journalctl -- since today  # 查看今天的日志

rsyslog和journald两个日志的关系,最原始的交给journald日志记录,rsyslog的配置文件中可以看到加载journald模块,所以关系看下图

PS:所有的服务都是由systemd启动,所以所有的日志都会默认交给systemd-journald,rsyslog为了向下兼容性,根据配置从数据库中将日志信息读出来,再写到相关的文件中

日志的轮转

var/log下的日志默认自动备份四次,每隔7天会做一个备份,会有一个轮询,老的日志会删除,所以查询只能查到一个月的

配置文件 /etc/logrotate.conf

weekly  # 备份周期一次

rotate 4  # 总的次数,4次

create  # 不存在则创建

dateext  # 文件名的后面加上日期

syslog日志格式分析

Feb 18 10:25:22 servera sshd[8942]: Accepted password for root from 192.168.5.30 port 9614 ssh2

1、日志条目时间戳

2、发送信息的主机

3、发送信息的程序名称和PID编号

4、具体信息,做了什么事

永久保存system journal日志信息

配置文件路径  /etc/systemd/journald.conf

man 5 journald.conf  # 使用man帮助查看信息,得知永久存放需要指向指定的目录/var/log/journal

mkdir /var/log/journal # 创建目录

chmod 2750 /var/log/journal/  # 查看/run/log/journal,按照这个目录权限给/var/log/journal设定权限

chown root:systemd-journal /var/log/journal/  # 设定所属用户和用户组,这个参照/runlog/journal下的文件

systemctl restart systemd-journald  # 重启服务

PS:system journal有一个默认机制,就是/var/log/journal这个目录存在则永久保存,如果不存在则临时保存,只要创建目录即可

PS:日志大小默认不能超过所属文件系统的10%,也不能造成文件系统可用空间低于15%,此值可以在/etc/systemd/journald.conf中设置

52、时间的同步

对于时钟同步,有一个ntp服务器

使用命令 timedatectl 

Local time: Wed 2020-02-19 13:09:26 CST  # 本地时间
Universal time: Wed 2020-02-19 05:09:26 UTC 
RTC time: Wed 2020-02-19 05:09:25 # 主板上bois时钟的时间
Time zone: Asia/Shanghai (CST, +0800)  # 时区
NTP enabled: yes # 时间有无通不过
NTP synchronized: yes  # NTP服务有无启动
RTC in local TZ: no # RTC时钟是不是本地的时区,所以RTC时间就是UTC时间

设置时区

tzselect  # 选择时区的命令,输入后选择时区后回提示使用设定的时区进行设置

timedatectl set-timezone Asia/Shanghai  # 设置时区

timedatectl set-time “2020-02-19 13:09:26” # 时间从 timedatectl 查看本地时间复制

timedatectl set-ntp true / false  # 设置是否开启ntp服务,通常都开启

设置NTP服务 # 本机同步时钟服务器进行时间校准

配置文件路径 /etc/chrony.conf 

以下四个选项默认没有注释,设置时钟服务器需要将下面四个注释掉

erver 0.centos.pool.ntp.org iburst
server 1.centos.pool.ntp.org iburst
server 2.centos.pool.ntp.org iburst
server 3.centos.pool.ntp.org iburst

server hostname/ip iburst  # 上面四条注释后按照格式自定一条,地址可以使hostname也可以是ip地址

systemctl restart chronyd.server  # 重启服务  

chronyc sources -v # 确认设置成功否,还能看到过程

53、网络配置

rehat7开始网卡命名规则

以前都是eth0这样的类型命名,当设备添加或者移除时候,命名的及机制会变化,而且PCIe标准无法保证启动时检测PCIe设备的顺序,所以rhel7开始使用新的命名规则,基于bois固件信息,PCI总线拓扑和网络设备类型,而且不会更改

开头为接口类型:以太网接口en开头,WLAN接口开头为wl,然后是固件信息或PCI设备位置信息

oN为板载设备,列入eno1为板载以太网设备1

sN为PCI热插拔设备,例如ens3表示PCI热插拔插槽3中的以太网卡

pMsN为位于插槽N中总线M上的PCI设备,例如wlp4s0表示插槽0中PCI总线4上的WLAN卡  # wl(无线网卡) p4(pci插槽第4位) s0(0号插槽) 

iptraf 可视化网络管理工具

这个软件可以看到连接,收发包信息,统计当前流量速度,可以看协议包等信息

yum install iptraf 

iptraf-ng  # 启动程序

nmap端口扫描工具

yum install nmap

nmap-ncat  # 启动程序

nmap -sn  ip地址/掩码(192.168.1.10/24) # 可以扫描出网段中有多少机器在运行

qperf查看网络速率

yum install qperf 

qperf hostname tcp_bw / udp_bw  # 查看tcp/udp协议网络速率

NetworkManager服务

网络中分两个部分,第一个devic是硬件,还有一个是connetion针对硬件设备的配置

redhat8开始使用NetworkManager监控和管理网路,无法关闭

配置保存在/etc/sysconfig/network-scripts 目录中,且只有root用户才能修改网络配置

配置命令是nmcli或nmtui  # nmcli命令复杂,但是支持table补齐

man nmcli-examples  # 使用这条man帮助命令,搜索 Example number (1~8)

使用命令配置IP地址

nmcli con add con-name my-con-em1 ifname em1 type ethernet ip4 192.168.100.100/24gw4 192.168.100.1 ip4 1.2.3.4 ip6 abbe::cafe

PS:1就是connetion name,2就是connetion name 的名字,3就是device的名字,4就是类型,5就是IPV4的地址,gateway的地址,7就是可以配置第二个ipv4的地址如果没有可以删除,8就是ipv6的地址

nmcli con mod my-con-em1 ipv4.dns "8.8.8.8 8.8.4.4"  # 配置DNS地址

nmctil connection reload / systemctl restart Networkmanager # 重新载入配置内容 / 重启网络服务

断开连接不使用nmcli con down name 命令,使用nmcli dev disconnect name 命令

因为nmcli con down name会关闭连接,但在默认情况下,大部分有线系统连接是在启用了autoconnect的情况下配置的,这将在其网络接口可用后立即激活连接,nmcli dev disconnect name 断开是从硬件层面彻底的断开,直到人为激活

配置文件解析 /etc/sysconfig/network-scripts/ifcfg-ens33  # 网络位置文件路径

TYPE=Ethernet  # 接口类型
PROXY_METHOD=none  
BROWSER_ONLY=no
BOOTPROTO=static  # 静态地址还是DHCP
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens33  # 网卡connection的名字
UUID=ded79cbd-c3f4-4ef1-a504-a54a467ab6e5  # 网卡的UUID
DEVICE=ens33 # device的名字
ONBOOT=yes # 开机是否激活
IPADDR=192.168.5.200 # ip地址
NETMASK=255.255.255.0 # 子网掩码
GATEWAY=192.168.5.2 # 网关地址
DNS1=192.168.5.2 # DNS地址 ,这个是个性化设置,不是全局,是一个连接的配置

PEERDNS=no  # 这个配置开启就会更新全局DNS配置,所有的连接DNS都会更新,会同步更新这个配置文件/etc/resolv.conf下的namserver项,search项配置后就可以自动补齐域名来尝试能否解析,在ping或其他操作时候通过域名可以不用全名

主机名的配置

配置文件 /etc/hostname  # 文件中修改立即生效

使用命令修改主机名 hostnamectl ser-hostname 主机名  # 这个会默认修改/etc/hostname中的内容

numtui 界面设置

配置DNS名称(域名)解析

1、静态名称解析  # 将域名关联到IP地址

2、动态名称解析

PS:静态优先级高于动态

/etc/nsswitch.conf  这个文件定于域名查找位置和顺序,默认先检查/etc/hosts 文件内容(这个文件中配置就是ip地址对应的域名),其次会查找

设置名称解析顺序

#hosts: db files nisplus nis dns
hosts: files dns myhostname  # 优先级先看文件,然后在看dns,最后才看主机名

vim /etc/hosts 设置静态域名解析 # 这个只能单向解析,只能主机名解析到ip地址,而不能从ip地址解析到主机名.基于IP地址的解析一定要从DNS反向解析

54、tar命令文件的归档,压缩包备份

将目录打包成一个文件,可以将文件进行加解压缩,支持三种格式gzip、bzip、xz

打包文件

tar cf etc.tar /etc  # tar 后面的参数c是创建,f是文件名,然后是名称,压缩的文件夹路径或文件,在名称不指定路径的情况下,默认压缩的文件放到当前路径

压缩文件

gzip etc.tar # 以gzip格式进行压缩

gunzip  etc.tar.gz  # gzip格式解压

bzip2 etc.tar #以bzip格式压缩

bunzip2 etc.tar.bz2 # bzio格式解压

xz etc.tar # 以xz格式压缩

unxz etc.tar.xz  # xz格式解压

直接打包归档+压缩两条命令合成一条

tar czf etc.tar.gz /dir # z就是以gzip压缩

tar xzf etc.tar.gz /dir # 解压gzip格式文件

tar cjf etc.tar.bz /dir  # j 就是以bzip压缩

tar xjf etc.tar.bz /dir  # 解压bzip格式文件

tar cJf etc.tar.xz /dir  #J就是以xz压缩,这里是大J,bzip是小写j

tar xJf etc.tar.xz /dir # 解压xz格式文件

PS:在指令中加入v参数,就可以看过程,tar cvzf etc.tar.gz /etc ,如果没有v就是静默压缩,参数没有位置关系,但是f一定要在最后因为f后面是跟文件名的

55、两台机器文件同步

使用scp命令  # s 是安全,cp是拷贝命令

scp /tmp/etc.tar.gz root@servera:/tmp/  # 使用scp命令将tmp目录下文件同步到serera的tmp目录下

然后输入被同步的主机密码即可

使用scp命令传回文件

scp root@servera:/tmp/etc* /tmp/  # 使用scp命令将tmp下的etc名称相关的文件全部传回到本机

输入被拷贝的主机密码即可

使用scp命令传回整个目录

scp -r root@servera:/tmp/etc* /tmp/   # 参数r就是递归,目录一定要递归

增量同步更新 # 只能做到增量更新,无法做到差异化更新,就是两边的目录文件一致

每次同步就会产生新的文件,就会存在文件重复占用空间,使用增量同步则存在文件不同步,仅同步新文件或有修改的文件

tar zcvf backup_etc_$(date +%Y%m%d).tar.gz /tmp # 使用时间进行命名归档压缩

rsync -a  /backup root@serverb:/root/ # a参数就是带权限,backup就是指定的目录到serverb主机的root目录下,如果文件相同则不作任何操作,参数中加v选项就可以看到过程

目录,文件,子目录增量差异化更新到另一台服务器,使两边的数据一致 

rsync -a --delete /backup root@serverb:/root/ # 差异化更新,如果主机a同步到主机b,主机b上有的文件是主机a上没有的,使用这条命令会在主机b上删除主机a上没有的文件,做到被同步的主机文件一致性

rsync -avP --delete /backup root@serverb:/root/  # 大写P就是可以看拷贝的百分比,有进度条

同步目录 rsync -avP --delete /aaa root@serverb:/  # 将servera的目录更新的serverb机器上,其实就是在serverb相等的位置下创建目录,存在则做对比

PS:对比是通过hash做对比

55、红帽系统的注册

按win键,搜索subscription点击后开始注册  # 使用界面进行注册

subscription-manager register  # 使用指令注册

56、RPM软件包

rpm软件包i命名规范

①abrt-addon-ccpp-②2.1.11-52.③el7.centos.④x86_64.rpm  # 1:软件名称、2:软件版本(官方版本)、3:针对系统版本el7就是红帽7、4:架构(x86_64就是64位的操作系统)

PS:红帽有BackPorting机制,在软件包版本中2.1.11是主版本(官方版本)也就是稳定版,后面的-52是子版本。子版本就是在社区开源的新版本中出现的新特性,整合到当前官方版本中,主版本还是当前的版本,但是有新版本的功能或特性。

RPM 全称 redhat Package Manager

abc.spec  # 这个是rpm的编包软件,在这里面定义软件名字,版本,说明,软件包依赖关系等

RPM安装过程中会放到rpm的db中,在/var/lib/rpm 中,有db数据库

centos的光盘镜像iso的Packages目录下都是rpm软件安装包

redhat的ISO镜像包下dvd/BaseOS/Packages下都是rpm软件安装包

安装rpm命令 rpm -ivh 软件包名

rpm -ivh # 参数ivh中,i=install,v=verbosre看过程,h=hash验证hash

升级软件包

rpm -Uvh

删除软件包

rpm -e 软件包名

57、yum仓库安装软件包

新装的redhat8 使用yum时提示没有yum,挂载本地源后使用dnf安装yum工具

vim /etc/yum.repos.d/rhel8.repo

[AppStream]
name=appstream
baseurl=file:///run/media/root/RHEL-8-0-0-BaseOS-x86_64/AppStream # 这里是ISO挂载的目录
enabled=1
gpgcheck=0
[BaseOs]
name=baseos
baseurl=file:///run/media/root/RHEL-8-0-0-BaseOS-x86_64/BaseOS
enabled=1
gpgcheck=0

dnf install yum -y # 使用install命令安装

在安装rpm软件包的时候会提示依赖关系,当手动去安装依赖关系时候会继续提示依赖关系,一层一层比较麻烦,甚至会进入死循环,这时候就要使用yum安装来解决依赖关系,会自动安装依赖关系

 在红帽8中,仓库分为两个,一个是和应用相关的AppStream,一个是和系统相关的BaseOs

仓库的配置文件路径 : /etc/yum.repos.d/rhel_dvd.repo

[rhel-8.0-for-x86_64-baseos-rpms]  # 这个是和系统相关的仓库配置

baseurl  # 仓库地址

enabled = true # 激活

gpgcheck = false  # 是否需要公钥私钥进行验证

name # 名字

[rhel-8.0-for-x86_64-AppStram-rpms] # 和应用相关的仓库

PS:配置yum仓库后,需要先清除缓存然后在加载缓存

PS:红帽中将软件包分为包组,将多个软件打包在一个包中,称为包组,可以直接安装包组来将软件打包安装

yum历史记录都有记录在文件

/var/log/dnf.log # yum 所有的输出信息

/var/log/dnf.rpm.log  # install的信息 

/var/log/dnf.librepo.log  # debug 信息

基于ISO文件做一个本地yum云

cd /

mkdir yum  # 创建一个文件夹名,采用yum比较容易识别

wget # 下载ISO

mv rhel-8.0-for-x86_64.iso rhel8.iso  # 下载的镜像名称太长,不方便操作,修改名字

挂载根据需求自行选择

临时挂载

mount -o loop /rhel8.iso /yum  # 将镜像挂载到yum目录下,临时生效,机器重启就没了

umount yum # 卸载挂载

永久挂载

vim /etc/fstab 

在文件内添加内容 /rhel8.iso /yum iso9660 defaults,ro 0 0

mount -a

vim /etc/yum.repos.d/dvd.repo

[Base]

name=Base

baseurl=file:///yum/BaseOS/

enabled=1

gpgcheck=0

[AppStream]

name=AppStream

baseurl=file:///yum/AppStream/

enabled=1

gpgcheck=0

yum claen all # 清除缓存

yum makecache # 生成缓存

58、module streams 模块流 # 红帽8的新特性

如工作中开发人员需要使用最新版本的应用,但是运维人员希望使用稳定版本,在管理上会很难做到兼容,红帽8就引入 了模块流的技术,允许单个仓库存在多个版本的软件包和依赖关系项

模块可以包含多个流,使用个版本应用提供安装,启用模块流后,系统能够访问改模块流中的RPM软件包

PS:模块是一组相关联的RPM软件包,每个模块可以有一个或多个模块流,其包含不同版本的内容,每个流独立接受更新。模块流可以视为应用流仓库中的虚拟仓库,并且每个模块可以有一个或多个配置文件

yum module list # 列出可用模块列表

yum module list 模块名 # 列出指定模块的列表

yum module install -y 模块名 # 模块安装包

PS:比如查看可用模块列表的时候看到python有两个,一个是python27,一个是python36,模块名字就是python,python模块中有两个流,一个是27一个是36

yum module remove -y 模块名 # 删除已安装的指定模块

yum module disable  模块名 # 禁用模块流

PS:对于指定模块,只能启用一个模块流,其他模块流将被禁用

59、文件系统

硬盘属于块设备 block device,在未挂载和格式化前就属于块设备(好比一块砖头无法使用),需要进过分区、格式化、挂载才能使用

Block device --> partation(分区) -->Format(格式化获得FileSystem文件系统) --> mount(挂载到某一个目录,才能往这个目录中读写文件)

PS:块设备挂载前必须使用文件系统对其格式化后再挂载

命名规则

虚拟硬盘就是用v表示(vda),U盘移动硬盘等就是用s表示(sda),nvme0表示ssd硬盘,mmcblk0表示存储卡(SD/MMC/EMMC)

其中a就表示第一块硬盘,第二块硬盘就是b以此类推,使用字母排序进行排序

vda1就表示vda中第一个分区,vda2就表示vda中第二个分区,分区排序使用数字进行排列

PS:ssd的命名略有不同,第一个磁盘上的第一个分区是/dev/nvme0p1,第二个磁盘上的第三个分区是/dev/nvme1p3,SD或MMC存储卡分区类似

挂载和取消挂载

挂载使用mount命令,,必须是root用户,第一个参数指定的是挂载的文件系统,第二个参数是指挂载的路径即什么目录下

使用blkid查看盘符的uuid

PS:挂载时候不要使用设备名称vda1这种名称进行挂载,因为盘符是会变的,如果使用设备名称挂载,一旦硬盘进行插拔则盘符变动则会故障,但是uuid是固定不变的,所以在做永久挂载的时候必须要使用uuid

挂载盘符

当u盘或移动设备插上后,可以使用blkid查看到uuid # 移动设备会自动挂载到/run/media/ 下

centos中默认源没有ntfs-3g软件包

添加yum源 wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

yum -y install ntfs-3g  # 可以直接安装

mount UUID="7d739626-58b3-4e86-9e2a-b09e9af23502" /mnt/test  # 将文件系统挂载到指定的目录下

永久挂载磁盘  # 即开机自动挂载

vim /etc/fstab

UUID="b7137d35-5c96-4122-8ec1-e89194901933"  mnt/test ext4 defaults 0 0  # 设备名(使用uuid) 挂载链 文件系统类型 挂载选项默认(defaults) 是否备份(默认0) 开机是否做磁盘检查及顺序(0表示不检查,1就是检查)

PS:磁盘检查0表示不检查,1开始按照顺序进行检查,设备名使用UUID,如果使用设备名在热插拔的时候设备名可能会变导致挂载失败

mouna -a  # 挂载磁盘

PS:如果希望磁盘目录就是一个纯粹的目录,不能运行任何脚本,在defaults后面加noexec即可(defaults,noexec)

PS:设置文件系统为只读,不能创建和写入数据,在defaults后面加ro参数

取消挂载

注意:离开挂载目录

如果挂载目录提示目标忙

安装psmisc软件

fuser -v /test # 查看连接的用户和进程

fuser -vk /test # 踢掉所有用户

umount /test  # umount 后面可以跟设备名,也可以直接跟挂载的目录

60、关于文件查询

查询命令由两条,find和locate

locate是从mlocate数据库中查找,速度快,如果提示没有索引数据库,每日自动更新,使用updatedb手动更新数据库

locate mlocate # 可以看到是用systemd服务做的计划任务

操作系统中每天都会自动执行索引数据库的生成和更新,rel8中使用systemd服务 /usr/lib/systemd/mlocate-updatedb.service做自动更新任务,使用/usr/lib/systemd/mlocate-updatedb.timer做计划任务

locate 文件名  # 查找到文件所在的路径

find 是实时查询

find后面也可以跟-user(用户)、-group(组)、-uid(uuid)、-gid(guuid)选项

选项-perm还可以查找具有特定权限的文件,权限前面加上/或- 符号

/ 将匹配文件的用户、组、其他人权限的至少一位,或的关系

find /home -perm /442  # 需要匹配用户具有读取权限、或者组至少具有读取权限,或者其他人至少具有写入权限的文件

-表示该位的所有三个权限都必须存在,与的关系

find /home -perm -324  # 匹配用户至少具有写入和执行权限,并且组至少具有写入权限,并且其他人至少具有读取权限 

0值类似于通配符,因为其表示至少无任何内容的权限

61、激活web控制台管理界面,以远程管理和监控linux服务器的性能,修改IP地址、创建计划任务等界面化的管理

Web Console是基于开源的Cookpit服务,实现远程管理和监控服务器,本机还可以添加其他主机进行管理

PS:除最小安装外,rhel8默认安装Web Console,但是需要订阅激活

yum install cockpit   # 安装服务

systemctl enable cockpit --now   # 启动服务,开机自动运行

systemctl enable cockpit.socket  # 启动socket服务,socket服务不启动则无法访问

systemctl status cockpit  # 查看服务运行否

PS:服务默认9090端口,防火墙要开启9090端口

PS:访问方式 https://ip(hostname):9090

Diagnostic Reports  该工具会从该系统搜集系统配置和诊断信息用于诊断系统问题。搜集的信息将保存在系统本地。#  命令行界面使用sosreport 即可,文件保存在 /var/tmp 压缩包

62、使用red hat insights 查询并修复故障  # 这个工具类似于wondows的360安全卫士

PS:需要红帽订阅

red hat insights 是一种预测分析工具,帮助识别和修复红帽系统的安全和稳定性。是作为软件即服务(SaaS)产品提供,可以快速部署和扩展,进行评估和修复

代替red hat insights 的工具,openscap无需订阅,并且只在一台服务器上安装后通过ssh对其他服务器进行扫描

yum install openscap*  # 安装工具

yum install *scap* # 安装工具

scap-workbench  # 启动工具命令

选择操作系统点击load content

 

63、BASH Shell脚本的编写

脚本编辑器分vim和emacs

纯文字编写使用vim

图形化的界面使用emacs

脚本的名称定义为 abc.sh,后缀使用sh表示这是脚本

第一行内容为 #!/bin/bash,第一行为注释,#!通常称为sh-bang或she-bang,/bin/bash表示这个脚本是在bash环境下执行

脚本没有执行权限也可以执行,使用 bash 执行,如 bash abc.sh这样也能得到结果,为了方便通常都会给与执行权限,chmod u+x abc.sh颜色会变成绿色,此时可以直接使用sh abc.sh(./abc.sh)执行了

PS:shell脚本必须为可执行文件,可将脚本放在shell的PATH环境变量中列出的目录中,即可直接输入脚本名来运行

echo $PATH  # 查看系统环境变量的路径

/usr/local/java/jdk1.8.0_221/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/root/bin  #系统默认回到这些目录中去搜索命令,搜索不到才会到当前目录搜索

为了方便脚本执行,将脚本拷贝到/usr/local/bin目录下,此时能够在任意目录下运行这个脚本

PS:脚本中特殊字符必须加双引号“”,否则会发生转义

例:取出变量中的值

#!/bin/bash

price=5 # 定义了一个变量值

echo "This price is $price"  # 语句中$price 就是表示取出变量值

PS:取值的语句中不能使用单引号,如果是单引号则$取值不生效,会直接输出语句内容

echo "This price is $$price"  # 语句中$$ 就是表示显示运行本次脚本进程号

echo "This price is $$price"  # 语句中就是将后面的特殊字符原意输出,第二个$才去取值

PS:反斜杠只能对后面的一个字符进行转义处理,多个字符就要每个字符前面都要加反斜杠

使用循环执行脚本

使用for循环创建十个用户

for i in {1..10};do useradd user$i;done  # 创建1-10的用户

for i in {1..10};do del -r user$i;done # 删除1-10的用户

使用for循环执行命令

for i in $(seq 2 2 8);do echo $i;done # seq命令就是以开头,中间为间隔相加,直到最后一个数,得到结果就是2,4,6,8

PS:由于是命令,所以在循环体中前面要以$开头,并且命令要用在()内

使用for循环执行命令读取文件内容

for i in $(cat test.txt);do echo $i;done # 读取文档内容

查看脚本是否运行成功,echo $? ,结果是0即表示成功,非0表示未成功

脚本名称abc.sh

echo "The  $? is $?"

echo "The  $0 is $0"

echo "The  $1 is $1"

echo "The  $2 is $2"

echo "The  $* is $*"

echo "The  $# is $#"

执行脚本 ./abc.sh haha heihei

输出结果

The $? is 0  #  $? 查询得到0,表示脚本运行成功了
The $0 is ./abc.sh  # $0 表示命令本身
The $1 is haha  # $1 表示命令的第一个参数
The $2 is heihwi  # $2 表示命令的第二个参数
The $* is haha heihwi  # $* 表示命令后面所有的参数
The $# is 2 # $# 表示命令后面有几个参数

通过if/then/elif/then/else 来进行多条件判断

if [ "$*" == "haha" ];then  # 判断指令参数后面是否是haha
    echo "heihei"   # 正确输出
elif [ "$*" == "heihei" ];then # 判断指令后面是否包含heihei
    echo "haha"  # 正确输出
else  # 如果都不是
    echo "heihei or haha" # 输出提示信息
fi  # fi就是语法结尾,就是if的倒写
PS:要注意[ ] 中空格,格式必须是前后有空格,中间间隔也要空格,对格式要求严格

使用正则表达式进行匹配

行中完全匹配表达式

grep cat /usr/share/dict/words  # 搜索多有带有cat的单词

grep ^cat /usr/share/dict/words # 搜索以cat开头的单词

grep cat$ /usr/share/dict/words # 搜索以cat结尾的单词

grep ^cat$ /usr/share/dict/words  # 搜索以cat开头并cat结尾的单词

grep ^c.t$ /usr/share/dict/words # 搜索以c开头t结尾的单词,中间的点表示中间只有一个单词,中间需要几个单词就可以用几个点

grep ^"c.{3}t"$ /usr/share/dict/words  # 搜索以c开头t结尾的单词,花括号中的数字表示中间单词数

grep ^c.t$ /usr/share/dict/words # 搜索以c开头t结尾的单词

grep ^c.*t$ /usr/share/dict/word # 搜索所有以c开头t结尾的单词

grep ^c[ao]t$ /usr/share/dict/word  # 搜索所有以c开头中间含有a或0,以t结尾的单词

grep -i ^"c.t"$ /usr/share/dict/words  # 忽略大小写匹配

cat /var/log/messages | grep -i error # 搜索日志错误信息,忽略大小写

cat /var/log/messages | grep -i  -A 5 error # 搜索日志错误信息,忽略大小写并且显示后五行的内容

cat /var/log/messages | grep -i  -B 5 error # 搜索日志错误信息,忽略大小写并且显示前五行的内容

cat /var/log/messages | grep -i  -C 5 error # 搜索日志错误信息,忽略大小写并且显示前后五行的内容

案列参考

yum install httpd 

cd /etc/httpd/conf

cat httpd.conf | grep -v "^[#;]" | grep -v ^$ | grep -v ^"    #"

 正则匹配参数表

参数

描述

.

匹配任何单个字符

?

只匹配一次

*

匹配0此或多次

+

匹配1次或多次

{n}

匹配n次

{n,}

前面的项目匹配n次或更多次

{,m}

前面的项目最多匹配m次

{n,m}

前面的项目匹配n次,但不超过m次

[:alnum:]

等同于[0-9A-Za-z]

[:alpha:]

等同于[A-Za-z]

[:blank:]

空白字符,空格和制表符

[:cntrl:]

控制字符,对应八进制000~037和177

[:digit:]

数字0~9

[:graph:]

图形字符‘[:alnum:]’和‘[:punct:]’

[:lower:]

对应小写字母a~z

[:print:]

可打印字符‘[:alnum:]’、’[:punct:]’和空格

[:punct:]

对应特殊字符!”#$&()’+-./;:<=>等

[:space:]

空格字符

[:upper:]

大写A~Z

[:xdigit:]

十六进制数0~9,A~F,a~f



匹配词语两侧的空字符串

B

匹配词语中间的空字符串

<

匹配词语开头的空字符串

>

匹配词语末尾的空字符串

w

匹配词语组分,‘[_[:alnum:]]’的同义词

W

匹配非词语组分,‘[^_[:alnum:]]’的同义词

s

匹配空格‘[[:space:]]’的同义词

S

匹配非空格,’[^[:space:]]’的同义词

grep命令参数表

参数

描述

-i

不区分大小写

-v

仅显示不包含正则表达式匹配项的行

-r

递归

-A

显示正则表达式匹配项之后的行数,参数后跟数字表示行数 –A 5

-B

显示正则表达式匹配项之前的行数,参数后跟数字表示行数 –B 5

-C

显示正则表达式匹配项前后的行数,参数后跟数字表示行数 –C 5

-e

使用多个正则表达式,并将与逻辑or并用

64、计划任务crontab

操作系统会默认安装一个软件包at,包含atd守护进程,和一组命令(at,atq)等。安装操作系统后是默认安装的,并自动启用atd守护进程

创建临时性的计划任务:at now + 5min(5分钟之后),teatime tomorrow(下午16点),noon + 4days(4天之后的中午12点),5pm august 3 2021(2021年8月3日下午5点)

PS:at命令非常灵活,可以用多种高级语言格式,但是只用作单次计划任务,at -l 查看队列中的计划任务,atrm number 就是删除执行作业号的任务

例:配置防火墙时候一个失误,不小心创建了规则自己也无法远程了,这时候在配置防火墙前先做一个防火墙配配置备份,使用临时计划任务进行定时还原

创建防火墙规则备份: iptables-save > /tmp/iptable.save

还原防火墙规则:iptables-restore > /tmp/iptables.save

需求计划任务来还原防火墙规则
at now +5min # 执行这句命令,5分钟后执行任务,这时候会提示以bin/sh的方式运行
iptables-restore /tmp/iptables.save # 会提示以/bin/sh运行,确认没问题后输入还原命令
当命令创建好后,使用ctrl + d 结束,这时候会提示计划任务完成
①2 ②Wed Mar 11 16:04:00 2020 ③a ④root  #这里是ctrl+d后提示的信息 1 作业的唯一编号 / 2执行的日期时间 / 3 作业的队列默认a,不同的作业可以排入不同的队列  /  作业所属用户,普通用户只能看自己的作业

PS:编辑好crontab后需要重启服务才能生效    /etc/init.d/cron restart

PS:iptable.save备份文件中命令详细信息在$(SHELL:-/bin/sh)这个下面,上面的都是环境变量

65、周期性的计划  # 反复执行的计划任务,不推荐使用这种方式,推荐使用使用脚本目录cron执行周期性的计划任务

PS:使用这个方式的缺点就是系统不会检查任务有没有执行,一旦由于其他因素比如在计划任务节点时候系统关机了,然后再开机则不会在执行,使用脚本cron脚本目录如果在系统异常时候错过节点则系统还原后会检查任务有没有执行,如未执行则会执行任务

周期性的计划任务是有crond守护进程管理的,由cronie软件包提供,系统默认安装,crond守护进程读取多个配置文件,crontab命令编辑配置文件,如果计划任务失败,crond会发送邮件给指定的用户

crontab -e 打开的文本编辑就可以开始定义计划任务,计划任务文件保存的路径 /var/spool/cron,以账户名称命名

计划任务格式: 23 14 * * * /bin/echo test  # 格式是5段,分钟、小时、日、月、星期,格式后面直接跟命令即可

PS:其中日的参数表示日期,多个日期可以用,间隔表示。每隔多少天可以用*/数字表示。星期和日月是或的关系,满足任意条件就可触发,拥有最大的包容性

例:计划任务

0 6 * * * systemctl restart httpd  # 0分6小时 每天每月每周的每天,就是每天早上6点重启apache

30 6 * * * systemctl restart httpd  # 就是每天早上6点30重启apache

30 6 15,30 * * systemctl restart httpd # 每个月15号和30号早上6点半重启apache服务

30 6 */10 * * systemctl restart httpd # 每隔十天重启一次服务

30 6 1 1 * systemctl restart httpd # 每年的1月1号重启服务

30 6 * * 7 systemctl restart httpd # 每个周日重启服务,星期中日可以用7、0、sun表示

30 6 1 * 7 systemctl restart httpd  # 逢周日或每月第一天早上6点30重启服务

30 6 * * 1-5 systemctl restart httpd # 每周1-5重启服务

0,30 * * * * echo 3 > /proc/sys/vm/drop_caches  # 每隔半小时清空系统缓存

* 9-17/2 * * * echo 3 > /proc/sys/vm/drop_caches  # 工作日的每天9-17点,隔两小时清空一次缓存

PS:*表示始终,x-y表示范围,x,y表示列表,*/y表示时间的间隔

66、使用脚本目录cron执行周期性的计划任务  # 推荐使用这个执行计划任务,会在系统重启或故障排除后进行任务执行检查,对于未执行的任务继续执行

目录的位置在 /etc/ 下不同目录定义的格式不通

cron.d  # 这个目录下定义的格式  0 6 * * * systemctl restart httpd,可定义时间

cron.daily # 存放可执行的脚本,缺点无法指定时间,而是每天运行一次

cron.hourly  # 存放可执行的脚本,缺点无法指定时间,而是每小时运行一次

cron.monthly  # 存放可执行的脚本,缺点无法指定时间,而是每月运行一次

cron.weekly  # 存放可执行的脚本,缺点无法指定时间,而是每周运行一次

PS:服务器异常重启或恢复后作业会几分钟延迟启动,配置作业延迟的文件是 /etc/anacrontab中RANDOM DELAY 项,随机的分钟内延误执行,nice的值越高优先级越低

67、tuned傻瓜式调优配置来优化系统性能

默认redhat中已经安装软件包,如没有手动进行安装

yum list | grep tuned # 查看在线能够安装的调优策略,使用yum install name 进行策略下载

yum install tuned  # 安装软件包

systemctl enable --now tuned  # 启动服务并且设置成自启动

systemctl status tuned # 查看服务状态

tuned-adm active # 查看当前的调优策略

tuned-adm list # 列出系统中所有预定义的调优策略

 ---------------------------对应策略含义-------------------------------

balanced  # 针对平衡优化 
desktop  # 针对低延迟,桌面应用
latency-performance  # 高性能低延迟,比如股票交易系统
network-latency  #  高性能低延迟,在latency-performance 的基础上增加了网络调优的项,更多的从cpu和内存上进行优化
network-throughput  # 针对大吞吐量的网络服务,如ftp,更多从IO,磁盘和网络上进行优化
powersave  # 节能
throughput-performance # 高吞吐高性能,针对高磁盘IO的场景
virtual-guest # 针对虚拟机
virtual-host # 针对运行虚拟机的主机

------------------------------------------------------------------------------

策略文件的路径:/usr/lib/tuned/

PS:每个目录对应的是调优策略的名称,进入目录下就是对应的配置文件

vim tuned.conf  # 编辑配置文件

-------------------------配置文件详解---------------------------------

[cpu] # CPU的调优选项

[sysctl] # kernel 的调优选项

vm.dirty_ratio=10  # 脏页攒到剩余内存的百分之10,强制写入磁盘

vm.dirty_background_ratio=3 # 后台占到剩余内存的百分之3,在后台强制写入磁盘

vm.swappiness=10 # swap交换分区的占比,从磁盘中划分一个分区代替物理内存,将物理内存中不常用的页放到磁盘中,这样物理内存就可以释放空间,供应用程序运行

kernel.sched_migration_cost_ns=5000000 # 应用程序调度需要花费的时间

包括调度的时间,脏页回收的时间,后台进行脏页回收的百分比。脏页就是应该要写入磁盘的数据没有写入磁盘,这些数据在内存中,积攒到一定程度一并写入磁盘,如果数据在内存中这些数据就无法使用,所以要实现低延迟就要经常把脏页写入磁盘,能够使用这些数据。

-----------------------------------------------------------------------------

使用调优的选项

tuned-adm profile latency-performance  # tuned-adm profile 后面跟调优的策略名称

tuned-adm recommend # 自动分析系统的负载,推荐调优的策略

自定义调优策略

配置写在  /etc/tuned

PS:在 /usr/lib/tuned 目录下用来查询,不能用来做修改,自定义的策略配置文件的添加和修改应该写在 /etc/tuned 目录下,如果要修改应从/usr/lib/tuned目录下复制到etc下,然后再进行修改

mkdir test # 在usr/lib/tuned目录下创建自定义调优策略目录

cd test # 进入目录

vim tuned.conf # 编辑配置文件

------------------------写入自定义的内容---------------------

[main]

include = latency-performance

[sysctl]

vm.swappiness = 30 # 定义了脏页的百分比

---------------------------------------------------------------------

tuned-adm profile test  # 使用自定义配置文件

cat /proc/sys/vm/swappiness # 查看脏页配置有没有修改成功

基于web console 使用界面进行调优

如何进入web console 详见61

68、控制进程的调度

现代计算的系统有一个共同点:需要运行的进程线程数量超出了其CPU的数量。通过使用称为time-slicing或multitasking的技术,Linux和其他操作系统可运行超出其处理单元数的进程。操作系统进程调度程序在单个核心上的进程之间快速切换,从而给人一种有多个进程在同时运行的印象。

cpu的调度的原理

1、以前的cpu调度策略叫o1

run-queue 1 2 3 4 5  # run 里面比如有5个进程号

wait-queue  # wait-queue 等待run-queue里面的进程放进来

等run-queue里面的进程都放到wait-queue里面后,两个名字互换,持续这样的调度策略,实现多进程运行

2、现在的cpu调度策略叫cfq,相对优先级

完全平均的,给一个时间片,假设0.01秒,在时间片里面将所有的进程全部运行一遍,一直这样周而复始实现多进程运行。正常情况下一秒钟所有进程调度667次。每个进程都有一个时间片,权重(time-slice)是1024,大家平均去分配667分之一秒的时间去运行一次.。例如一个程序要提高优先级,则将time-slice设置成2048,那就是其他程序的两倍,如果要降低优先级,则将time-slice设置成512,就是其他程序的一半运行时间。

系统上大多数进程所使用的调度策略称为SCHED_OTHER(也称为SHCED_NORMAL)

SCHED_OTHER  # 针对普通进程

SCHED_FIFO  # 针对实时进程,比如键盘、屏幕显示是实时进程,优先级高于-20

SCHED_RR  # 针对实时进程,一个时间片667分之一秒里面95%的时间会给这个里面的进程进行轮询,剩下的时间分配给其他进程。优先级高于-20

SHCED_IDLE  # 发呆调度,优先级比19还低

可为采用SCHED_OTHER策略运行的进程指定相对优先级,称为nice值,对于任何进程,有40种不同级别的nice值可以设置。nice值的范围介于-20(最高优先级)到19(最低优先级)之间。默认情况下,进程将继承其父进程的nice值,通常为0。因为所有进程都是systemd的子进程,而systemd的nice值就是0。nice值越高表示优先级越低,nice值越低表示优先级越高。如果不存在资源争用,例如当活动进程数少于可用CPU核心数时,即使nice值高的进程也将仍使用尽可能多的cpu资源

只有root用户可以降低进程的nice值,就是提高优先级。普通用户仅限于提高自己进程的nice值,就是降低优先级。

使用top命令查看nice值(NI)和(PR)

通过ps命令可以显示nice值:ps axo pid,comm,nice,cls --sort=-nice  # cls就是调度策略,TS针对的就是SHCED_NORMAL

nice值修改案列

top命令中,输入r,输入需要调整nice值的进程PID,然后输入-20~19的值

69、访问控制列表ACL 

标准linux文件权限即可满足一般要求,当要求指定 的用户和组以不同的权限来访问文件时,就需要使用ACL。用户可以对自己的文件和目录设置ACL,新文件和子目录自动从父目录的默认ACL中继承ACL。父目录至少要有X权限(大写X,就是进入权限)。

PS:文件系统需要在挂载选项上启用ACL支持。XFS文件系统内置ACL,ext3或ext4文件系统挂载默认启用ACL选项。要启用文件系统ACL支持,需要在mount命令或 /etc/fstab中有ACL挂载选项。

 

查看文件系统的ACL

使用mount命令查看文件系统的挂载选项

/dev/sda1 on /boot type xfs (rw,relatime,seclabel,attr2,inode64,noquota)  # seclable 这个选项就是可以定义ACL

不使用ACL,vi /etc/fstab 对应的文件系统的defaut后面加noacl  #  /dev/sda3  /cm   ext3    defaults,noacl    0 0

PS:使用ll查看文件信息,在权限后面是一个 + 就是带有ACL权限,可以使用getfacl filename 查看文件的acl信息

给文件设置ACL命令: setfacl -m u:student:--- filename # u表示是用户,也可以设置g组或者o其他,---这里表示权限(---表示无任何权限),filename就是文件名

------------给文件设置ACL权限--------------------------

root用户下根目录新建test.txt文件

chmod 644 test.txt # 设置文件的权限

setfacl -m u:admin:--- test.txt  # 设置admin对于此文件没有任何权限

ll test.txt  # 可以看到权限后面带+

getfacl test.txt  # 查看ACL

su - admin

cat test.txt  # admin没有任何权限

------------------------------------------------------------------

----------------ACL的信息解读-----------------------------

使用getfacl test.txt 查看ACL信息

file: test.txt   # 文件名
owner: root  # 所属用户
group: root  # 所属组
user::rw-  # 所属用户的权限

user:1005:rwx  # 这个UID是1005的用户,本地不存在,可能来自于网上或者域服务器,这属于正常
user:admin:---  # ACL
group::r--
mask::r--
other::r--

PS:在ACL所有的权限不能超过mask的权限,mask是遮罩也就是最高权限,比如mask的权限是r,组和其他非本地用户可能只有r的权限,

------------------------------------------------------------------

ACL的权限

ACL的权限优先级,首先匹配用户的ACL,如果匹配上则后面的权限忽略,如果没有匹配上则在继续匹配用户组,都匹配不上则就是默认的文件权限

r表示读取权限,w表示写入权限,x表示执行权限,-表示缺少相关权限,大写X表示只设置目录(不会对文件设置)的执行权限,-m选项设置ACL

PS:设置ACL权限的时候,命令setfacl -m u::rwx,g:con:rX,o::- filename 两个::就是表示所有用户(组,其他)

PS:递归ACL修改使用 -R,在递归时候目录需要执行权限所以要加大写X,对文件则无需大写X执行权限,如果以非递归方式设置ACL,也最好使用大写X,可防止意外的向普通文件添加执行权限

setfacl -Rm u:name:rwX 目录名

通过查看A文件的ACL然后设置到B文件

setfacl a.txt | setfacl --set-file=- b.txt

目录设置默认的ACL,这样在设置ACL后,再在此目录下新建目录也会携带默认的ACL权限,就是目录的权限遵循default

setfacl -Rm d:u:name:rwX 目录名  # 在u前面加d:

删除ACL

从文件或目录ACL中删除指定用户和组,其他现有ACL条目均保持不变  setfacl -x u:name,g:name file  # 删除指定得用户和组的ACL,在操作次数多以后容易配置混乱

删除文件或目录的所有ACL(包括默认ACL) setfacl -Rb dirfile  # 推荐使用这条命令删除所有ACL,从头开始设置ACL比较清晰

经典案列

lampp平台 # linux+apache+mysql+php

查看当前安装目录/opt/lampp的权限和所属用户和组   #  777 admin:admin

案列要求目录权限是755,文件是644

chown -R root:root /opt/lampp # 设定目录所属用户和组

chmod -R 644 /opt/lampp   # 设定目录的权限

chmod -R ugo+x /opt/lampp  # 设定目录的执行权限,

setfacl -Rm u:admin:rwx /opt/lampp # 设置目录所属用户的ACL

setfacl -Rm d:u:admin:rwx /opt/lampp  # 设置默认ACL

passwd admin  # 重设admin的密码

usermod -s admin /sbin/nologin  # 不允许登录,只能以服务形式授权,centos中用户名放在最后usermod -s /sbin/nologin admin

PS:根据原有的设置不变,升级安全等级,所以针对admin用户有755的权限,其他用户和组以及目录文件遵循要求设置权限

70、SElinux

SELinux的标签,也就是上下文(context),SELiux有一组安全规则,定义进程可以访问哪些文件,目录和端口。每个文件、进程、目录和端口都有专用的标签,只有相同的标签才能相互访问。

PS:新文件通常从父目录继承其SELinux context(标签),mv或cp -a这两个命令除外

SELinux由若干组策略组成,这些策略准确的声明了对于应用使用的每个可执行文件,配置文件和数据文件。哪些操作和访问是被允许的,这被称为targeted policy。策略声明了各个程序、文件和网络端口的预定义label。

SELinux有三种模式

1、Enforcing 强制模式  # 一切要遵守控制规则,一旦违反规则记录日志,计算机通常在改模式下运行,不需要重启系统

2、Permissive 宽容模式  # 不强制准守规则,但是违反规则记录日志,改模式通常用户测试和故障排除。不需要重启系统

3、Disabled 关闭模式  # 完全关闭SELinux,必须要重启计算机

设置SELinux的模式

getenforce  # 查看当前状态(模式)

临时生效命令

setenforce 1 # 设置 Enforcing 强制模式

setenforce 0 # 设置 Permissive 宽容模式

永久生效

vim /etc/sysconfig/selinux  # 配置文件中写入对应的模式

setenforce number # 必须还要通过命令设置一次配置文件中对应的模式

PS:/etc/selinux/config 这个文件是一个软连接,连接到selinux的配置文件,所以在设置模式写配置文件是用/etc/selinux/config 或 /etc/syscinfug/selinux效果是一样的

SELinux的标签有多种,user、role、type和sensitivit

目标策略(target policy 即rhel中启用的默认策略),会根据第三个标签(即type context 来制定自己的规则,通常以 _t 来结尾)

dr-xr-xr-x. root root ①system_u:②object_r:③boot_t:④s0  # 1就是用户,2就是对象,3就是类型,4就是调度

SELinux的命令

ls -Z # 查看标签

ls -Zd 目录  # 在其他目录下查看指定路劲目录的标签

chcon -t context_name filename  # 修改指定文件的标签,不需要执行restorecon

chcon -Rt context_name *  # 当前目录文件和子目录一起修改标签

semanage fcontext -a -t context_name "/srv/html(/.*)?" # 设置默认的目录标签,新建文件或子目录自动继承父标签,命令后面目录的路径双引号和单引号都可以

restorecon -Rv dir  # 修改标签后需要执行这条语句才能修改成功

使用布尔值调整SELinux策略

semanage boolean -l # 查看bool值其状态

setsebool context_name on # 修改开关状态为开启,最后的on是参数,改成off就是关闭

getsebool -a # 查看bool值其状态,显示的信息比较简略

分析和解决SELinux问题

使用SELinux日志分析工具

ausearch -m avc  # 分析审计日志

安装setroubleshoot-server软件包,侦听/var/log/audit.log中的审核消息,将SELinux消息发送至/var/log/messages

tail -n 30 /var/log/messages # 查看日志文件最后30行,日志中已经告诉排错的指令

71、磁盘分区

MBR分区方案,最多支持4个主分区,支持扩展分区和逻辑分区,最多创建15个分区,分区大小以32位值存储,最大磁盘分区为2TB,缺点是存在单点故障(分区表损坏,分区表是在硬盘开头的地方)

 PS:最多主分区是4个,通常当我们创建三个分区后,第四个分区会创建扩展分区,扩展分区使用剩余的空间,然后在扩展分区中创建逻辑分区,最多不能超过vdb15(扩展分区有默认编号,默认编号vdb4),逻辑分区编号从5开始至15

GTP分区方案,对于使用UEFI固件的系统,默认使用GPT分区方案,解决MBR方案的缺点。GTP最多128个分区,64位值存储分区大小,最大磁盘和分区大小可以达到8ZiB。GPT使用全局唯一标识符(GUID)来识别每个磁盘和分区,主GPT位于磁盘头部,而备份副本位于磁盘尾部。

使用Parted管理分区 # 红帽8开始使用这个工具

Parted工具可以管理MBR和GPT分区方案

使用fdisk创建分区 # fdisk无法通过脚本进行分区,不支持脚本,但是未保存的操作不会生效

fdisk /dev/vdb

m  # 帮助

n  # 创建

p  # 查看分区表

d  # 删除

t  # 转换分区类型

w  # 保存退出

创建分区步骤

1、fdisk /dev/vdb  # 命令后面跟需要分区的磁盘

2、p  # 查看分区表,可以看到能够分配的控件

3、n  # 创建分区,选择primary还是extended

4、确定分区号,直接回车

5、扇区大小确认,如果默认直接回车 

6、last sector  # 可以输入扇区的号或者大小,比如需要加1G,直接 输入+1G然后回车即可

7、w  # 保存

8、partprobe  # 让内存重新加载一次分区表

PS:如果创建多分区,创建完一个后直接输入n,继续创建

PS:在创建完分区或者创建分区的时候,使用p查看所有的分区信息,然后输入t,选择需要转换第几个分区,然后输入L可以查看所有能够转换的分区类型,输入对应的序号

使用parted创建分区  # 创建过程中所有的命令参数不清楚可以使用help + 命令 查看参数,支持脚本,可以实现脚本分区

PS:这个工具的缺点就是要自己计算扇区大小,不能直接提供分区大小。也就是如果给一个2T的磁盘,创建多个分区时候要计算扇区大小来设置分区的空间

1、parted  /dev/vdc   # 命令后面跟需要进行分区的磁盘

2、mklabel  msdos # 重新定义分区表,可以使用help mklabel 查看能够定义的类型

3、unit  MiB # 如果不指定则默认单位是MB

4、mkpart  # 创建分区,后面不定义就会进入引导

5、Partition type会提示类型,选择一个输入

6、File system type  # 文件系统类型,不清楚按两下tab键,出现类型提示

7、Start?  # 扇区开始大小。新硬盘可以输入1,即从1开始,如果是已存在则需要自己计算

8、End   # 结束扇区的大小,默认单位是MiB,就输入1024 ,此时就是定义了分区大小

9、print  # 查看分区

10、quit  # 退出

11、udevadm settle  # 内存重新加载一次分区表,同partprobe

PS:使用脚本创建分区,parted mkpart primary linux-swap 1 2048,一条命令创建一个2G的分区

使用parted删除分区

1、parted /dev/vdb  # 操作指定的分区

2、print  # 查看分区

3、rm  分区号  # 直接删除分区,无法回退

72、创建文件系统

红帽支持多文件系统,常用的是XFS和ext4

rhel安装程序Anaconda默认使用XFS,使用mkfs.xfs命令为块设备应用XFS文件系统,对于ext4使用mkfs.ext4

mkfs.xfs /dev/user  # 命令后面跟路径,对磁盘进行格式化

mkfs.ext4 /dev/user 

73、交换分区swap

当系统物理内存不够时,将不常用的页放到磁盘中,释放物理内存运行程序,缺点就是swap位于磁盘上,速度和效率较慢

使用parted创建swap分区,将文件类型设置为linux-swap

parted  /dev/vdb 

mkpart

swap1 # 创建分区名

linux-swap # 设置文件系统类型

quit  # 退出

undevadm settle 

mkswap /dev/vdc2  # 格式化

vim /etc/fstab # 写配置文件自动挂载

UUID='xxxxxx' swap swap defaults 0 0

free -m(swapon -s) # 查看系统中已有的swap

swapon /dev/vdc2  # 加载swap

多磁盘swap # 优先级设置

UUID='xxxxxx' swap swap defaults,pri=0 0 0  # 老磁盘

UUID='xxxxxx' swap swap defaults,pri=5 0 0  # 新磁盘

reboot  # 设定好后需要重启

PS:当老磁盘速度慢,新磁盘速度快是,可以使用pri参数来设定swap写入的优先级,值越大优先级越高

PS:机械硬盘做swap一定要放在第一个分区

PS:swap也可以做负载,如果一个电脑上有多快硬盘,swap的pri值可以设置成一样,这样在写swap的时候会同时写入数据,起到负载,速度效率增加一倍

74、逻辑卷的管理

逻辑卷的创建过程:块设备(还未格式化的硬盘)> PV(创建) > VG(创建VG) >  LV(创建LV) > File System(创建文件系统) > mount(挂载)

创建逻辑卷

使用parted创建

1、parted /dev/vdb

2、mklabel # 选择磁盘类型

3、mkpart # 回车

4、primary # 选择文件系统类型ext4

5、start? # 选择磁盘开始大小

7、end?  # 选择磁盘结束大小

8、print # 查看分区

9、set 1 lvm on  # 数字1是表示分区的顺序号

10、udevadm settle

11、lsblk  # 查看磁盘信息

使用fdisk创建逻辑卷

1、fdisk /dev/vdc

2、n  # 后续一直回车

3、command 选输入t

4、输入8e

5、输入w

6、partprobe  # 保存

7、lsblk  # 查看分区

创建PV

1、pvcreate /dev/vdb1 /dev/vdc1 /dev/vdd1  # 一条指令可以创建多个逻辑卷的PV

2、pvdisplay # 看到pv的情况和有无数据

3、pvs # 这条指令可以看到简略的情况

创建VG

1、vgcreate -s 8M vgtest /dev/vdb1 /dev/vdc1  # 在vg中创建lv最小大小必须是8M的整数倍,默认是4M,vgtest就是vg的名称

2、vgdisplay  # 查看vg的情况

PS:vgs指令可以看到简略情况

创建LV

1、lvcreate -n lvtest1 -L  3G vgtest  #lvtest1就是lv的名称,3G就是创建的大小, vgtest就是针对哪个vg也就是vg名

2、lvdisplay  # 查看lv

步骤总结:

1、fdisk # 创建磁盘

2、类型要转成lvm,选择8e类型

3、pvcreate /dev/vdb1 /dev/vdc1  # 将需要创建的磁盘创建pv

4、vgcreate vgname /dev/vdb1 /dev/vdc1  -s 16M  #  创建vg,vgname就是vg名称,然后输入设备名,-s后面跟pv的大小,默认就是4M

5、 lvcreate lvname -L size vgname # -L size 也可以写成 l penumber

6、pvdisplay(pvs) / vgdisplay(vgs) / lvdisplay(lvs)  # 查询命令

8、mkfs.ext4 /dev/vname/lvname 或 mkfs.ext4 /dev/mapper/vgname-lvname  # 格式化逻辑卷

逻辑卷扩容

lvextend(lvresize)  -rL 5G /dev/vgname/lvname  # 扩容时候一定要文件系统的完整路径,这条命令中参数容量大于需要扩容的磁盘则是扩大,如果小于就是缩小磁盘容量

PS:如果命令中忘记加r参数,在df -h的命令查看磁盘状态的时候会发现没有扩容成功。使用 resize2fs 5G /dev/vgname/lvname 这条命令即可

PS:ext4的磁盘类型支持扩容和缩小,xfs的磁盘类型只能支持扩容

vg的空间扩容

1、pvs 查看pv有无空间

2、vgextend vgname  /dev/vdd1  # 把空余的pv加入指定的vg中

3、vgs 查看创建成功否

删除逻辑卷

1、vim /etc/fstab  # 将里面自动挂载的卷用 # 注释掉

2、umount /mnt/fxs  # 取消挂载

3、lvremove /dev/vgname/lvname  # 卸载

执行删除逻辑卷命令失误,删错了逻辑卷,使用备份还原

1、 cgcfgrestore -l vgname  # 这条命令中可以看到备份的镜像,name.vg 

2、vgcfgrestore -f /etc/lvm/archive/vgtest_0008-114114114.vg vgname  # 命令后面跟镜像的路径和vg名称

3、输入y

4、lvchange -an /dev/vgname/lvname # 激活逻辑卷

5、lvchange -ay /dev/vgname/lvname  # 激活逻辑卷

75、使用stratis本地存储管理系统管理存储,并使用VDO卷优化使用中的存储空间  # 红帽的新特性

Stratis就是现有的存储上多了一个存储管理工具,红帽8中退出了Stratis存储管理方案,服务以管理物理存储设备池的形式进行。使用元数据(就是描述信息)来识别所管理的池、卷和文件系统。一旦使用了Stratis来管理,绝不能对Stratis创建的文件系统进行

PS:一旦使用Stratis管理工具,则fdisk等命令不能使用,一旦使用磁盘则损坏

Linux系统有存储栈,最底层的是硬件,硬件的硬盘分为虚拟硬盘如/dev/vd1,SCSI接口的硬盘包括SATAIDEUSB等均使用SCSI协议的。然后通过驱动或中间层或DM-mnultipath(就是双线连接预防一根坏了另一根可继续使用)将硬盘连接到操作系统就称为块(Block Layer),可以直连也可以通过Device Mapper做映射。然后对块做分区和格式化后就是文件系统称为VFS,供应用系统访问。

PS:文件系统都遵循unix中标准的存储协议POSIX,无论是EXT4、fxs等都是遵循标准的文件系统

Stratis的架构 :所有硬盘放到一个池,在池里面直接创建文件系统,文件系统格式化、逻辑卷和映射等都无需管理。池可将块设备分组到数据层,或分组到缓存层(可选)。数据层侧重于灵活性和完整性,而缓存层则侧重于提高性能(SSD)。 还可以对存储打快照。

管理Thin-provisioned的文件系统,需要安装stratis-cli和stratisd软件包

stratis-cli软件包提供了stratis命令,将用户请求发送到stratisd服务

1、yum install stratis-cli stratisd  # 安装软件包

2、systemctl enable --now stratisd  # 启动服务并开机自运行

3、stratis pool create pool1 /dev/vdb  # 创建名为pool1的池
4、stratis pool list  # 查看池列表,也能看到快照

5、stratis pool add-data pool1 /dev/vdc  # 将一块硬盘加入池中

6、stratis blockdev list  # 查看池中有哪些硬盘

7、stratis filesystem creat  pool1 stratis-filesystem1 # 从pool1池中创建文件系统,后面的 stratis-filesystem1是文件系统的名字,这个名称自定义

8、blkid  # 查看UUID

9、mount UUID  # 挂载

10、stratis filesystem snapshot pool1 stratis-filesystem stratis-filesystem1-snap  # 对pool1池中文件系统创建快照,快照名字为stratis-filesystem1-snap

11、stratis filesystem destroy pool1 stratis-filesystem1  # 删除文件系统,从pool1池中删除名为stratis-filesystem1 的文件系统

PS:快照占用实际空间,如果把磁盘数据删除,可以使用挂载快照做到回复,blkid查看快照的路径,复制整个路径进行挂载即可还原数据

PS:使用df -h 查看的空间是不准确,使用stratis pool list  查看才是准确的

PS:配置不定义文件系统大小,根据池的大小动态分配,用多少给多少,不能超过池中硬盘的大小

PS:需要永久挂载,在/etc/fstab添加参数,UUID=31B.....02B /dev xfs defaults, x-systemd.requires=stratisd.service 0 0,必须要添加 x-systemd.requires=stratisd.service整个参数,延迟挂载文件系统,直到systemd在启动过程中启动stratis.service为止,如果stratis服务没启动,直接进行挂载则文件系统会损坏

使用VDO压缩存储和删除重复数据  # 适合用于备份

PS:VDO卷与磁盘分区类似,创建的逻辑设备称为VDO卷。VDO卷的逻辑大小可以大于实际块设备的物理大小。如果在创建卷时未指定逻辑大小,则VDO会将实际物理大小视为卷的逻辑大小,这种采用1:1的比率映射方式有利于提高性能。但是会降低存储空间的使用效率,

VDO(Virtual Data Optimizer),是一个Linux device mapper驱动程序,它可以减少块设备上的磁盘空间使用,同时最大限度减少重复数据,从而节省磁盘空间,甚至提高数据吞吐量。VDO包括两个内核模块,kvdo模块用于透明的方式控制数据压缩,uds则可用于重复数据删除。VDO层位于块存储设备的顶部,存储层(如LMV逻辑卷和文件系统)位于VDO设备之上

VDO按以下顺序对数据实施三个阶段处理,做到压缩

1、消除包含0的数据块

2、重复数据删除

3、压缩

使用VDO

1、yum install vdo kmod-kvdo  # 安装vdo

2、vdo create --name=vdo1 --devier=/dev/vdd --vdologicalSize=500G  # 创建VDO的卷名字叫vdo1,对应的块就是/dev/vdd 、如果块设备是50G,则可以定义的虚拟大小500G,将来可以通过扩容增加vdd的容量,但是不能超过500G

3、vdo list  # 显示当前启动vdo卷的列表

4、vdo start / vdo stop  # 启动和停止vdo卷

5、mkfs.xfs -K /dev/mapper/vdo1  # 格式化,K就是快速格式化

6、udevadm settle  # 重新加载分区表

7、mount  /dev/mapper/vdo1 /mnt/vdo1  # 将vdo挂载

8、vdostats --human-readable  # 查看vdo的控件

76、NFS网络文件系统  # NFS是网络文件共享服务

创建NFS服务端

1、vim /etc/exports  # 全局配置文件

/nfsshare 192.168.1.10/24(rw,sync,no_root_squash) #共享的目录,共享给谁地址可以是主机名,也可以是ip地址或者 使用* 表示所有用户,掩码后面括号中是参数,rw表示能读写,sync立即同步(async是异步同步,性能好但是网络不稳定会导致文件丢失),no_root_squash参数表示root用户具有完全的管理权限

PS:修改全局配置文件后需要重新载入,exportfs -r

2、systemctl enable nfs-server --now # 启动服务

3、showmount -e servername/ip # 查看共享的网段

4、firewall-cmd --permanent --add-service=nfs  # 防火墙放行nfs服务

5、firewall-cmd --reload  # 重新载入防火墙

客户端挂载服务端共享目录

1、mount -t nfs serverb:/nfs /mnt/nfs  # 挂载目录类型是nfs,挂载的来源是serverb下的nfs目录,挂载到mnt/nfs目录

2、chmod o+w /nfs  #  在共享服务器上给目录添加其他用户写入权限,否则所有挂载这个目录的主机上都无法写入文件

使用autofs服务或systemd.automount功能进行按需挂载

REHL8引入了nfsconf工具,用于管理NFSv4和NFSv3的客户端和服务器配置文件

PS:在rehl7中配置文件是/etc/sysconfig/nfs,在rehl8中使用/etc/nfs.conf,两个版本的配置文件是不同的

使用命令进行基本的nfs配置  # 这里是使用命令修改配置文件

nfsconf --set nfsd udp n  # 禁用UDP协议

nfsconf --set nfsd vers2 n # 禁用NFSv2

nfsconf --set nfsd vers3 n # 禁用NFSv3

nfsconf --set nfsd tcp y # 启用tcp协议

nfsconf --set nfsd vers4 y # 启用NFSv4

nfsconf --set nfsd vers4 .0 y # 启用NFSv4.0

nfsconf --set nfsd vers4.1 y # 启用NFSv4.1

nfsconf --set nfsd vers4.2 y # 启用NFSv4.2

nfsconf --set nfsd vers4.3 y # 启用NFSv4.3

NFS参数说明

ro

只读访问

rw

读写访问

sync

所有数据在请求时写入共享

async

nfs 在写入数据前可以响应请求

secure

nfs 通过 1024 以下的安全 TCP/IP 端口发送

insecure

nfs 通过 1024 以上的端口发送

wdelay

如果多个用户要写入 nfs 目录,则归组写入(默认)

no_wdelay

如果多个用户要写入 nfs 目录,则立即写入,当使用 async 时,无需此设置

hide

在 nfs 共享目录中不共享其子目录

no_hide

共享 nfs 目录的子目录

subtree_check

如果共享 /usr/bin 之类的子目录时,强制 nfs 检查父目录的权限(默认)

no_subtree_check

不检查父目录权限

all_squash

共享文件的 UID 和 GID 映射匿名用户 anonymous,适合公用目录

no_all_squash

保留共享文件的 UID 和 GID(默认)

root_squash

root 用户的所有请求映射成如 anonymous 用户一样的权限(默认)

no_root_squash

root 用户具有根目录的完全管理访问权限

anonuid=xxx

指定 nfs 服务器 /etc/passwd 文件中匿名用户的 UID

anongid=xxx

指定 nfs 服务器 /etc/passwd 文件中匿名用户的 GID

nfs共享实例

一台servera服务器,开启了nfs服务并且共享了目录,serverb属于admin用户组的需要访问并永久的挂载servera的共享目录。serverb共享的是/shares/public,admin组成员(admin1,sysmanager1)具有/shares/public读写访问权限,serverb的挂载点是在/public

1、mkdir /public  # serverb上创建挂载目录

2、mount -t  nfs -o rw servera:/shares/public /public  # serverb上进行挂载,将servera的目录挂载到/public

永久挂载

1、vim /etc/fstab # servera(ip):/shares/public  /public nfs defaults,rw,sync 0 0

自动挂载 # 按需挂载

自动挂载器是一个系统服务(autofs),它可以根据需要自动挂载NFS共享,并在不使用时自动卸载共享。不需要永久连接,可释放网络和系统资源

自动挂载器的特点,无需root权限就可以运行mount和umount命令,autofs中配置的NFS共享可供所有用户使用,受访问权限约束。autofs在客户端配置,无需在服务器中配置,autofs与mount命令使用相同的选项,包括安全性选项。autofs支持直接和间接挂载点映射,可挂载和删除间接挂载点,从而避免手动管理。autofs默认网络文件系统是NFS,也可以自动挂载其他网络文件系统。

PS:直接挂载点就是绝对路径,明确的目录。间接就是相对路径,通配符挂载点

yum install autofs  # 安装autofs软件包

vim /etc/auto.master.d/demo.autofs  #  主配置文件写入内容,/shares /etc/auto.demo

vim /etc/auto.demo  # 辅配置文件写入内容,work -rw,sync servera:/shares/work,虚拟目录指向真正的挂载点

PS:autofs在配置的时候需要些一个主配置文件,就是定义一个基础目录指向辅配置文件,辅配置文件就是虚拟目录(虚拟目录前不能加 / ,加了会报错)指向NFS的真正挂载点 

直接映射(挂载)

vim /etc/auto.master.d/demo.autofs  #主配置文件写入内容,/- /etc/auto.direct, 所有直接映射条目都使用 根目录作为基础目录

vim /etc/auto.direct  # 辅配置文件和间接挂载是不同的,/mnt/docs -rw,sync servera:/shares/docs,辅配置文件中目录指向真正的挂载点,挂载点始终为绝对路径。

通配符挂载点

当NFS服务器的共享目录下有多个子目录,可将autofs配置为使用单个映射条目访问子目录中任意一个

vim /etc/auto.demo  #  辅配置文件中写入内容,* -rw,sync servera:/shares/&

配置直接和间接自动挂载点案列  # 在serverb服务器上操作

1、vim /etc/auto.master.d/direct.autofs  # /- /etc/auto.direct  直接挂在指向的是根目录下的etc下的辅配置文件是auto.direct

2、vim /etc/auto.master.d/indirect.autofs   #    /indirect /etc/auto.indirect  间接挂载指向本地的一个目录indirect下的辅配置文件auto.indirect

3、vim /etc/auto.direct  #  /direct -rw,sync  servera:/shares/direct  根目录下的direct挂在到servera上

4、vim /etc/auto.indirect  # * -rw,sync servera:/shares/&  # 将/indirect中所有的子目录挂载到servera的shares下的子目录中,

77、系统的修复

红帽8的启动过程

接通电源  ---> bois初始化硬件  ---> 将控制权交给boot分区中的GRUB2 ---> GRUB2读取配置文件 ---> 启动kernel和initramfs ---> kernel将参数传递给内存中启动的initramfs(mini linux) ---> mini linux 加载驱动程序,并且mini linux中的/sbin/init是一个纸箱systemd的链接,以PID1启动 ---> systemd将根分区挂载到sysroot目录 ---> 内存中的systemd 使用磁盘中的systemd来自我重新执行将根分区切换到真正的根分区---> 系统启动

/boot/grub2/grub.cfg  # 这个配置文件显示要启动的内核

grub.cfg使用 /etc/grub.d/ 和 /etc/default/grub 中的文件,然后使用grub2-mkconfig 命令进行配置

PS:不要直接修改grub.cfg文件,如果要修改只能修改 /etc/grub.d/ 和 /etc/default/grub 中的文件,然后使用grub2-mkconfig 命令进行配置

78、选择系统启动的模式

1、systemctl get-default  # 看系统默认的启动模式

2、systemctl set-default graphical.target # 设置启动模式为图形化界面,包含 muiti-user-target ,也就是说服务依赖于 muiti-user-target 

3、systemctl set-default multi-user.target  # 设置启动模式为命令界面

4、startx  #  启动图形化界面,无需输入账号密码直接进入桌面

79、重置root密码

1、启动界面按上下键,可以暂停自动菜单

2、按e

3、找到linux 行,光标移动到最后ro 后,然后按ctrl+k 删除ro后面所有的内容(是linux这一行ro后面的)

4、输入rd.break

5、按ctrl + x 启动

6、mount -o remount,rw /sysroot  # 将sysroot目录以读写方式重新挂载

7、mount |grep sysroot  # 查看挂载穆的权限

8、chroot  /sysroot  # 切换到chroot存放位置,其中/sysroot视为文件系统的根,也就是将根目录挂载到sysroot目录

9、passwd # 修改密码

10、touch /.autorelabel  # 修改密码是修改etc/shadow,此时selinux没有启动,这个文件就是没有打过标签的文件,启动时候会卡死,在才做系统启动时候对所有文件打一次标签,创建根目录下的隐藏文件

11、exit #  退出伪根chroot

12、exit  # 退出跑在内存中的linux(initramfs debug shell)

80、修复系统文件故障导致无法启动

当修改系统配置文件错误是导致重启后系统无法启动,此时系统会进入紧急shell界面,会提示输入密码进入用户

1、此时查看ip地址都没有,所以启动时没有启动起来

2、输入密码进入root用户

3、启动界面可以看到报错信息

4、打开修改的文件进行修复

81、防火墙的管理  # 红帽8中

linux内核中包含netfilter,它对网络流量执行操作(如数据包过滤、网络地址转换、端口转换等)。iptables和firewalld是防火墙管理器,用来管理netfilter中的规则。

linux内核中还包含了增强版的netfilter,启用了nftables后无法被iptables管理,只能使用firewalld。

PS:firewalld可以读取和管理iptables的规则,并使用xtables-nft-multi将iptables转换为nftables规则,不推荐转换操作

firewall会检查进入系统的每个数据包的源地址,如果该源地址被分配给特定的zone,则应用改zone的规则。如果该源地址未分配给某个zone,就会将数据包与传入网络接口的zone相关联,并应用改zone的规则。如果网络接口未与某个zone相关联,则firewalld会将数据包与默认zone相关联。默认zone不是一个单独的zone,而是指代现有的zone。forewalld指定public zone为默认zone,并将IO接口映射至trusted zone。

firewalld上有一些预定义的zone,可分别进行自定义。默认情况下,如果传入流量属于系统启动通信一部分,则所有zone都允许传入流量和传出流量

预定义zone

区域名称

默认配置

trusted

允许所有传入流量

home

流量出去不限制,进入只允许ssh、mdns、ipp-client、samba-client、dhcpv6-client这几个预定义服务匹配

Internal

与home区域相同

work

传出流量不限制,进入只允许ssh、ipp-client、dhcpv6-client这几个预定义服务匹配

public

传出流量不限制,进入只允许ssh、dhcpv6-client这几个预定义服务匹配

external

传出流量不限制,进入只允许ssh预定义服务匹配。通过此区域转发的IPV4传出流量将进行伪装,以使其看起来像是来自传出网络接口的IPV4地址

dmz

传出流量不限,进入只允许ssh预定义服务匹配

block

传出流量不限,拒绝一切传入流量,有消息提示

drop

传出流量不限,所有传入流量丢弃,无消息提示

 PS:firewalld开启后默认使用public zone,防火墙白名单,只放允许规则,不放拒绝规则应为默认全部拒绝,通常使用默认zone来做管理。

firewalld -cmd --get-services  # 查看所有预定义服务

yum install firewall-config  # 安装firewall图形化配置工具

firewall-config  # 启动图形化

常用命令

1、firewall-cmd --list-all  # 查看所有生效的规则

2、firewall-cmd --permanent --add -service=ftp # 添加ftp服务,permanent参数就是永久生效

3、firewall-cmd --reload  # 重新载入配置

4、firewall-cmd --permanent --add -port=8080/tcp  # 添加端口和协议类型

5、firewall-cmd --permanent --remove-port=8080/tcp  # 移除规则

82、Selinux 端口标记

所有知名的端口都有标记

semanage port -l  # 查看端口标签清单

semanage port -l -C # 查看对默认标签的修改,使用 -C

yum -y install selinux-policy-doc # 安装工具可以查看端口类型说明

当修改httpd的监听端口后,发现systemctl start httpd无法启动httpd,是因为端口标签中没有修改的端口导致selinux标签不认识

 semanage port -l  # 查看端口标签清单,找到httpd标签,发现自己修改的8989端口没有在标签中

 tail /var/log/message  # 查看报错信息

semanage port -a -t PORT_TYPE -p tcp 8989 可以看到修改的命令,此时将PORT_TYPE改成http_port_t 执行命令即可,a是添加、t是类型、p是协议

如果修改文件标签错误,导致访问不了服务,使用restorecon -Rv /var/www/html  # 如果目录中的标签不对,就执行下这条命令

chcon -t admin_home_t index.html #  index.html的路径是在/var/www/html,此时已经无法访问

ls -Zd /var/www/html  # 查看标签

restorecon -Rv /var/www/html # 重置标签

83、操作系统的安装

dd if=/root/rhel8.iso of=/dev/sdc bs=1M # 使用命令制作系统安装u盘,if是iso文件的目录,of是u盘的路径

在KVM虚拟化中安装操作系统

virt-manager  # 打开kvm虚拟机管理界面

使用kickstart自动安装操作系统

安装操作系统后都会生成一个kickstart的配置文件,通常copy这个配置文件来修改定义给新安装操作系统使用,文件的路径在用户家目录下,名为anaconda-ks.cfg

# Root password 定义密码是否是明文

--iscrypted 非明文 / --plaintext 明文

# Disk partitioning information 磁盘分区定义

autopart # 自动分区

PS:在kvm创建配置时候一定要定义好网桥

1、yum install pykickstart 

2、ksvalidator anaconda-ks.cfg  # 检查语法,但是无法检查逻辑错误如没有vda磁盘,但是配置中定义vda磁盘无法检测正确否

3、将 anaconda-ks.cfg 文件放到U盘或网络服务器

4、启动界面按tab,输入  inst.ks=http://192.168.1.10/ksconfig/anaconda-ks.cfg  # 这个inst.ks后面定义的就是anaconda-ks.cfg配置文件的路径

84、Ansible自动化运维

只要有ssh,就可以通过ansible进行配置管理、修改、配置应用、操作系统部署(补丁升级等,无法安装操作系统)、有安全审计界面、通过角色搭建复杂应用平台等

ansible是部署在控制节点,一台普通的linux服务器即可,部署好后就有一个自动化运维的引擎

引擎中有inventory清单(就是受控节点清单)也可以来自于数据库、modules模块(许多python小程序)超过2000个模块、api接口(提供服务或者拿去云服务的主机清单)、plugins

yum install ansible  # 安装

ansible可以管理所有的平台,如云、虚拟化、容器、windows、网络设备、聊天工具、监控工具等

PLAYBOOKS

PLAYBOOKS就是一个YUML格式的软件,定义了任务如何运行。一个playbooks中包含play可以是多个,一个play针对一组主机进行操作,多个play可以针对多组主机同时操作。play中包含了任务tasks,每个任务会调用一个模块做一件事(如一个任务是httpd、一个任务是firewalld)。任务是顺序执行的

以目标为导向,可以反复运行,目标达到不再操作,这个就是持续交付CD

ansibale的配置文件

/etc/ansible/ansible.cfg  # ansible找不到其他配置文件则读取这个配置文件,不常用

~/.ansible.cfg  # 当前用户家目录下的隐藏文件,如果当前工作目录中没有ansible.cfg,则读取此配置文件,取代etc下的,不常用

./ansible.cfg  # 如果执行ansible命令所在的工作目录中存在ansible.cfg文件,则使用它,最常用

PS:ansible只使用最高优先级的配置文件中的设置,其他配置如etc下的则被忽略

ansible命令运行的方式

ad-hoc  # 一次性的运行命令和bash命令一样效果,写法就是ansible 主机 -m 模块名,通常用来查询使用

Playbooks  # 运行playbook

Automation Framework  # 图形化中运行 Ansible Tower

Dry-run # 模拟运行命令,写法就是ansible web -C -m yum -a "name=httpd state=latest" ,参数中用大写C

GALAXY 社区 # 可以在这个网站上传写好的playbook,也可以下载别人上传的做修改为自己用

ansible指令

ansible-doc -l  # 列出所有模块,ansible --version能够看到模块的路径

 ansible-doc  yum  # 帮助,如何写运行任务

ansible概念和架构

Ansible 是DevOps语言,持续集成持续交付

Ansible架构中有两种计算机类型:受控节点和受管主机

Ansible软件安装在控制节点上,所有组件也在控制节点上被维护

受管主机列在主机清单(inventory)文本文件中,位于控制节点上,含有受管主机名称或ip列表

Ansible使用SSH与受管主机进行通信,playbook中引用的模块通过ssh复制到受控节点,然后使用playbook中指定的参数,按顺序执行,这就是Ansible的原理

以目标为导向的自动化运维工具,不看过程只管目标,用户也可以按需自行编写模块,通常使用Ansible默认模块即可

关于ansible的模块维护

ansible-doc 命令可以查看模块的维护者及当前的开发状态

模块文档中status段描述的开发阶段包括

stableinterface  # 模块关键字已稳定,更新不会修改关键字

preview   # 技术预览状态,可能不稳定,关键字可能修改

deprecated  # 该模块已被启用,将来的某个版本中将不再可用

removed  # 模块已从当前版本移除,存在的文档用于帮助迁移到新模块

模块文档中supported_by 段描述模块的维护者

core  # 被ansible核心开发团队维护,永远属于ansible

curated  # 被社区中的合作伙伴或公司维护,核心团队审核并测试更新

community  # 模块不被核心团队、合作伙伴或公司维护,被开源社区维护,可能会存在未知问题

Ansible用例

配置管理(Configuration Management)、应用部署(Application Deployment)、部署(Provisioning)、持续交付、安全和审计、编排

Ansible安装和命令

在控制节点上需要安装python2.7或者python3.5以上的版本,受控节点需要安装python2.6或3.5以上,rhel安装python软件包即可

yum install python  # rhel中直接安装

yum install ansible  # centos源中无ansible,需要添加后才能安装

yum list installed python  # 查看安装的版本

ansible --version  # 查看版本,可以看到config file(配置文件路径),ansible python module location(模块路径),executable location(命令的路径)

ansible-doc -l # 列出所有模块

ansible-doc nmcli # 查看模块的使用帮助,可以搜索EXAMPLE查看配置帮助,直接复制黏贴修改参数即可使用

配置ansible受管主机并运行临时命令

主机的默认清单路径 /etc/ansible/hosts  # 通常不会用默认,会在工作目录自建

主机定义可以是一个网络段,也可以是一个主机段

192.168.[4:7].[0:255]  # 就是192.168.4.0 ~ 192.168.7.255 段

server[01:20].example.com  # 就是server01.example.com  ~ server20.example.com  

列:简单的清单和配置文件

vim inventory  # 创建清单,名字不限自定义

[servers]  # 组名

servera   # 这个是主机名单名字

serverb

serverc

serverd

vim ansible.cfg  # 创建配置文件,定义清单的路径

[defaults]

inventory=./inventory  # 定义清单文件的路径、可以是目录(读取目录下所有的清单文件)

ansible all --list-hosts  # 可以看到自定义的主机清单

ansible servers --list-hosts # 查看指定组名的清单

ansible serverc --list-hosts # 查看指定主机是否在清单

ansible server* --list-hosts # 查看通配符名称的清单

编写ansible清单

PS:编写清单记不住,可以打开/etc/ansible/ansible.cfg,搜索相应的分组即可

【defaults】常规配置

【privilege_escalation】提权配置

【paramiko_connection】在老版本的红帽(6以下),ssh的版本较低,没有持续连接的特性,没执行一次模块ssh就会发起一次连接,效率低,使用这个组,这个组有持久连接的特性,对老版本ssh优化

【ssh_connection】老版本红帽中ssh调优使用,针对红帽6以下

【accelerate】老版本红帽中ssh调优使用,针对红帽6以下

[defaults]

inventory = /etc/ansible/hosts  # 清单文件路径

remote_user = root  #  ssh登录到受控节点的用户,如果不写这条配置,则以当前登录的用户登录
ask_pass = True  # ssh登录到受控节点否需要密码

[privilege_escalation]  # 定义了谁来运行palybook,是否需要提权
become=True  # 是否需要提权
become_method=sudo  # 如何提权
become_user=root  # 提权至那个账号
become_ask_pass=False  # 提权是否需要密码

PS:配置文件必须有上述两个分组及内容

临时命令ad-hoc实例

inventory目录下有hosta是主机清单文件

ansible servera -m ping

PS:如果用户不属于wheel组,配置文件中定义了提权不需要密码无效,必须放入wheel组后再 vi sudo,打开后找到wheel组的配置,将NOPASSWD这个注释去掉即可

关于ansible的模块

常用的模块command模块,能够在受控节点运行shell命令,不指定模块时候,默认使用command模块

ansible servera -m command -a "ip a s"

ansible servera -a "ip a s"

两条命令运行的结果是一样的,因为-a 就是command的参数,不指定模块指定参数,默认使用command模块

copy  # 拷贝模块

file  # 设置权限

lineinfile   # 往一个文件中写入内容

synchronize  # 就是rsync,同步两个目录使用

yum   #  安装软件使用

apt   #  安装apt软件包

dnf   # 管理软件包

gem  # 管理ruby

pip  #  用于python 安装模块  

firewalld  #  配置防火墙 

reboot  # 重启

service  # 启动或关闭服务

user  # 管理用户

get_url  # 判断网站能否访问或者用于下载

nmcli  #  配置ip地址

uri  # 访问网页

PS:大部分模块带有参数,-a选项传递参数到指定模块,一些模块可以无参数如ping,一些模块可以多参数,参数说明可以在模块文档中找到,使用ansoble-doc 模块名 即可查看

搭建基本的ansible环境和使用一次性命令执行任务

节点的基本配置

主控节点 servera的基本配置

1、yum  install ansible -y  # 主控节点安装ansible

2、useradd test  # 创建测试用户

3、su - test  # 切换到工作用户

4、mkdir  test  # 创建工作目录

5、cd test  # 进入工作目录

6、vim inventory  # 创建主机清单文件

[server]  # 组名

serverb.lab.example.com  # 添加主机名

7、vim ansible.cfg  # 创建配置文件

[defaults]

inventory=inventory  # 定义清单文件的路径

remote_user=test

[privilege_escalation]

become=True # 是否要提权

become_method=sudo  # 如何提权

become_user=root  # 提权成什么用户

become_ask_pass=False  # sudo不要密码

-----------提权配置打开/etc/ansible/ansible.cfg进行查找------------------------

vim /etc/ansible/ansible.cfg

查找privilege_escalation,直接拷贝即可

-------------------------------------------------------------------------------------------------

8、ssh-keygen  # 生成密钥对

9、ssh-copy-id test@serverb  # 将秘钥发到受控节点serverb

PS:这一步操作则是登录servera远程登录serverb则不需要密码

受控节点 serverb的基本配置

1、useradd test  # 创建测试用户

2、echo redhat |passwd --stdin test  # 给test用户设置密码

3、visudo  # 编辑sudo文件设置sudo不需要密码

-------------------搜索wheel-------------------------------

# %wheel  ALL=(ALL)  NOPASSWD:ALL 在这行下添加

test  ALL=(ALL)  NOPASSWD:ALL

-----------------------------------------------------------------

对主机清单中主机进行自动化安装

1、ansible all --list-hosts  # 在主控节点运行,显示主机列表则表示配置成功

2、ansible server --m command -a hostname # m是后面跟模块,默认command模块,a是参数,查询出主机清单

3、使用yum模块安装httpd软件包 # 不知道yum模块怎么使用,使用ansible-doc命令查看模块如何使用

-----------ansible-doc yum-----------------

 搜索EXAMPLES

能够看到模块后面参数如何使用

 --------------------------------------------------

4、ansible server --m yum -a "name=httpd state=latest"  # 向server组里面所有的主机安装httpd

5、ansible server --m command -a "yum list installed httpd"  # 确认安装

编写简单的ansible playbook和并执行

playbook开头以 --- 作为文档开始标记,并以 ... 作为文档结尾标记

playbook文档以yml或yaml作为后缀

ansible-playbook --syntax-check playbook.yml    # 使用命令验证playbook语法,如果执行后没有消息则表示语法正确

ansible-playbook -C playbook.yml  # 试运行(dry run 空运行),在内存中模拟跑一边playbook,并不会真的去执行

ansible-playbook -s playbook.yml  # 显示模块参数的简要说明

ansible-playbook playbook.yml运行时候可以跟参数

参数名

用途

-v

显示输出信息

-vv

显示输入输出信息

-vvv

显示连接信息

-vvvv

显示连接信息,模块调用详细信息

 

PS:playbook的格式中禁止使用tab进行缩进,通常以两个空格为缩进

PS:运行后的信息黄色表示做过更改,绿色表示未做更改

PS:playbook中是以key:value键值表示,在键后面冒号必须空格再跟值

PS:在运行 ansible-playbook playbook.yml 必须在工作目录中,如果在其他目录则会找不到自定义inventory(主机清单文件),回去搜索默认的inventory文件,就会发生报错

 

关于ymal(playbook)的语法

可以使用 # 开头作为注释,可存在于任何空行或非空行的末尾,如果非空行中使用(即行间注释),需在井号之前加一个空格,通常情况下不会使用行间注释。

也可以使用字符串,不要求放在引号里,如果需要,字符串可以用双引号或单引号括起

编写多行字符串有两种方式,一种方式是使用竖线(|)字符表示保留字符串中的换行字符

include_newlines: |

              Example Company

              123 Main Street

               Atlanta, GA 30303

另一种是使用大于号(>)字符来表示换行字符转换成空格,且行前的空白将被删除

include_newlines: >

              This is

              Example Company,

              123 Main Street,

               Atlanta, GA 30303.

 

YMAL (playbook)字典

YMAL中使用的key/value对也称为字典

在key/value对中,键与值通过由冒号和空格组成的分隔符隔开

字典通常以缩进的块格式表示

字典也可使用内嵌块格式表示,其中多个key/value对用花括号括起,并由逗号和空格隔开{name: svcrole, svcservice: httpd, svcport: 80}

 

YMAL (playbook)列表(即数组)

使用一个短划线加一个空格作为每个列表项的前缀

hosts:

     - servera

     - serverb

     - serverc

PS:不是所有的模块都支持数组

 

-------------------- 最简单的playbook ---------------------

使用playbook卸载httpd

vim playbook.yml   # 编辑创建文件

---

- name: first play  # playbook名称

  hosts: server  # 指向的主机

  tasks: # 这行下面开始写任务

    - name:first task  #  任务名

      yum:

          name:httpd

          state:absent  # 卸载,这项不写就是默认创建

-- 命令后直接跟playbook文件名即可运行如: ansible-playbook playbook.yml  --

 

----- 使用ansible安装apache,打开防火墙,然后使用copy模块将html文件拷贝到指定目录,使用service模块使apache模块开机自启动 -----

基本环境:plackbook-basic(工作目录已创建)在此目录下有 、ansible.cfg(配置文件已写好)、inventory(主机清单已写好)、files文件夹下有html文件

ansible.cfg  # 配置文件如下

[defaults]

inventory =  inventory # 清单文件路径

remote_user = devops  #  ssh登录到受控节点的用户,如果不写这条配置,则以当前登录的用户登录

[privilege_escalation]

become=True # 是否要提权

become_method=sudo  # 如何提权

become_user=root  # 提权成什么用户

become_ask_pass=False  # sudo不要密码

 

inventory(主机清单如下)

[web]  # web组

servera

 

开始编写playbook

vim playbook.yml

---

  - name: install and start httpd  # playbook名称

   hosts:all  # 所有主机

   tasks:

        - name:install httpd  # 任务名安装httpd

          yum:  # 使用yum模块

              name: httpd  # 需要安装的软件名

              state: present  # 这里参数表示执行安装

         - name: start and enable httpd  # 任务名启动httpd和设置开机自启

           service:  # 使用service模块

               name:  httpd  # 需要启动的软件名

               state: started  # 这个参数表示启动

               enable: yes  # 设置开机自启

         - name: copy index.html  # 任务名拷贝html文件

            copy:  # 使用拷贝模块

                src: files/index.html  # 需要拷贝的文件路径

                dest: /var/www/html/index.html    # 拷贝的目的地及需要定义的文件名

--------- ansible-playbook --syntax-check playbook.yml(验证语法) 、ansible-playbook -C playbook.yml(试运行)、ansible-playbook playbook.yml(执行安装)---------

 

注意事项:尽量避免在playbooks中使用command(可以执行命令),shell(可运行脚本)和raw(可运行脚本)模块,因为这几个模块不支持干运行就是 -C参数,最多用来做查询,不要用来做执行

 

-------------------- 一个playbook文件中有多个任务 ---------------------

要求:在servera中部署一个httpd,然后再主控机上进行验证,并开启防火墙配置

ansible.cfg 内容如下

[defaults]

inventory =  inventory # 清单文件路径

remote_user = devops  #  ssh登录到受控节点的用户,如果不写这条配置,则以当前登录的用户登录

[privilege_escalation]

become=False # 是否要提权

become_method=sudo  # 如何提权

become_user=root  # 提权成什么用户

become_ask_pass=False  # sudo不要密码

inventory(主机清单如下)

[web]

serverb

开始编写playbook

vim playbook.yml

---

  - name: Enable intranet service

   hosts:servera

   become:yes

        - name:latest version of httpd and firewalld installed  # 使用yum模块安装httpd和firewlld

          yum:  

              name:  # 这里使用了语法中的数组

                   - httpd

                   - firewalld 

              state: latest

         - name: test html page is installed  # 使用copy模块将content内容写入index.html中

           copy: 

               content:  "Welcome to the example.com intranet! "

               dest: /var/www/html/index.html

            

         - name: firewalld enable and running  # 开启firewalld服务并设置自启动

            service:

                name: firewalld

                enabled: true

                state: started 

          - name: firewalled permits http service # 设置防火墙放行80端口

            firewalld:  

                sercvice: httpd

                permanent: true

                state: started

                immediate: yes

           - name: httpd enabled and running  # 开启apache服务并自启动

              service:  

                 name: httpd

                 enabled: true

                  state: started

- name: Test intranet web server  # 测试web网页的任务

  hosts: localhost  # 本机

  become: no

  tasks:

      - name: connect to intranet web server  # 访问网页的任务

         uri:  # 这个模块用于测试网页能不能访问,如果报错表示网页无法访问

             url: http://servera  # 访问的地址

             return_content: yes  # 返回json格式的值

             status_code: 200 # 设定得到的结果,用来做校验,如果匹配上就表示访问成功

-------------------------------------------------------------------------------------

 

-------------------------------------------编写playbook使用变量和事实(facts)------------------------------------------

ansible变量的名称由字符串组成、必须以字母开头,并且只能含有字母、数字和下划线

Global 全局范围  # 主要在命令行或配置文件中,优先级最高

play 范围  # 在playbook中,优先级其次

h ost 主机范围   # 在inventory、facts或register的变量,在主机组合个别主机上设置的变量,优先级最低

PS:变量重复定义,以优先级最高的为主

 

playbook中如何定义变量

最简单的方式是将它放在playbook开头的vars块中,也可以在外部文件中定义playbook变量。此时不使用vars,使用vars_files指令,在YAML文件中

例:在playbook开头中定义变量

        - hostst all

          vars:

              user: joe

              home: /home/joe

 例:在外部文件中定义变量

         - hosts all

               vars_files:

                    - vars/users.yml

        文件中的格式

           user : joe

           home: /home/joe

         定义了变量后,管理员可在任务中使用这些变量,若要引用变量,可将变量名放在双花括号内

            vars: 

                user: joe

            tasks:

                 #  this line will read:creates the user joe

                 - name: Creates the user {{ user }}

                 user:

                        # this line will read creates the ueser named Joe

                        name: "{{ user }}"

                        PS:建议变量使用引号,这可以防止ansible将变量视为YMAL字典的开头

 

主机变量和组变量

主机变量(host variables)应用到特定的主机

组变量(group variables)应用到某一或某组主机组的所有主机

PS:主机变量优于组变量,但palybook中定义的变量的优先级比这两者更高

PS: 建议在与清单文件或目录相同的工作目录中,创建两个目录,group_vars 和 host_vars,分别包含用于组变量和主机变量定义文件,不要直接在一个或多个清单文件中定义主机变量和组变量

PS:为了定义servers组的组变量,需要创建名为group_vars/servers的YAML文件,使用与playbook相同的语法为变量赋值,注意文件名一定要和组名一样

PS:为了定义用于主机的主机变量,需要在host_vars中创建名称与主机匹配的文件,注意创建的文件名也要与主机相匹配

 

变量和数组

除了将与同一元素相关的一组配置数据(软件包列表,服务列表和用户列表等)分配到多个变量外,管理员也可以使用数组。好处是数组可读性更好

user1_first_name: Bob

user1_last_name: Jones

user1_home_dir: /users/bjones

user2_first_name: Anne

user2_last_name: Cook

user2_home_dir: /users/acook

users:

    bjones:

   first_name: Bob

   last_name: Jones

      home_dir: /users/bjones

 acook:

   first_name: Anne

   last_name: Cook

   home_dir: /users/acook

PS:引用的方法就是"{{ users.bjones.home_dir }}"

 

注册的变量

管理员可用register语句捕获命令的输出,输出保存在一个变量中,可用于调试用途或其他目的,例如输出命令的结果

-name: Install a package and prints the result

 hosts: all

 tasks:

     - name: Install the package

        yum:

            name: httpd

            state: installed

        register: install_result  # 输出结果全部注册到install_result这个变量中

     - name: debug install_result  # 调用debug模块

  debug: 

    var: install_result

 PS:注意注册变量register是和yum平级的,register部署yum中的选项,所以是平级的

-----------------实例练习:使用变量向servera中执行任务---------------------------

vim playbook.yml

 -name: Deploy and start Apache HTTPD service  # 这里设置变量

  hosts: wevserver

  vars:

      web_pkg: httpd

   firewall_pkg: firewalld

   wev_service: httpd

      python_pkg: python3-PyMySQL

   rule: http

  tasks:

  - name: Required packages are installed and up to date  # 这里引用变量

     yum:

    name:

      - "{{ web_pkg }}"

      - "{{ firewall_pkg }}"

      - "{{  python_pkg }}"

     state: latest

  - name: The {{ firewall_service }} service is started and enabled 

    service:

    name: "{{ firewall_service }}"

    enabled: true

    state: started

  

  - name: Web content is in place

    copy:

    content: "Example web content"

    dest: /var/www/html/index.html 

  

  - name: The firewall port for {{ rule }} is open

    firewalld:

    service: "{{ rule }}"

    permanent: true

    immediate: true

    state: enabled

- name: Verify the Apache service

  hosts: localhost

  become: false

  tasks:

  - name: Ensure the webserver is reachable

    uri:

    url: http://servera.lab.example.com

      status_code: 200

ansible-playbook playbook.yml  # 直接执行playbook.yml

-----------------------------------------------------------------------

 

-----------------实例练习:使用外部变量文件来定义向servera中执行任务--------------------------

vim  variable.yml  # 创建外部文件,文件中不需要缩进,全部顶头

web_pkg: httpd

firewall_pkg: firewalld

wev_service: httpd

python_pkg: python3-PyMySQL

rule: http

vim playbook.yml

 -name: Deploy and start Apache HTTPD service  # 这里设置变量

  hosts: wevserver

  vars_files:  # 这里如果是内部变量直接是vars换行写变量,对比上面例子

  - variable.yml   

  tasks:

  - name: Required packages are installed and up to date  # 这里引用变量

     yum:

    name:

      - "{{ web_pkg }}"

      - "{{ firewall_pkg }}"

      - "{{  python_pkg }}"

     state: latest

  - name: The {{ firewall_service }} service is started and enabled 

    service:

    name: "{{ firewall_service }}"

    enabled: true

    state: started

  

  - name: Web content is in place

    copy:

    content: "Example web content"

    dest: /var/www/html/index.html 

  

  - name: The firewall port for {{ rule }} is open

    firewalld:

    service: "{{ rule }}"

    permanent: true

    immediate: true

    state: enabled

- name: Verify the Apache service

  hosts: localhost

  become: false

  tasks:

  - name: Ensure the webserver is reachable

    uri:

    url: http://servera.lab.example.com

      status_code: 200

ansible-playbook --syntax-check  playbook.yml  # 直接执行playbook.yml

-----------------------------------------------------------------------------------

使用ansoble给文件加密  # 管理秘密

ansible-vault   是一个开源的加密函数,使用Python工具集,通过利用AES256的对称加密加以保护

默认情况下Ansible使用python-crypto软件包中的函数来加密和解密vault文件,如果有许多加密文件,会在启动时解密导致明显的延迟,可以安装python-cryptograpty软件包

1、ansible-vault vreate test.txt   # 命令给test.txt 文件启用加密

1.1、根据提示设置密码

2、ansible-vault view test.txt  # 使用命令查看加密文件内容

2.1、根据提示输入密码

3、ansible-vault edit test.txt   # 编辑文件

3.1、根据提示输入密码开始编辑

4、ansible-vault rekey test.txt  # 重新设置密码

4.1 根据提示输入当前密码

4.2 根据提示设置新密码

5、ansible-vault decrypt test.txt  # 给文件解密,关闭加密

5.1 根据提示输入密码

6、ansible-vault encrypt test.txt  # 对已有的文件进行加密

6.1 根据提示设置密码

如playbook.yml文件被加密,直接执行会提示解密失败

1、此时使用ansible-playbook playbook.yml --aks-vault-pass,此时会提示输入密码。

2、将秘钥 存入文件

vim pass.txt  # 放在家目录,写入密码,chmod 600给权限

ansible-playbook playbook.yml --vault-password-file=/home/student/pass.txt  # 执行playbook.yml时使用参数定义密码文件直接读取 

3、秘钥存入文件,可能被别人获取,使用随机生成的秘钥给文件加密

dd if=/dev/urandom of=/home/student/pass.txt bs=4k count=1  # 使用random模块生成随机的4096位对称秘钥写入文件

ansible-vault rekey variable.yml --new-vault-password-file=/home/student/pass.txt  # 给文件重新设置密码,并且密码来源是随机生成的秘钥文件,先输入当前密码后提示修改成功

4、ansible-vault view variable.yml --vault-password-file=/home/student/pass.txt # 因随机生成的4096位秘钥且是加密的,不可能手动输入,使用秘钥文件去解密查看文件内容

5、 ansible-playbook playbook.yml --vault-password-file=/home/student/pass.txt  # 使用秘钥文件运行playbook

管理事实

变量名前面带asnsble的就是事实变量。ansible事实是ansible从受管主机自动探查到的变量,事实由setup模块调取,其中包含的信息存储到可重复使用的变量中, 事实可以成为playbook的一部分,事实提供主机的一切信息“主机名称、内核版本、网络接口、IP地址、操作系统版本、各种环境变量、CPU数量、提供的或可用内存、可用磁盘空间。

使用setup查看事实,是以json格式存储在一个Python字典中

ansible webserver -m setup   # ansibl 运行playbook时会自动运行setup,通过命令查看变量,变量能直接使用,命令中的webserver就是主机名,事实使用ansible_facts.ipv4.address这样的格式来取值

ansible2.5之前,事实变量的前缀是ansible_,2.5之后是ansible_facts,2.5版本也支持老的取值方式即ansible_all_IPv4_address,新的取值是ansible_facts.ipv4.address

PS:受控节点不支持setup模块,可以在配置文件中添加gather_facts:no这项参数就不会去收集事实,这样可以加快playbook的运行速度

魔法变量 # 一些变量并非是setup模块采集的事实或配置信息,但是很有用,仍可以被ansible使用。成为magic cariables,也就是特殊的事实变量,和受控节点没关系

-hostvars:列出受管主机的非事实变量

-group_name:列出受管主机所属的所有组

-groups:列出所有incentory中的groups和hosts

-inventory_hostname:列出当前受管主机在inventory中定义的主机名,可能和事实变量不同

编写循环和条件判断任务

使用loop构建循环

循环使管理员不必编写相同的多个人物

ansible支持使用loop关键字在一组项目上迭代人物

--------------------样例---------------------

-name: Postfix is running

  service:

           name: postfix  # 启动postfix程序

           state:started

-name:Dovecot is running

  service:

            name: dovecot  # 启动docecot程序

            state: started

使用loop循环改写,在循环中启动程序

-name: Postfix and Dovecot are running

  service:

          name:"{{ item }}"  # 这里的item 就是loop,在循环时候会将循环内容放入这里

           state:started

  loop:

       - postfix  # 内容必须有 - ,否则报错

       - dovecot

loop列表可用变量表示

vars:

 mail_services:

     - postfix

  - dovecot

tasks:

 - name: Postfix and Dovecot are running

    service:

   name:"{{ item }}"

   state:started

 loop:"{{ mail_service}}"

hash列表:将诉诸作为参数传递时,数组可以时hash列表

-name: Users exist and in the correct groups

  user:

   name:"{{ item.name }}"

   state:present

   groups:"{{ item.groups }}"

  loop:

  - name:jane

     groups:sheel

      - name:joe

         group:root

在循环中使用register变量,可将register关键字用于输出循环的结果

-name: Loop Rsgister Test

  gather_facts:no

  hosts: localhost

  tasks:

   - name: Looping Echo Task

  shell: "echo This is my item: {{ item }}"  # 屏幕上打印的内容

  loop:

   - one

   - two

  register: echo_results  # 将执行结果放入echo_results变量中

 - name: Show echo_results variable

    debug:

   var: echo_results  # 这里使用debug var输出

------------------------------------------

条件

ansible可以利用条件在符合特定条件是执行任务,管理员可用条件来区分不同的受管主机,并根据他们所符合的条件来分配功能角色。Playbook变量、注册的变量和ansible事实都可以通过条件来进行测试。可以使用字符串比较、数学运算和布尔运算等各种运算符。不如定义了一个min_memory的值,并将他鱼受管主机上的可用内存进行比较然后判断是否执行任务。

例如某体程序失败,则需要跳过批处理、确认受管主机网络配置并决定是否要发送的模板文件、评估CPU数量来确定如何调节某一web服务器、检查服务的变化来验证文件的MD5等。

------------------样例--------------------

最简单的条件判断是布尔变量是true或false

- name: Simple Boolean Task Demo

   hosts: all

   vars:

  run_my_tasks: true  # 定义变量是true

  tasks:

  - name: httpd package is installed

     yum:

    name: httpd

    when: run_my_task  # 如果是ture就安装httpd

判断my_service 变量是否赋值,如果没有赋值,此任务将被跳过而不报错

- name: Test varoable is Defined Demo

   hosts: all

   vars:

  my_service: httpd

  tasks:

  - name: "{{ my_service }} package is installed"

     yum:

    name: "{{ my_service}}"

    when: my_service is defined  # 这个条件意思就是被定义值才能安装

运算符

operation

example

等于

ansible_machine == “x86_64”

等于

mac_memory == 512

小于

min_memory < 128

大于

min_memory > 256

小于等于

min_memory <= 256

大于等于

min_memory >= 512

不等于

min_memory != 512

是定义

min_memory is defined

是不定义

min_memory is not defined

treu or fasle(如果ture做什么,如果false做什么)

memory_available

非bool

not memory_available

包含数组变量

ansible_distribution in supported_distros

PS:用于测试条件中相等的 == 运算符不可与变量赋值的 = 运算符混淆

PS:when表达式不属于模块,必须放在模块外部

多条件判断

一个when语句可用于评估多个值,为此,可以使用and和or关键字组合条件或使用括号分组条件

PS:loop、when后面变量都不加{{}} 和“”

PS:在组合使用when和loop时,when语句将对每一项目进行处理

--------------------样例-----------------------

- name: install mariadb-server if enpugh space on root

   yum:

        name: mariadb-server

    state:latest

   loop:"{{ ansible_mounts }}"  # 这里每次循环都会执行下面的when进行判断是否满足条件

   when: item.mount == "/" and item.size_available > 300000000  #当根目录大于300M时才安装mariadb

--------------------------------------------------

组合使用条件和已注册变量的实例

----------------------样例------------------------

- name: Restart HTTPD if Postfix is Running

   hosts: all

   tasks:

  - name: Get Postfix server status

     command: /usr/bin/systemctl is-active postfix   # 查看服务是否在运行

     ignore_errors: yes  # 如果不运行就会报错,yes就代表有报错,如果不运行就不退出

     register: result  # 将command命令注册到result变量中

  - name: Restart Apache HTTPD based on Postfix status

     services:

    name: httpd  

    state: restarted # 重启httpd服务

     when: result.rc == 0  # 重启的条件就是true

-----------------综合练习:使用条件判断对不同主机安装服务---------------

工作目录是control-flow

cat inventory  # 查看清单文件

[databases]

servera.lab.example.com

[httpd]

serverb.lab.example.com

cat ansible.cfg  # 查看配置文件

[defaults]

inventory=inventory

remote_user=devops

[privilege_escalation]

become=True

become_method=sudo # 提权

become_user=root # 提权成root

become_ask_pass=False

vim playbook.yml

- name: Mariadb server is running  # 这里定义变量mariadb_packages
  hosts: all # 这里定义哪一个主机组执行,主机组定义在清单中,all表示所有主机组
  vars:
      mariadb_packages  # 这里变量定义要做什么,安装mariadb数据库,启动数据库,安装httpd服务
        - mariadb-server
        - python3-PyMySQL
    httpd_packages
        - httpd
    tasks:
       -  name: Mariadb packages are installed # 这里定义循环
           yum:
               name:"{{ item }}"
               state: preesent
          loop: "{{ mariadb_packages }}"
          when: inventory_hostname in groups.database # 条件定义只对database组
      
      - name: Start Mariadb service  # 这里做启动服务操作
         service:
         name: mariadb
         state: started
         enable: true
     when: inventory_hostname in groups.database
      
    - name: install httpd
       yum:
          name:"{{ item }}"
          state:present
       loop: "{{ httpd_packages }}"
       when: inventory_hostname in groups.httpd # 条件定义只对database组

-------------------------------------------------------------------------------------------------

Handler任务

Ansible模块设计为idempotent模式。表示正确编写的playbook中,playbook及其任务可以运行多次而不会改变受管主机,除非需要进行更改使受管主机进入所需的状态。有时在任务更改系统时可能需要运行进一步的任务,例如更改服务配置文件时要求重新加载该服务以使更改的配置生效。handler程序响应由其他任务触发通知的任务,每一处程序具有全局唯一的名称,在playbook中任务模块的末尾出发。如果没有任务通知handler程序它就不会运行,如果有一个或多个任务通知则会的paly中所有其他任务完成后仅运行一次。通常handler被用于重新引导主机和重新启动服务

如果两个handler程序中有同一个处理程序名称,则仅运行一个

include内定义的处理程序无法获得通知

-----------------handler任务样例---------------  
tasks:
  - name: copy demo.example.conf configuration template  # 将本地模板文件拷贝到目标节点下
    template:
      src: /var/lib/templates/demo.example.conf.template  # 本地模板文件
      dest: /etc/httpd/conf.d/demo.example.conf  # 目标节点目录
    notify: # 如果执行成功会激活notify
      - restart apache # 重启apache

handlers:
  - name: restart apache # 这里任务名字,名字要和notify下面的一样
    service:
      name:httpd
      state:restartd

-----------------------------------------------------

-----------------handler一个任务多notify样例---------------  
tasks:
  - name: copy demo.example.conf configuration template  # 将本地模板文件拷贝到目标节点下
    template:
      src: /var/lib/templates/demo.example.conf.template  # 本地模板文件
      dest: /etc/httpd/conf.d/demo.example.conf  # 目标节点目录
    notify: # 如果执行成功会激活notify
      - restart apache # 重启apache
      - restart mysql
      

handlers:
  - name: restart apache # 这里任务名字要和notify下面的一样
    service:
      name:httpd
      state:restartd
      
  - name: restart mysql # 这里任务名字要和notify下面的一样
    service:
      name:mariadb
      state:restartd

--------------------------------------------------------

------------handler实例-----------------
vim configure_db.yml

- name: Installing MariaDB server # 安装mariadb
  hosts: databases
  vars:
    db_packages: # 安装服务
      - mariadb-server
      - python3-PyMySQL
    db_service: mariadb # 启动服务
    resoursces_url: http://materoals.example.com/labs/control-handlers # 这个变量是下载配置文件地址
    config_file_url: "{{ resoursces_url }}/my.cnf.standard"  # 这个变量是配置文件地址
    config_file_dst: /etc/my.cnf  # 这个变量是被拷贝的目录
  tasks:
    - name: install packages
      yum:
        name:"{{ db_packages }}"
        state: latest
    
    - name: start and enable service
      service:
        name: "{{ db_service }}"
        state: started
        enable: true
    
    - name: copy configuration files  # copy模块无法使用链接,这里使用get_url
      get_url:
        src: "{{ config_file_url }}"
        dest: "{{ config_file_dst }}"
        force: true # 这个参数是强制覆盖
      notify:
        - restart mariadb

  handlers:
    - name: restart mariadb
      service:
        name: "{{ db_service }}"
        state: restarted
        
ansible-playbook -C configure_db.yml # 大C参数是测试运行
-------------ansible-playbook configure_db.yml 这里最终运行------------

处理任务错误

默认情况下,如果某一任务失败,play则停止执行

使用ignore_errors: yes 参数可以跳过失败任务

- name: Latest version of notpakg is installed
  yum:
    name: notapkg
    state: latest
  ignore_errors: yes

强制处理程序

正常情况下激活handlers的程序报错,则handler则不会执行,但是使用fotce_handlers参数,则不管有没有报错都会执行handler

- hosts: all
  force_handlers: yes # 这个参数加后不管handler激活程序有没有报错,都会执行handlers
  tasks:
    - name: start and enable service
      service:
        name: "{{ db_service }}"
        state: started
        enable: true
      notify:
        - restart mariadb

  handlers:
    - name: restart mariadb
      service:
        name: mariadb
        state: restarted

PS:直接去掉handlers将任务变成普通任务更简单

覆盖failed状态

shell、cmd这类模块没有办法告诉ansible任务有没有成功,只能从输出结果中使用关键字来判断

使用filed_when 参数用于任务

tasks:

      - name: Run user creation script

         shell: /usr/local/bin/create_users.sh

         register: command_result

         failed_when: "'Passwiord missing' in command_result.stuout"  # 这里如果结果中出现Passowrd missing关键字则认为任务失败

覆盖changed状态

如果管理员希望在每次运行playbook时重新启动某一服务,可以将changed_when关键字添加到相应任务中,

tasks:
  - shell:  # 使用shell模块
      cmd: /usr/local/bin/upgrade-database  # cmd中打开一个脚本
    register: command_result  # 将结果注册到这个变量中
    changed_when: "'Success' in command_result.stdout"  # 如果command_result.stdout输出信息中有Sucess
    notify:  # 通知restart—_database
      - restart_database

handlers:  # 这里做重启任务
  - name: restart_database
    service:
      name: mariadb
      state:restarted

blocks和错误处理

-block 定义要运行的主要任务

- rescue 定义将在block子句中定义的任务失败时运行的任务

-always定义始终都独立运行的任务,不论block和rescue子句中定义的任务是成功还是失败

---------------案例-----------------

tasks:
  - block:
      - name: upgrade the database
        shell:  # 使用shell模块
          cmd: /usr/local/bin/upgrade-database  # cmd中打开一个脚本
    rescue: # 如果 block执行任务失败则执行这条任务
      - name: revert the database upgrade
        shell:
          cmd: /usr/local/lib/revert-database
    always: # 无论上面block任务是成功还是失败,都会执行always这里的任务
      - name: always restart the database
        service:
          name: mariadb
          state: restarted

-------------------------------------------------------

使用ansible在主机上修改和拷贝文件

ansible常用模块

blockinfile : 在文档中填入文字

copy : 将控制节点的文件拷贝到受控节点

fatch : 抓取web页面的文件,抓取到控制节点上

file : 创建文件或目录、删除文件或目录、修改文件权限等

lineinfile :  在文档中替换内容

stat : 查看文件的状态信息,用于条件判断

synchronize : 目录同步

sefcontext: 修改selinux的标签模块

file模块示例   # 创建文件,修改标签,移除文件

- name : Touch a file and set permissions

   file:

      path: /path/to/file  # 制定路径和文件名,如创建则在这个路径下创建文件,如有则可以修改属性

  owner: user1   # 定义所属用户,修改标签不需要此参数

  group: group1  #  定义所属组,修改标签不需要此参数

  mode: 0604  # 定义权限,修改标签不需要此参数

  state: touch  # 创建,修改标签不需要此参数

  state: absent  # 移除文件

      setype: samba_share_t  # 修改文件的selinux标签

 

sefcontest模块示例,修改selinux标签

-name: SELinux type is persistently set to asmba_share_t

  sefcontext:

  target: /path/to/samba_file

  setype: samba_share_t

  state: present

copy模块示例,只能拷贝单个文件,不支持目录

- name: Copy a file to managed hosts

  copy:

  src :  file  # 文件名

  dest: /path/to/file  # 受控节点的路径

  froce: yes  #这个参数加了后就会强制覆盖文件

lineinfile模块示例

- name : Add a line of text to a file

   lineinfile:

  path: /path/to/file  # 需要增加内容的文件,文件不存在则不添加

  line: 'ADD this line to the file'  # 增加的内容

  state: present

blockinfile 模块示例

- name: Add additional lines to a file

   blockinfile:

  path: /path/to/file  # 文件的路径

  block:   # block行中可以写很多行内容

    First line in the additional block of text

    Second line in the additional block of text

  state: present

stat模块示例

- name: Verify the checksum of a file

   stat:

  path: /path/to/file  # 文件路径

  checksum_algorithm: md5  # 检测MD5

   register: result  # 输出信息注册到result变量中

- debug

  msg: "The checksum of the file is {{ result.stat.checksum }}"  # 显示输出信息

synchronize模块,类似于rsync命令,可以拷贝整个目录,会比对hash,如果相同则不拷贝,不同则覆盖

- name: synchronize local file to remote file

   synchronize:

  src: file

  dest: /path/to/file

-----------------模块实例---------------------

file-manage目录下,inventory(清单)中有servera和serverb主机,ansible.cfg(配置文件)中清单路径指向本目录中inventory

要求:使用root用户登陆要受控节点,然后将受控节点的/var/log/serure文件拷贝到本地serure-backups 目录中,并且创建目录结构

vim secure_log_backups.yml

---

- name: fetch secure log

   hosts: all

   remote_user: root  # 用什么用户登陆到受控节点

   tasks:

  - name: fetch log

     fetch:

    src: /var/log/serure   # 文件来自于

    dest: serure-backups  # 目标本地的文件夹

    flat: no  # 参数no就是创建目录结构

创建copy_file.yml,以root用户身份将本机文件拷贝到所有受控节点,所属用户是devops,所属组是decops,文件权限是u+rw,g-wx,o-rwx,并且修改selinux标签为samba_share_t

vim copy_file.yml

---

- name: copy files

   hosts:all

   remote_user: root

   tasks:

  - name: copy files

     copy:

    src:  files/user.txt  # 文件名

    dest: /home/devops/user.txt   # 受控节点的路径

    owner:devops

    group: devops

    mode: 0640  # 数字表示权限第一位必须是0,0就是特殊权限

    setype: samba_share_t

创建selinux_defaults.yml,在当前的工作目录下配置playbook使用file模块保证selinux的标签是samba_share_t

vim selinux_defaults.yml

---

- name: Using the file module to ensure SELinux file context

   hosts: all

   remote_user: root

   tasks:

  - name: SELinux file context is set to defaults

    file:

   path: /home/devops/users.txt  # 文件名

       seuser: _default   #参数指定修改成默认

   serole: _ default

   setype: _default

   selevel: _ default

创建一个add_line.yml,在user.txt文件中增加一行内容,自定义

vim add_line.yml

---

- name: Add line

   hosts: all

   remote_user: devops # 可以直接将这个参数放到配置文件中

   tasks:

  - name : Add a single line of text to a file

     lineinfile:

    path: /home/devops/user.txt

    line: 自定义内容  # 这里写的就是要加入的内容

创建一个add_block.yml,在user.txt文件中增加一段内容,自定义

vim add_line.yml

---

- name: Add line

   hosts: all

   remote_user: devops # 可以直接将这个参数放到配置文件中

   tasks:

  - name : Add a single line of text to a file

     lineinfile:

    path: /home/devops/user.txt

    block:

      自定义内容  # 这里写的就是要加入的内容

    state: present

创建一个remove_file.yml,删除users.txt

vim remove_file.yml

---

- name: use the file module to remove a file

   hosts: all

   remote_user: devops # 可以直接将这个参数放到配置文件中

   tasks:

  - name : remove a file

     file:

    path: /home/devops/users.txt  # 受控节点的文件

    state: absnet  # 这个参数就是删除

----------------------------------------------------------------------------------------


jinja2模板  # 了解内容

ansible使用jinja2模板系统来修改文件,然后将文件分发到受管主机。也使用jinja2在playbook中引用变量。允许模板中使用jinja2循环条件,但playbook中不允许使用这两者。

jinja2模板由多个元素组成:数据、变量和表达式

模板中使用的变量可以在playbook的vars部分中指定

可将受管主机的facts用作模板中的变量

使用ansible system_hostname -i inventory_file -m setup 命令来获取与受管主机相关的facts

jinja2模板文件的后缀是.j2

在playbook中使用jinja2模板,可以通过template模块部署到受管主机上

----------------template模块使用jinja2模板------------------

tasks:

  - name: template render

     template:

    src: /tmp/j2-template.j2

    dest: /tmp/dest-config-file.txt

------------------------------------------------------------------------

jinja2使用for 语句来提供循环功能,loop.index变量扩展之循环当前所处的索引号,它在循环第一次执行时值为1,每一次迭代递增1

{# for statement #}  # 注释

{% for myuser in user if not myuser == "root" %}  # 表达式,如果myuser不是root,myuser变量属于user组里

User number {{loop.index}} - {{ myuser }}   # 执行循环

{%  endfor %}

变量过滤器

jinja2提供过滤器,更改模板表达式的输出格式 (例如,输出到JSON)。有适用于YAML或JSON等语言的过滤器

to_json过滤器使用JSON格式化表达式输出,to_yaml过滤器则将YAML用作格式化语法

{{ output | to_json}}

{{ output | ti_yaml}}

也有其他过滤器,如to_nice_json和to_nice_yaml过滤器,他们将表达式输出格式化为JSON或YAML等人类可读格式

{{ output | to_nice_json}}

{{ output | to_nice_yaml}}

from_json和from)yaml过滤器要求JSON或YAML格式的字符串,并对它进行解析

{{ output | from_json}}

{{ output | from_yaml}}

在Ansible playbook中与when子句一同使用的表达式是jinja2表达式。用于测试返回值的内置Ansible过滤器包括failed、changed、succeeded和skipped

tasks:

...output omitted...

  - debug: msg="the execution was aborted"

     when: returnvalue | failed

----------------使用jinja2模板覆盖登陆后提示的信息,/etc/motd这个文件就是现实登陆后信息的-------------------

工作目录下,有files目录

cat ansible.cfg

[defaults]

inventory = inventory

ansible_managed = Ansible managed: modified on %Y-%m-%d %H:%M:%S

files目录下有inventory、motd.j2、motd.yml三个文件,通过mv把三个文件移动到工作目录下

cat inventory

[webservers]

servera.lab.example.com

[workstations]

workstation.lab.example.com

cat motd.j2  # 这个文件就是用来在登陆后界面显示的内容

This is the system {{  ansible_facts['fqdn'] }}  # fqdn是域名

Thsi is a {{ ansible_facts['distribution'] }} version {{ ansible_facts['distribution_version'] }} system.  # distribution指的就是红帽操作系统的版本

Only use this system with permission.  # 一句话

Please report issues to: {{system_owner }}. 

cat motd.yml

---

- name: configure SOE

   hosts: all

   remote_user: devops

   become: true

    vars:

  - system_owner: clyed@example.com

 tasks:

  - name: configure /etc/motd

     template:

    src: motd.j2

    dest: /etc/motd  # motd文件就是登陆后界面会显示的内容,在无界面的模式下

    owner: root

    group: root

    mode: 0644

PS:登陆前的提示文件是/etc/issue

---------------执行ansible.playbook motd.yml-----------------

管理动态inventory  # 如云平台和虚拟化架构 主机名和IP地址会经常变,无法写死,需要一个脚本来获得主机名或ip,动态构建清单,这个就叫动态清单

Ansible在 /etc/ansible/hosts文件中指定,通过 -i 参数指定

PS:动态清单必须是一个脚本,而且有可执行权限,如果不可执行则视为静态清单

PS:动态清单可以用任何语言编写,但必须以JSON格式返回

PS:查看动态清单  ./inventoryscript --list

Ansible 支持多个清单,对于有静态也有动态的,ansible.cfg配置中inventory参数的值是目录,这样目录中所有文件都识别为清单文件,动态就执行,静态就读取,最后生成一个总的清单文件

PS:如果存在多个清单文件,则按照字母顺序进行检查。如果一个文件的内容依赖于另一个文件的内容,则前者的文件吗务必要在字母顺序上排于后者的后面

----------------动态清单实例-----------------

cd projects-inventory

cat ansible.cfg

[defaults]

inventory=inventory

mkdir inventory

cd inventory

wget http://ip  # 这里练习给到脚本,直接下载

wget http://ip

------------ansible all --list-hosts---------------

配置并行 # ansible默认只能同时在5台主机上操作,需要同时操作更多的主机,可以在ansible.cfg中设置

forks = 20 # 数值根据需求写

PS:也可以在ansible-playbook或ansible命令后跟--forks 选项来更改值

serial 关键字主要用于滚动更新,可以临时降低某些任务并发数量,比如使用ansible更新100台主机后,需要重启,这时候重启任务可以用serial定义比如5,就是同时重启5台

PS:serial的值不允许超过forks,超过也无效

PS:serial也可以使用百分比的值来设置

 --------------serial实例----------------

cd projects-parallelism

cat ansible.cfg

[defaults]

inventory=inventory

remote_user=devops

forks=4

[privilege_escalation]

become=Ture

become_method=sudo

become_user=root

become_ask+pass=False

cat inventory

[webservers]

servera.lab.example.com

serverb.lab.example.com

serverc.lab.example.com

serverd.lab.example.com

vim playbook.yml

---

-name: Update web server

  hosts:webservers

  serial: 2  # 这里加上serial,限制了并发

  tasks:

  - name: Latest version of apache installed

     yum:  # 升级软件包

    name:httpd

    state:lates

     notify:  #重启

    - Restart apache

  handlers:  # 重启

  - name: Restart apache

    service:

    name:httpd

    enabled:yes

    state: restarted

vim remove_apache.yml

---

- hosts: webservers

   tasks:

  - service:  # 停止服务

    name: httpd

    enabled: no

    state: stooped

  - yum:  # 删除软件包

    name: httpd

    state: absent

使用time命令执行命令,可以查看运行了多少时间

time ansible-playbook playbook.yml

结果会输出系统调用时间和用户空闲时间

real 就是系统调用时间

user 库函数调用时间

sys 内核调用时间

-------------------------------------------------------

包含或导入文件 # 在playbook中可以引用playbook或者任务

从外部文件导入其他playbook或tasks来管理大型playbook,就是模块化

PS: import_playbook功能只能在playbook的顶层使用,不能在play中使用

PS:loop即循环不能与import_tasks一起使用

PS:对于大型项目,tasks导入最好定义成变量,定义变量不能用横杠,定义文件采用横杠

-------导入外部playbook和tasks并使用变量来定义(11-3视频50分钟)-------

cd  projects-file

cat ansible.cfg

[defaults]

inventory=inventory

remote_user=devops

[privilege_escalation]

become=True

become_method=sudo

become_user=root

brcome_ask_pass=False

cat inventory

servera.lab.example.com

cd plays  # 这个文件夹在projects-file目录下

cat test.yml

---

- name:Test web service

  hosts:localhost

  become: no  # 不提权

  vars:

  url: http://servera.lab.example.com

  tasks:

  - name: connect to internet web server  # 查看网页是否能访问

    uri:

    url:"{{ url }}"

    status_code: 200

cd  tasks  # 这个文件夹在projects-file目录下

cat environment.yml

---

  - name: Install the {{ package }} package

     yum:

  name: "{{ package }}"

  state:latest

   - name: Start the {{ service }} service

      service:

  name: "{{ service }}"

  enabled: true

  state:started

cat firewall.yml

---

   - name: Install the firewall

      yum:

  name: "{{ firewall_pkg }}"

  state: latest

    - name: Start  the firewall

   service:

  state: started

  name: "{{ firewall_svc }}"

  enabled : true

     - name: Open the port for {{ rule }}

    firewalld:

    service: "{{ item }}"

    immediate: true

    permanent: true

    state: enabled

  loop:"{{ rule }}"

  

cat placeholder.yml

---

   - name: Create placeholder file

  copy:

  content: "{{ ansible_facts['fqdn'] }} has been customized using Ansible. " # 内容

  dest: "{{ file }}"   # 将内容输出到文件中

vim playbook.yml  # 在projects-file创建

---

- name : configure webserver

   hosts: all

   tasks:

   - name:configure webserver

      include_tasks:  tasks/environment.yml  #这里就是引入外部文件,并且定义目录下的文件

   vars: # 这里定义变量的值

   package: httpd

   service: httpd

   firewall_pkg: firewalld

   firewall_svc: firewalld

   rule:

     - http

     - https

   file: /var/www/html/index.html  # 这里是一个网页文件 

   - name:configure webserver

      include_tasks:  tasks/firewall.yml

   vars:

   package: httpd

   service: httpd

   firewall_pkg: firewalld

   firewall_svc: firewalld

   rule:

     - http

     - https

   file: /var/www/html/index.html

   - name:configure webserver

      include_tasks:   tasks/placeholder.yml

   vars:

   package: httpd

   service: httpd

   firewall_pkg: firewalld

   firewall_svc: firewalld

   rule:

     - http

     - https

   file: /var/www/html/index.html

PS:include_tasks 一个name 下只能写一个,有多少个就得写几个name,如上例有三个  include_tasks所以要写三个name

 ------------------ansible-playbook playbook.yml-------------------

  

ansible 的角色

数据中心具有许多不同类型的主机,一些充当web服务器,另一些充当数据库服务器,一个ansible playbook中如果包含所有任务,随着时间推移将变得硕大而复杂,ansible角色让管理员可以将playbook组织为独立、较小的playbook和文件。可以从外部文件加载任务和处理程序和变量,也可以关联和引用静态的文件和模板。可以备重复利用。角色可以分组内容,和他人共享代码。编写角色可以定义系统类型的基本要素比如web服务器、数据库夫妻、git代码库或用途。

在社区中可以下载别人的角色使用

ansible-galaxy init test  # 生成角色的目录,test就是角色名

tree test # 查看角色目录

defaults  # 定义默认变量

files # 定义文件,运行playbook可以将这个目录下的文件拷贝到受控节点

handlers  这里的服务重启服务或计算机用的

meta # 定义源数据和角色之间的依赖关系

tasks # 这里文件定义了改角色在受管主机上调用那些模块

templates # 这里存放jinjia2模板,供template模块使用

tests # 测试playbook

vars # 这里自定义变量

PS:角色变量由目录结构中的vars/main.yml文件来定义,这些角色变量在角色YAML文件中引用:{{ VAR_NAME }}。这里的变量优先级高于默认变量。在vars/main.yml或defaults/main.yml中都可以定义变量,但不要重复定义。需要覆盖变量时,应使用默认变量

PS: 在角色中需要将文件拷贝到受控节点,不需要指定本地路径,直接是copy src:index.html,自动会到相关的目录中查找

PS: 控制执行顺序,pre_tasks在角色之前执行,post_tasks任务在所有角色完成后执行

色可以保存在由ansible配置文件中roles_path变量引用的目录中

-------------------------------创建角色---------------------------

cd role-create # 工作目录

cat inventory

[webservers]

servera.lab.example.com

cat ansible.cfg

[defaults]

inventory=inventory

remote_user=devops

[privilege_escalation]

become=True

become_method=sudo

become_user=root

become_ask_pass=False

cat vhost.conf.j2 # 是一个虚拟网站的配置文件

mkdir roles # 创建角色目录

ansible-galaxy init myvhost # 创建角色

mv vhost.conf.j2 roles/myvhost/templates/

cd roles/myvhost/tasks/

vim main.yml

- name: Ensure httpd is installed  # 这个任务确保apache被安装

   yum:

  name:httpd

  state:latest

- name: Ensure httpd is started and enabled  # 确保apache服务启动

   service:

  name: httpd

  state: started

  enabledL true

- name: vhost file is installed

   template:

  src: vhost.conf.j2

  dest: /etc/httpd/conf.d/vhost.conf

  owner: root

  group: root

  mode: 0644

   notify:

  - restart httpd  # 这里有重启任务,需要在handlers中写配置

cd .. # 返回上级菜单

cd handlers/  # 进入handlers目录

vim main.yml

---

- name: restart httpd

   service:

  name:httpd

  state: restarted

cd ..

cd files

mkdir html

cd html

echo 'simple index' > index.html # 内容写到文件中

cd role-create # 返回到角色目录下

vim playbook.yml

---

- name : install and configure website

   hosts: all

   roles:

  - myvhost  # 使用的角色

   tasks:

   - name: copy index.html

  copy:

    src: roles/myvhost/files/html/

    dest: "/var/www/vhosts/{{ ansible_hostname }} # 目标放到节点目录

ansible-playbook --syntax-check playbook.yml  #测试有无报错

ansible-playbook playbook.yml

PS:进入受控主机,curl http://servera 查看虚拟站点是否能显示

---------------------------------------------------------------------------

Ansible Galaxy[https://galaxy.ansible.com]是一个Ansible角色公共资源库,由许多Ansible管理员和用户编写,是一个包含无数Ansible角色的档案库,具有可搜索的数据库,可以下载角色使用,有丰富的文档和视频

############必考题############

本地有一个角色文件是tar包,要安装到roles目录中,角色的名字叫myrole

ansible-galaxy install -r roles/requirements.yml > -p roles

------------------------------部署一个来自于ansible-galaxy的角色-----------------------

cd role-galaxy

cat ansible.cfg

[defaults]

inventory=./inventory

remote_user=devops

roles_path=./roles  # 这行如果注释掉的,可以使用ansible-galaxy list -p roles,去指定的角色目录找,也可以去掉注释后直接运行ansible-galaxy list。

[pricilege_escalation]

become=True

become_method=sudo

become_user=root

become_ask_pass=False

cat inventory

workstation.lab.example.com

[devservers]

servera.lab.example.com

cd roles  # 这个目录是空的,需要下载觉得装到和目录中

cd role-galaxy

vim requirements.yml

-src:

  name: git@workstation.lab.example.com:student/bash_env

  scm: git

  version: master

  name: student.bash_env

ansible-galaxy install -r requirements.yml -p roles/

cd roles

tree .

vim playbook.yml

---

- name: use student.bash_env role playbook

   hosts: deveservers

   vars:

  default_prompt: ' [u on h in W dir]$ '  # 定义了变量,覆盖默认变量

   pre_tasks:

   - name: Ensure test user does not exist  # 这里查看是否有这个用户,用户存在强制移除这个用户和家目录

  user:

    name: student2

    state: absnet

    force: yes

    remove: yes

  roles: # 调用的角色

  -student.bash_env  # 这里是角色名

  post_tasks:

  - name: Create the test user  # 创建用户,设置密码

  user:

  name: student2

  state: present

  password: " { 'redhat' | password_hash( 'sha512', 'mysecretsalt' ) }}"

---------------------------------------------------------------------

系统角色

RHEL7.4开始有一个软件包rhel-system-roles,包含了大量的Ansible角色,用于系统的事物

rhel-system-roles.kdump  # 做kermel dump配置的

rhel-system-roles.network # 配置网络的

rhel-system-roles.selinux # 配合selinux

rhel-system-roles.timesync # 配置ntp服务器

rhel-system-roles.postfix # 配置邮件服务器

rhel-system-roles.firewall # 配置防火墙

rhel-system-roles.tuned # 配置系统调优

sudo yum install rhel-system-roles

cd  /usr/share/ansible/  # 默认安装目录

cd roles # 这里看到所有的角色目录

cd /usr/share/dec/rhel-system-roles  # 使用文档的目录

cd timesync # 如果要查看如何配置ntp,进入这个目录

vim  example-timesync-playbook.yml  # 打开这个文档里面就是如何使用

----------------------系统角色实例---------------------

cd role-system

cat ansible.cfg

[defaults]

inventory=inventory

remote_user=devops

roles_path=./roles:/usr/share/ansible/roles:/etc/ansible/roles

[pricilege_escalation]

become=True

become_method=sudo

become_user=root

become_sak_pass=False

cat inventory

workstation.lab.example.com

[na_datacenter]

servera.lab.example.com

[europe_datacenter]

serverb.lab.example.com

[database_servers]

servera.lab.example.com

serverb.lab.example.com

cd roles

cat requirements.yml # 这个是git角色

cd role-system

vim confiuger_time.yml

---

- name: Time Synchronization

   hosts: database_servers

   roles:

  -  rhel-system-roles.timesync  # 使用的角色

   post_tasks:

  - name: set timezone

     timezone:

       name: "{{ host_timezone }}"

     notify: restart crond

   handlers:

  - name: restart crond

     service:

    name: crod

    state:  restarted

mkdir -p group_vars/all  # 指定目录下创建一个组变量文件

vim group_vars/all/timesync.yml # 所有组全部使用这个变量

timesync_ntp_provider:chrony

timesunc_ntp_servers:

  - hostname: classroom.example.com  # 时间服务器的地址

    iburst: yes

cd group_vars/

mkdir europe_datacenter

mkdir na_datacenter

cd enrope_datacenter

vim europe_datacenter/timezone.yml

host_timezone: Europe/Helsinki  # 定义欧洲的时间

vim nam_datacenter/timezone.yml

host_timezone: America/Chicago  # 定义变量名,芝加哥时间

 -----------------------------------------------------------------------------------

对playbook故障排除

PS:写playbook时候要多写注释,不要使用tab来空格

ansible 默认日志不记录到文件,只在运行的时候在屏幕上输出

ok=number # 就是执行成功几个任务

changed=0 # 对受管主机修改的数量

unreachable=0 # 未连接上的受管主机数,0就是全部连接上

failed=0 # 失败数,0就是全部成功

可以通过ansible.cfg的default部分中log_path参数进行配置,或通过$ANSIBLE_LOG+PATH环境变量来配置

vim ansible.cfg

[defaults]

inventory=inventory

log_path=./ansible.log

remote_user=devops  # 登陆受控节点使用的账户

debug模块:msg是显示一句话,var是显示变量的信息

如果playbook中有大量的任务,可以使用ansible-playbook命令中的--step或--start-at-task

--step:每执行一个任务会需要你手动确认

--start-at-task:  从指定任务开始执行

ansible-playbook 中参数v

-v : 显示输出信息

-vv: 显示输入输出信息

-vvv: 显示输入输出信息包括连接的信息

-vvvv: 包含了模块的调试信息

ansible-playbook --check # 其中check参数会将所有模块模拟运行一次,shell和cmd模块无法模拟运行

ansible-playbook --check --diff playbook.yml  # --diff参数可以查看模板中的变量产生了什么变化

tasks:

    - name: tasks always in check mode

      shell: uname -a

      check_mode: yes  # 这个参数就是允许检查,如果是no就是不允许检查

uri模块提供了一种方式,可以检查RESTful API是否返回需要的内容

tasks:

    - uri:

  url:http://www.baidu.com

  return_content: yes

   reguster: apiresponse

    - fail:  # 这个模块就是当条件为false时输出msg信息

        msg: 'version was not provided'

       when: "'version' not in apiresponese.content "  # 这里version在apirespinese.content中没有,就是报错了,会打印msg信息

stat模块可以检查不直接由Ansible管理的文件和目录是否存在

tasks:

  - name: Check if /var/run/app.lock exists  # 程序运行时候检查文件

     stat:

          path: /var/run/app.lock # 检查的路径和文件

     register: lock

  - name: Fail if the application is running

     fail:

     when: not lock.stat.exists # 当文件不存在程序不运行

assert模块是fail模块的替代,assert模块支持that选项,判断一组条件,如果任何一项不满足,则task失败.可以使用sucess_msg和fail_msg选项来自定义输出内容

tasks:

  - name: Check if /var/run/app.lock exists  # 程序运行时候检查文件

     stat:

          path: /var/run/app.lock # 检查的路径和文件

     register: lock

  - name: Fail if the application is running

     assert:

    that:

      - not lock.stat.exists # 这里是条件判断,可以加很多个条件判断

自动化运维任务 # 如果遗忘模块名使用ansible-doc -l |grep yum

-----------------------------练习一、管理软件的订阅-----------------------------

所有主机上都需要安装

原文地址:https://www.cnblogs.com/shizhengquan/p/11789371.html