查看物理CPU的个数

1
cat /proc/cpuinfo | grep "physical id" | sort | uniq | wc -l

查看物理CPU内核的个数

1
cat /proc/cpuinfo | grep "cpu cores" | uniq

查看所有逻辑CPU的个数

1
cat /proc/cpuinfo | grep "processor" | wc -l

查看每个物理CPU中逻辑CPU的个数

1
cat /proc/cpuinfo | grep 'siblings' | uniq

查询CPU是否启用超线程

1
cat /proc/cpuinfo | grep -e "cpu cores" -e "siblings" | sort | uniq

如果cpu cores数量是siblings数量一半,说明启动了超线程。
如果cpu cores数量和siblings数量一致,则没有启用超线程。

查看CPU的主频

1
cat /proc/cpuinfo |grep MHz|uniq 

查看CPU信息(型号)

1
cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c

查看内存信息

1
cat /proc/meminfo

查看机器型号

1
dmidecode | grep "Product Name"  

CPU运行位数

1
getconf LONG_BIT

线程组

微信截图_20210106142353.png

线程组参数详解:

  • 线程数:虚拟用户数。一个虚拟用户占用一个进程或线程。设置多少虚拟用户数在这里也就是设置多少个线程数。
  • Ramp-Up Period(in seconds)准备时长:设置的虚拟用户数需要多长时间全部启动。如果线程数为10,准备时长为2,那么需要2秒钟启动10个线程,也就是每秒钟启动5个线程。
  • 循环次数:每个线程发送请求的次数。如果线程数为10,循环次数为100,那么每个线程发送100次请求。总请求数为10*100=1000 。如果勾选了“永远”,那么所有线程会一直发送请求,一到选择停止运行脚本。
  • Delay Thread creation until needed:直到需要时延迟线程的创建。
  • 调度器:设置线程组启动的开始时间和结束时间(配置调度器时,需要勾选循环次数为永远)
    持续时间(秒):测试持续时间,会覆盖结束时间
    启动延迟(秒):测试延迟启动时间,会覆盖启动时间

聚合报告参数详解

  • Label:每个 JMeter 的 element(例如 HTTP Request)都有一个 Name 属性,这里显示的就是 Name 属性的值
  • #Samples:请求数——表示这次测试中一共发出了多少个请求,如果模拟10个用户,每个用户迭代10次,那么这里显示100
  • Average:平均响应时间——默认情况下是单个 Request 的平均响应时间,当使用了 Transaction Controller 时,以Transaction 为单位显示平均响应时间
  • Median:中位数,也就是 50% 用户的响应时间
  • 90% Line:90% 用户的响应时间
  • Min:最小响应时间
  • Max:最大响应时间
  • Error%:错误率——错误请求数/请求总数
  • Throughput:吞吐量——默认情况下表示每秒完成的请求数(Request per Second),当使用了 Transaction Controller 时,也可以表示类似 LoadRunner 的 Transaction per Second 数
  • KB/Sec:每秒从服务器端接收到的数据量,相当于LoadRunner中的Throughput/Sec

参考:

JMeter性能测试,完整入门篇

算术运算符

运算符 描述 实例
+ 加 - 两个对象相加 a + b
- 减 - 得到负数,或是一个数减去另一个数 a - b
* 乘 - 两个数相乘,或是返回一个被重复若干次的字符串 a * b
/ 除 - x 除以 y a / b
% 取模 - 返回除法的余数 a % b
** 幂 - 返回x的y次幂 a ** b
// 取整除 - 向下取接近商的整数 >>> 9//2 4 >>> -9//2 -5

比较运算符

1
2
3
4
5
6
== :等于 
!= :不等于
> :大于
< :小于
>= :大于等于
<= :小于等于

赋值运算符

运算符 描述 实例
= 简单的赋值运算符 c = a + b 将 a + b 的运算结果赋值为 c
+= 加法赋值运算符 c += a 等效于 c = c + a
-= 减法赋值运算符 c -= a 等效于 c = c - a
*= 乘法赋值运算符 c *= a 等效于 c = c * a
/= 除法赋值运算符 c /= a 等效于 c = c / a
%= 取模赋值运算符 c %= a 等效于 c = c % a
**= 幂赋值运算符 c **= a 等效于 c = c ** a
//= 取整除赋值运算符 c //= a 等效于 c = c // a
1
2
3
4
5
6
# 海象运算符,可在表达式内部为变量赋值。Python3.8 新增。
:=

# 示例中,赋值表达式可以避免调用 len() 两次:
if (n := len(a)) > 10:
print(f"List is too long ({n} elements, expected <= 10)")

逻辑运算符

1
2
3
and
or
not

成员运算符

1
2
in:如果在指定的序列中找到值返回 True,否则返回 False
not in:如果在指定的序列中没有找到值返回 True,否则返回 False

身份运算符

1
2
isis 是判断两个标识符是不是引用自一个对象
is notis not 是判断两个标识符是不是引用自不同对象

is 与 == 区别:
is 用于判断两个变量引用对象是否为同一个, == 用于判断引用变量的值是否相等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
a = 20
b = 20

if ( a is b ):
print ("1 - a 和 b 有相同的标识")
else:
print ("1 - a 和 b 没有相同的标识")

if ( id(a) == id(b) ):
print ("2 - a 和 b 有相同的标识")
else:
print ("2 - a 和 b 没有相同的标识")

# 修改变量 b 的值
b = 30
if ( a is b ):
print ("3 - a 和 b 有相同的标识")
else:
print ("3 - a 和 b 没有相同的标识")

if ( a is not b ):
print ("4 - a 和 b 没有相同的标识")
else:
print ("4 - a 和 b 有相同的标识")

Python 中的变量不需要声明。每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建。

1
2
var1 = 1
var2 = 'a'

在 Python 中,所说的”类型”是变量所指的内存中对象的类型。变量可以通过赋值指向不同类型的对象。

可以使用 del 语句删除一些对象引用。

del语句的语法是:

1
del var1[,var2[,var3[....,varN]]]

可以通过使用del语句删除单个或多个对象:

1
2
del var
del var_a, var_b

变量赋值

等号(=)用来给变量赋值。

等号(=)运算符左边是一个变量名,等号(=)运算符右边是存储在变量中的值。

1
2
3
counter = 100           # 整型变量
miles = 1000.0 # 浮点型变量
name= "Hello, Python!" # 字符串

1,同时为多个变量赋值。例如:

创建一个整型对象,值为 1,从后向前赋值,三个变量被赋予相同的数值。

1
a = b = c = 1

2,为多个对象指定多个变量。例如:

两个整型对象 1 和 2 的分配给变量 a 和 b,字符串对象 “Python” 分配给变量 c。

1
a, b, c = 1, 2, "Python"

标准数据类型

Python3 中有六个标准的数据类型:

  • Number(数字)
  • String(字符串)
  • List(列表)
  • Tuple(元组)
  • Set(集合)
  • Dictionary(字典)

标准数据类型中:

不可变数据(3 个):Number(数字)、String(字符串)、Tuple(元组);
可变数据(3 个):List(列表)、Dictionary(字典)、Set(集合)。

string、list 和 tuple 都属于 sequence(序列)。

空值用 None 表示

type()和isinstance()函数

isinstance 和 type :

  • type():不会认为子类是一种父类类型。
  • isinstance():会认为子类是一种父类类型。

内置函数 type() 可以用来查询变量所指的对象类型。

1
2
3
>>> a,b,c,d=20,5.5,True,5+4j
>>> print(type(a), type(b), type(c), type(d))
<class 'int'> <class 'float'> <class 'bool'> <class 'complex'>

isinstance

1
2
3
>>> a=1234
>>> isinstance(a,int)
True

数字(Number)类型

Python3 中数字有四种类型:int(整数)、bool(布尔型)、float(浮点数)、complex(复数)。

  • int (整数), 可以为任意大小、包含负数,如 1, 只有一种整数类型 int,表示为长整型,没有 python2 中的 Long。
    整型有四种进制表示,分别为:二进制、八进制、十进制、十六进制,说明如下表所示:

    种类 描述 引导符
    二进制 由 0 和 1 组成 0b 或 0B
    八进制 由 0 到 7 组成 0o 或 0O
    十进制 默认情况
    十六进制 由 0 到 9、a 到 f、A 到 F 组成,不区分大小写 0x 或 0X
  • bool (布尔), 如 True。

  • float (浮点数), 由整数部分和小数部分组成,如 1.23、3E-2

  • complex (复数), 由实数部分和虚数部分组成,如 1 + 2j、 1.1 + 2.2j

注意:混合计算时,Python 会把整型转换成为浮点数。

复数由实数部分和虚数部分构成,可以用a + bj,或者 complex(a,b) 表示, 复数的实部a和虚部b都是浮点型

String(字符串)

字符串用单引号 ‘ 或双引号 “ 括起来,同时使用反斜杠 \ 转义特殊字符。Python 没有单独的字符类型,一个字符就是长度为1的字符串。Python 字符串不能被改变。向一个索引位置赋值,比如 word[0] = ‘m’ 会导致错误。

字符串的截取:索引值以 0 为开始值,-1 为从末尾的开始位置。

遵循左闭右开原则,str[0:2] 是不包含第 3 个字符的,即不包括尾标。

1
变量[头下标:尾下标]

实例:

1
2
3
4
5
6
7
8
9
str = 'Hello, Python!'

print (str) # 输出字符串
print (str[0:-1]) # 输出第一个到倒数第二个的所有字符
print (str[0]) # 输出字符串第一个字符
print (str[2:5]) # 输出从第三个开始到第五个的字符
print (str[2:]) # 输出从第三个开始的后的所有字符
print (str * 2) # 输出字符串两次,也可以写成 print (2 * str)
print (str + "TEST") # 连接字符串

加号 + 是列表连接运算符,星号 * 是重复操作。

反斜杠 \ 转义特殊字符,如果你不想让反斜杠发生转义,可以在字符串前面添加一个 r (raw),表示原始字符串

1
2
3
4
5
6
print('RHello, \nPython!')
RHello,
Python!

print(r'Hello, \nPython!')
Hello, \nPython!
  • ord() 函数返回单个字符的编码;
  • chr() 函数把编码转成相应字符;
1
2
3
4
5
6
s = 'A'
print(ord(s))
print(chr(65))

65
A

python三引号允许一个字符串跨多行,字符串中可以包含换行符、制表符以及其他特殊字符

1
2
3
4
5
6
para_str = """这是一个多行字符串的实例
多行字符串可以使用制表符
TAB ( \t )。
也可以使用换行符 [ \n ]。
"""
print (para_str)

格式化

Python 使用 % 格式化字符串,常用占位符如下表所示:

占位符 描述
%s 格式化字符串
%d 格式化整数
%f 格式化浮点数

实例:

1
2
3
4
print('Hello %s' % 'Python')
Hello Python

print ("我叫 %s 今年 %d 岁!" % ('小明', 20))

format() 方法格式化:

1
print('{0} {1}'.format('Hello', 'Python'))

f-string

f-string 是 python3.6 之后版本添加的,称之为字面量格式化字符串,是新的格式化字符串的语法。

1
2
name = 'Python'
f'Hello {name}' # 替换变量

List(列表)

列表是写在方括号 [] 之间、用逗号分隔开的元素列表。List中的元素是可以改变的。列表中元素的类型可以不相同,它支持数字,字符串甚至可以包含列表(所谓嵌套)。和字符串一样,列表同样可以被索引和截取,列表被截取后返回一个包含所需元素的新列表。

列表截取的语法:索引值以 0 为开始值,-1 为从末尾的开始位置。

1
变量[头下标:尾下标]

加号 + 是列表连接运算符,星号 * 是重复操作。

  • 更新

append() 向列表中添加新元素

1
2
3
4
5
6
7
8
9
10
l = ['Hello', 'Python',1]

# 修改列表中第3个元素
l[1] = 2

# 向列表中添加新元素
l.append('Hello')

print('l[2] -->', l[1])
print('l -->', l)

输出:

1
2
l[2] --> 2
l --> ['Hello', 'Python', 2, '666']
  • 删除

del 删除列表中元素

1
2
3
l = ['Hello', 'Python',1]
# 删除列表中第二个元素
del l[1]
  • count():统计列表中某个元素出现的次数
  • index():查找某个元素在列表中首次出现的位置(即索引)
  • remove():移除列表中某个值的首次匹配项
  • sort():对列表中元素进行排序
  • copy():复制列表
1
2
3
4
5
6
l = ['d', 'b', 'a', 'f', 'd']
print("l.count('d') -->", l.count('d'))
print("l.index('d') -->", l.index('d'))
l.remove('d')
l.sort()
lc = l.copy()

Tuple(元组)

元组(tuple)与列表类似,不同之处在于元组的元素不能修改,常用于保存不可修改的内容。元组写在小括号 () 里,元素之间用逗号隔开,元组中的元素类型也可以不相同,元组也可以使用+操作符进行拼接。

常用方法

  • len():计算元组中元素个数
  • max():返回元组中元素最大值
  • min():返回元组中元素最小值
  • tuple():将列表转换为元组
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
tup1 = ()    # 空元组
tup2 = (20,) # 一个元素,需要在元素后添加逗号
tinytuple = (123, 'Python')
print (tinytuple * 2) # 输出两次元组
print (tuple + tinytuple) # 连接元组

t = ('Hello','Python','666')
t = ('Hello','Python','666','777')

del t
print('len(t) -->', len(t))
print('max(t) -->', max(t))
print('min(t) -->', min(t))

l = ['d', 'b', 'a', 'f', 'd']
t = tuple(l)

Set(集合)

集合(set)是由一个或数个形态各异的大小整体组成的,构成集合的事物或对象称作元素或是成员。

基本功能是进行成员关系测试和删除重复元素。

可以使用大括号 { } 或者 set() 函数创建集合,注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
s = {'a', 'b', 'c'}

# 或者
set(['a', 'b', 'c'])

# 添加元素可以使用 add 或 update 方法,如果元素已经存在,则不进行操作
s.update('e')
s.add('a')

# 删除元素
s.remove('c')

# 获取集合的长度
len(s)

# 清空集合
s.clear()

Dictionary(字典)

字典的内容在花括号 {} 内,键-值(key-value)之间用冒号 : 分隔,键值对之间用逗号 , 分隔。

键必须是唯一的,但值则不必。
值可以取任何数据类型,但键必须是不可变的,如字符串,数字。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 创建字典
d = {'name':'富贵', 'age':'28',2:'num'}

# 使用 dict 函数
# 方式一
l = [('name', '开花'), ('age', 29)]
d = dict(l)
# 方式二
d = dict(name='金尚', age='18')

# 方式三
dict = {}
dict['one'] = "1 - 开花"
dict[2] = "2 - 开花"

# 空字典
d = dict()
d = {}

print (dict['name']) # 输出键为 'name' 的值
print (dict[2]) # 输出键为 2 的值
print (d) # 输出完整的字典
print (d.keys()) # 输出所有键
print (d.values()) # 输出所有值

集合与字典

  • 无序:集合是无序的,所以不支持索引;字典同样也是无序的,但由于其元素是由键(key)和值(value)两个属性组成的键值对,可以通过键(key)来进行索引
  • 元素唯一性:集合是无重复元素的序列,会自动去除重复元素;字典因为其key唯一性,所以也不会出现相同元素

编码

Python2 中默认编码为 ASCII,内容如果为汉字,不指定编码则会乱码,想要指定编码为 UTF-8,Python 中通过在开头加入:

1
# -*- coding: UTF-8 -*-

Python3 中默认编码为 UTF-8,因此在使用 Python3 时,通常不需指定编码。

标识符

标识符是用于给变量、函数、语句块等命名,Python 中标识符由字母、数字、下划线组成,第一个字符必须是字母表中字母或下划线 _,不能以数字开头,区分大小写。

在 Python 3 中,可以用中文作为变量名,非 ASCII 标识符也是允许的了。

以下划线开头的标识符的特殊含义:

  • 单下划线开头的标识符,如:_xxx ,表示不能直接访问的类属性,需通过类提供的接口进行访问,不能用 from xxx import * 导入;
  • 双下划线开头的标识符,如:__xx,表示私有成员;
  • 双下划线开头和结尾的标识符,如:xx__,表示 Python 中内置标识,如:__init() 表示类的构造函数。

关键字

1
2
3
>>> import keyword
>>> keyword.kwlist
['False', 'None', 'True', '__peg_parser__', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']

注释

  • 单行注释以 # 开头。
  • 多行注释可以用多个 # 号,三个单引号(’’’)或三个双引号(”””)。
1
2
3
4
5
6
7
8
9
10
11
12
# 第一个注释
# 第二个注释

'''
第三注释
第四注释
'''

"""
第五注释
第六注释
"""

行与缩进

Python 使用缩进来表示代码块,控制类、函数、逻辑判断等,,不需要使用大括号 {} ,缩进的空格数是可变的,但是同一个代码块的语句必须包含相同的缩进空格数,如果语句缩进数的空格数不一致,会导致运行错误。

1
2
3
4
if True:
print ("True")
else:
print ("False")

多行语句

如果Python 的语句很长,可以使用反斜杠 (\) 来实现多行语句,例如:

1
2
3
total = one + \
two + \
three

如果包含在 []、{}、() 括号中,则不需要使用反斜杠 (\)。如下所示:

1
2
total = ['item_one', 'item_two', 'item_three',
'item_four', 'item_five']

Python3学习-基础语法
Python3学习-基本数据类型
Python3学习-运算符
Python3学习-基本语句
Python3学习-函数
Python3学习-迭代器与生成器
Python3学习-数据结构
Python3学习-模块与包
Python3学习-输入和输出
Python3-字符串格式化
Python3学习-文件操作
Python3学习-OS模块
Python3学习-错误和异常处理
Python3学习-面向对象
Python3学习-命名空间和作用域
Python3学习-函数装饰器
Python3-星号和双星号变量用法
Python3-时间模块
Python3-数学模块
Python3-多线程
Python3-多进程
Python3-MySQL操作
Python3-操作SqLite
Python3-JSON操作
Python3-XML操作
Python3-Word操作
Python3-Excel操作
Python3-网络编程
Python3-标准库1

密码更换周期设置

密码定期更换配置在 /etc/login.defs 中:

1
2
3
4
PASS_MAX_DAYS	90   # 密码到期时间
PASS_MIN_DAYS 6 # 初始密码更改时间
PASS_MIN_LEN 8 # 密码最小长度
PASS_WARN_AGE 10 # 密码过期提示时间

注意:

/etc/login.defs 中设置仅影响创建用户,而不会影响现有用户。
如果设置为现有用户,使用命令 chage -M(days)(user),例如:chage -M 60 root

chage命令

chage 命令是用来修改帐号和密码的有效期限。

语法

chage [选项] 用户名

选项

  • -m:密码可更改的最小天数。为零时代表任何时候都可以更改密码。
  • -M:密码保持有效的最大天数。
  • -w:用户密码到期前,提前收到警告信息的天数。
  • -E:帐号到期的日期。过了这天,此帐号将不可用。
  • -d:上一次更改的日期。
  • -i:停滞时期。如果一个密码已过期这些天,那么此帐号将不可用。
  • -l:例出当前的设置。由非特权用户来确定他们的密码或帐号何时过期。

示例

1
2
3
4
5
# 查看root配置
chage -l root

# 设置root密码90天过期
chage -M 90 root

密码复杂度设置

CentOS7/RHEL7 开始使用 pam_pwquality 模块进行密码复杂度策略的控制管理。pam_pwquality 替换了原来 Centos6/RHEL6 中的 pam_cracklib 模块,并向后兼容。

pam_pwquality模块设置

retry=N 允许重试N次
difok=N 新密码必需与旧密码不同的位数 difok=3 新密码必须与旧密码有3位不同
minlen=N 最小位数
ucredit=N 大写字母位数
lcredit=N 小写字母位数
dcredit=N 数字个数
ocredit=N 特殊字母的个数

两种方式实现:

  • 1,直接指定 pam_pwquality 模块参数,在 /etc/pam.d/system-auth 中的 password requisite pam_pwquality.so 行尾添加具体参数,比如 minlen=16 ucredit=-1 lcredit=-1 ocredit=-1 dcredit=-1 ,表示最小密码长度16位,数字,大小写字母,特殊字符均至少包含1位。

N >= 0:密码中最多有多少个;
N < 0 :密码中最少有多少个;

1
password    requisite     pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type= minlen=8 ucredit=-1 lcredit=-1 ocredit=-1 dcredit=-1
  • 2,通过修改 /etc/security/pwquality.conf 参数文件,定义密码复杂度规则。

修改 pwquality.conf 参数文件有2种方法。

(1)直接修改 /etc/security/pwquality.conf
(2)使用 authconfig 命令修改,修改后最终会体现在 /etc/security/pwquality.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 最小长度
authconfig --passminlen=8 --update
grep "^minlen" /etc/security/pwquality.conf

# 设置同一类的允许连续字符的最大数目
authconfig --passmaxclassrepeat=6 --update
grep "^maxclassrepeat" /etc/security/pwquality.conf

# 至少需要一个小写字符
authconfig --enablereqlower --update
grep "^lcredit" /etc/security/pwquality.conf

# 至少需要一个大写字符
authconfig --enablerequpper --update
grep "^ucredit" /etc/security/pwquality.conf

# 至少需要一个数字
authconfig --enablereqdigit --update
grep "^dcredit" /etc/security/pwquality.conf

# 至少一个特殊字符
authconfig --enablereqother --update
grep "^ocredit" /etc/security/pwquality.conf

# 以下需要单独设置
vim /etc/security/pwquality.conf

# 添加一下配置

# 设置单调字符序列的最大长度
maxsequence = 5

# 新密码中不能出现在旧密码中的字符数
difok = 5

# 检查来自用户 passwd 条目的 GECOS 字段的长度超过3个字符的字是否包含在新密码中。
gecoscheck = 1

# 设置不能包含在密码中的Ssace分隔的单词列表
badwords = test test1 test2

示例:

1
2
vim /etc/security/pwquality.conf
grep -vE "^#|^$" /etc/security/pwquality.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
minlen = 8

# 新密码所需的字符类(数字、大写、小写、其他)的最小字符数。
minclass = 1

# 新密码中允许的连续相同字符的最大数量。如果值为 0,则禁用检查。
maxrepeat = 0

maxclassrepeat = 6
lcredit = -1
ucredit = -1
dcredit = -1
ocredit = -1

Centos7 继续使用 pam_cracklib 模块检验密码复杂度

vim /etc/pam.d/system-auth

1
2
# 添加到 pam_pwquality.so 所在行的上行
password requisite pam_cracklib.so try_first_pass retry=3 type= minlen=8 ucredit=-1 lcredit=-1 ocredit=-1 dcredit=-1

Read Hat配置密码复杂度

vim /etc/pam.d/system-auth

1
password   requisite      pam_cracklib.so retry=3 difok=3 minlen=8 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1

参考:

CentOS7上密码复杂度设置

CentOS7密码复杂度配置

chage命令

CentOS 7 设置密码规则

数据库审计简介

数据库审计(简称 DBAudit)能够实时记录网络上的数据库活动,对数据库操作进行细粒度审计的合规性管理,对数据库遭受到的风险行为进行告警,对攻击行为进行阻断。它通过对用户访问数据库行为的记录、分析和汇报,用来帮助用户事后生成合规报告、事故追根溯源,同时加强内外部数据库网络行为记录,提高数据资产安全。数据库审计可以记录某用户在某个时间点对数据库的操作,包括登录、连接、对表的增删改查等等,便于责任追溯,问题查找,当然开启审计功能在一定方面会影响数据库性能。

环境

  • 操作系统:CentOS7.4
  • Mysql:mysql-5.7.31-linux-glibc2.12-x86_64.tar.gz (社区版)
  • Mariadb:mariadb-10.5.8-linux-x86_64

由于MySQL的社区版不支持审计系统,可通过第三方插件实现,此次采用MariaDB的server_audit插件来记录{时间,节点,用户,源IP,事件类型,库,语句,影响行数},注:从mysql8开始已不支持该插件。

安装插件

1,登陆 Mysql,查看插件安装目录:

1
2
3
4
5
6
7
mysql> show global variables like 'plugin_dir';
+---------------+------------------------------+
| Variable_name | Value |
+---------------+------------------------------+
| plugin_dir | /usr/local/mysql/lib/plugin/ |
+---------------+------------------------------+
1 row in set (0.01 sec)

2,提取 Mariadb 审计插件,并放置Mysql插件目录。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 拷贝
cp /ldjc/mariadb-10.5.8-linux-x86_64/lib/plugin/server_audit.so /usr/local/mysql/lib/plugin/

# 授予执行权限
chmod +x /usr/local/mysql/lib/plugin/server_audit.so

# 安装
# 或者 在 my.cnf 中配置:plugin_load=server_audit=server_audit.so
install plugin server_audit soname 'server_audit.so';

# 备注:
# UNINSTALL PLUGIN server_audit; # 卸载插件
# show variables like '%audit%';

# 查看插件
show plugins;

3,新建 auditlogs 目录,并更改所属的组和用户

1
2
3
mkdir /usr/local/mysql/auditlogs
chown -R mysql /usr/local/mysql/auditlogs
chgrp -R mysql /usr/local/mysql/auditlogs

4,修改my.cnf配置文件

vim /usr/local/mysql/my.cnf

在 [mysqld] 标签下添加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#防止server_audit 插件被卸载 进行配置文件配置
server_audit=FORCE_PLUS_PERMANENT

#指定哪些操作被记录到日志文件中
server_audit_events='CONNECT,QUERY,TABLE,QUERY_DDL'

#开启审计功能
server_audit_logging=on

#默认存放路径,可以不写,默认到data文件下
server_audit_file_path=/usr/local/mysql/auditlogs

#设置文件大小 默认1000000,1073741824=1GB
server_audit_file_rotate_size=1073741824

#指定日志文件的数量,如果为0日志将从不轮转
server_audit_file_rotations=200

#强制日志文件轮转
server_audit_file_rotate_now=ON

4,重启mysql

1
2
3
4
/etc/init.d/mysqld restart

# 或
service mysqld restart

验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
mysql> show variables like '%audit%';
+-------------------------------+-------------------------------+
| Variable_name | Value |
+-------------------------------+-------------------------------+
| server_audit_events | CONNECT,QUERY,TABLE,QUERY_DDL |
| server_audit_excl_users | |
| server_audit_file_path | /usr/local/mysql/auditlogs |
| server_audit_file_rotate_now | ON |
| server_audit_file_rotate_size | 1073741824 |
| server_audit_file_rotations | 200 |
| server_audit_incl_users | |
| server_audit_loc_info | |
| server_audit_logging | ON |
| server_audit_mode | 1 |
| server_audit_output_type | file |
| server_audit_query_log_limit | 1024 |
| server_audit_syslog_facility | LOG_USER |
| server_audit_syslog_ident | mysql-server_auditing |
| server_audit_syslog_info | |
| server_audit_syslog_priority | LOG_INFO |
+-------------------------------+-------------------------------+
16 rows in set (0.00 sec)
1
cat /usr/local/mysql/auditlogs/server_audit.log

参数配置说明

  • server_audit:启用安全审计插件;
  • server_audit_output_type:指定日志输出类型,可为 SYSLOG或 FILE
  • server_audit_logging:启动或关闭审计
  • server_audit_events:指定记录事件的类型,可以用逗号分隔的多个值(connect,query,table),如果开启了查询缓存(query cache),查询直接从查询缓存返回数据,将没有 table 记录
  • server_audit_file_path:如 server_audit_output_type 为 FILE,使用该变量设置存储日志的文件,可以指定目录,默认存放在数据目录的 server_audit.log 文件中
  • server_audit_file_rotate_size:限制日志文件的大小
  • server_audit_file_rotations:指定日志文件的数量,如果为0日志将从不轮转
  • server_audit_file_rotate_now:强制日志文件轮转
  • server_audit_incl_users:指定哪些用户的活动将记录,connect将不受此变量影响,该变量比server_audit_excl_users优先级高
  • server_audit_syslog_facility:默认为LOG_USER,指定facility
  • server_audit_syslog_ident:设置ident,作为每个syslog记录的一部分
  • server_audit_syslog_info:指定的info字符串将添加到syslog记录
  • server_audit_syslog_priority:定义记录日志的syslogd priority
  • server_audit_excl_users:该列表的用户行为将不记录,connect将不受该设置影响
  • server_audit_mode:标识版本,用于开发测试

参考:

MariaDB Audit Plugin Options and System Variables

Mysql5.7安装server_audit审计

MySQL5.7审计功能windows系统

MySQL数据库启用安全审计功能

查看gcc版本

1
gcc -v

查看glibc版本

1
ldd --version
1
2
gcc -v
ldd --version

修改配置文件

前提:

  • 1,两台服务器都需要添加一个用户数据同步的帐号。
  • 2,端口,策略,数据库远程等互通。
  • 3,主库备份后,从库需要还原备份文件。

配置以下两台服务器互为主从。

配置:vim /usr/local/mysql/my.cnf

主1服务器配置:

1
2
3
4
5
6
auto_increment_increment=2         #步进值 auto_imcrement。一般有n台主MySQL就填n
auto_increment_offset=1 #起始值。一般填第n台主MySQL。此时为第一台主MySQL
binlog-ignore-db=mysql #忽略mysql库【可忽略不写】
binlog-ignore-db=information_schema #忽略information_schema库【可忽略不写】
binlog-ignore-db=performance_schema #忽略performance_schema库【可忽略不写】
log-slave-updates=on

主2服务器配置:

1
2
3
4
5
6
auto_increment_increment=2         #步进值auto_imcrement。一般有n台主MySQL就填n
auto_increment_offset=2 #起始值。一般填第n台主MySQL。此时为第二台主MySQL
binlog-ignore-db=mysql #忽略mysql库【可忽略不写】
binlog-ignore-db=information_schema #忽略information_schema库【可忽略不写】
binlog-ignore-db=performance_schema #忽略performance_schema库【可忽略不写】
log-slave-updates=on

主1完整配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
[mysql]
socket=/var/lib/mysql/mysql.sock
# set mysql client default chararter
default-character-set=utf8
#
[mysqld]
socket=/var/lib/mysql/mysql.sock
bind-address=0.0.0.0
# set mysql server port
port = 3306 #默认是3306,防止这种情况发生,可以避免使用3306mysql默认端口
# set mysql install base dir
basedir=/usr/local/mysql
# set the data store dir
datadir=/usr/local/mysql/data
# set the number of allow max connnection
max_connections=200000
# set server charactre default encoding
character-set-server=utf8
# the storage engine
default-storage-engine=INNODB
# lower_case_table_names=1
max_allowed_packet=16M
explicit_defaults_for_timestamp=true

sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

# 服务器唯一ID
server-id=1

# 要生成二进制日志文件 主服务器一定要开启
log-bin=/usr/local/mysql/binlogs/bin-log

binlog_format=ROW
expire_logs_days=7
max_binlog_size=100M
binlog_cache_size=4M
max_binlog_cache_size=512M

auto_increment_increment=2
auto_increment_offset=1
binlog-ignore-db=mysql
binlog-ignore-db=information_schema
binlog-ignore-db=performance_schema

log-slave-updates=on

#skip-grant-tables=1

[mysql.server]
user=mysql
basedir=/usr/local/mysql

配置主从

互相配置主从服务器。

主1服务器:192.123.75.68;
主2服务器:192.123.3.87;

登陆到主1服务器,执行一下命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 查看 主 复制状态
show master status \G

change master to master_host='192.123.3.87',
master_port=3306,
master_user='slave',
master_password='123456',
master_log_file='bin-log.000005',
master_log_pos=74562307;

# 开始复制
start slave;

# 查看 从 复制状态
# 输出结果中应该看到 I/O 线程和 SQL 线程都是 YES, 就表示成功。
show slave status \G

# 主服务器复制状态
show master status\G

登陆到主2服务器,执行一下命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 查看 主 复制状态
show master status \G

change master to master_host='192.123.75.68',
master_port=3306,
master_user='slave',
master_password='123456',
master_log_file='bin-log.000005',
master_log_pos=74562307;

# 开始复制
start slave;

# 查看 从 复制状态
# 输出结果中应该看到 I/O 线程和 SQL 线程都是 YES, 就表示成功。
show slave status \G

# 主服务器复制状态
show master status\G
0%