1. 常见的数据类型
  2. 字符串的常用操作
  3. 列表的语法和使用
  4. 元组的语法和使用
  5. 字典的语法和使用

常见的数据类型

Python中的数据类型可以分为两类,一类是 基本数据类型 一类是 引用数据类型

基本数据类型

  • 字符型: ‘a’, ‘message’
  • 数值型: 59, 1991.59
  • 布尔类型: True, False

引用数据类型

  • 列表: [1, 2, 3], [‘abc’, ‘xyz’]
  • 元组: (1, 2, 3), (‘abc’, ‘xyz’)
  • 字典: {‘name’=’larry’, ‘age’: 25}

基本数据类型与引用数据类型的区别:前者传值,后者传址

字符串的常用操作

  • 移除字符串的两端空白字符
1
2
3
4
5
6
7
8
9
10
11
12
13
14

In [12]: a = ' aa '

In [13]: a
Out[13]: ' aa '

In [14]: a.strip()
Out[14]: 'aa'

In [15]: a.lstrip()
Out[15]: 'aa '

In [16]: a.rstrip()
Out[16]: ' aa'
  • 将字符串以指定的分割符分割成列表
1
2
3
4
5

In [17]: a = 'a,b,c,d,e'

In [18]: a.split(',')
Out[18]: ['a', 'b', 'c', 'd', 'e']
  • 统计字符串长度
1
2
3
4
5

In [19]: a = 'I am Chinese!'

In [20]: len(a)
Out[20]: 13
  • 在字符串中找到指定字符的位置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
In [21]: a = 'polarsnow'

In [22]: a.index('o')
Out[22]: 1

In [23]: a.index('o', 2)
Out[23]: 7

In [24]: a.index('o', 2, 6)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-24-2bb3a06d2fe6> in <module>()
----> 1 a.index('o', 2, 6)

ValueError: substring not found
  • 切片
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
In [25]: a = 'polarsnow'

In [26]: a[0:5]
Out[26]: 'polar'

In [27]: a[:5]
Out[27]: 'polar'

In [28]: a[-1]
Out[28]: 'w'

In [29]: a[-4:]
Out[29]: 'snow'

In [30]: a[5:]
Out[30]: 'snow'

In [31]: a[-4:-1] #注意Python中的切片是左闭右开
Out[31]: 'sno'
  • 统计字符串中指定字符的个数
1
2
3
4
In [32]: a = 'polarsnow'   

In [33]: a.count('o')
Out[33]: 2
  • 将指定字符串置于中央
1
2
3
4
In [34]: a = 'polarsnow'

In [35]: a.center(50, '-')
Out[35]: '--------------------polarsnow---------------------'
  • 判断是否以指定字符串开头或结尾
1
2
3
4
5
6
7
In [38]: a = 'polarsnow'  

In [39]: a.endswith('ow')
Out[39]: True

In [40]: a.startswith('po')
Out[40]: True
  • 字符串大小写或首字母大写
1
2
3
4
5
6
7
8
9
10
In [41]: a = 'polarsnow'   

In [42]: a.upper()
Out[42]: 'POLARSNOW'

In [43]: a.upper().lower()
Out[43]: 'polarsnow'

In [44]: a.capitalize()
Out[44]: 'Polarsnow'
  • 字符串属性判断-isalnum-是否只含有字母和数字
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
In [46]: a = 'polarsnow'

In [47]: a.isalnum()
Out[47]: True

In [48]: a = 'polarsnow%'

In [49]: a.isalnum()
Out[49]: False

In [50]: a = 'polarsnow5'

In [51]: a.isalnum()
Out[51]: True

In [52]: a = 'polar snow'

In [53]: a.isalnum()
Out[53]: False
  • 字符串属性判断-isalpha-是否只含有字母
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
In [54]: a = 'polarsnow' 

In [55]: a.isalpha()
Out[55]: True

In [56]: a = 'polarsnow%'

In [57]: a.isalpha()
Out[57]: False

In [58]: a = 'polarsnow5'

In [59]: a.isalpha()
Out[59]: False

In [60]: a = 'polar snow'

In [61]: a.isalpha()
Out[61]: False
  • 字符串属性判断-isdigit-是否只包含数字
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

In [62]: a = '123'

In [63]: a.isdigit()
Out[63]: True
``

- 字符串属性判断-isspace-是否只包含空格

```python
In [71]: a = ' '

In [72]: a.isspace()
Out[72]: True

In [73]: a = ''

In [74]: a.isspace()
Out[74]: False
  • 字符串其他属性判断
1
2
3
str.isupper()  #检查字符串所有的字母是否全部为大写
str.islower() #检查字符串的所有字母是否全部为小写
str.istitle() #检查字符串的所有单词拼写是否首字母大写,其余小写
  • 字符串拼接可迭代对象
1
2
3
4
5
6
7
8
l = [1, 2, 3, 4, 5]
print("".join(l))

------------
Traceback (most recent call last):
File "/Users/lvrui/PycharmProjects/untitled/4/test.py", line 2, in <module>
print("".join(l))
TypeError: sequence item 0: expected str instance, int found

使用join的方式把一个可迭代对象进行拼接的基本要求是,可迭代对象中的每一个元素必须是字符串!!!

1
2
3
4
5
l = ['1', '2', '3', '4', '5']
print("+".join(l))

------------
1+2+3+4+5

列表的常用操作

  • 列表的定义
1
2
list_a = []  #定义了一个空列表
list_b = [1, 'a', [2, 'z']] #嵌套列表
  • 列表的索引/取值
1
2
3
4
5
6
7
In [75]: a = ['a', 'b', 'c', 'a', 'd']

In [76]: a[0]
Out[76]: 'a'

In [77]: a[1]
Out[77]: 'b'
  • 列表的切片
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
In [78]: a = ['a', 'b', 'c', 'a', 'd']

In [79]: a[2:]
Out[79]: ['c', 'a', 'd']

In [80]: a[-1]
Out[80]: 'd'

In [81]: a[-2:]
Out[81]: ['a', 'd']

In [82]: a[1:3]
Out[82]: ['b', 'c'] #与字符串的切片相同,也要注意左闭右开

In [128]: a = ['a', 'b', 'c', 'a', 'd']

In [129]: a[::2] #设置步长
Out[129]: ['a', 'c', 'd']
  • 列表的遍历
1
2
3
4
5
6
7
8
9
10
In [83]: a = ['a', 'b', 'c', 'a', 'd']

In [84]: for item in a:
....: print item
....:
a
b
c
a
d
  • 向列表中追加数据
1
2
3
4
5
6
In [85]: a = ['a', 'b', 'c', 'a', 'd']

In [86]: a.append('xxx')

In [87]: a
Out[87]: ['a', 'b', 'c', 'a', 'd', 'xxx']
  • 向列表中插入数据
1
2
3
4
5
6
In [107]: a = ['a', 'b', 'c', 'a', 'd']

In [108]: a.insert(0, 'xxx')

In [109]: a
Out[109]: ['xxx', 'a', 'b', 'c', 'a', 'd']
  • 删除列表中的元素
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
In [88]: a = ['a', 'b', 'c', 'a', 'd']

In [89]: del a[0] #万能删除法 可以将整个变量删除

In [90]: a
Out[90]: ['b', 'c', 'a', 'd']

In [91]: a.pop() #将列表最后一个元素删除
Out[91]: 'd'

In [92]: a
Out[92]: ['b', 'c', 'a']

In [93]: a.remove('c') #删除列表中,第一次出现的指定元素(即使有两个c,只会删除第一个)

In [94]: a
Out[94]: ['b', 'a']

In [95]: a = ['a', 'b', 'c', 'a', 'd'] #重新赋值

In [96]: a
Out[96]: ['a', 'b', 'c', 'a', 'd']

In [97]: del a[1:4] #删除连续的元素 注意左闭右开

In [98]: a
Out[98]: ['a', 'd']
  • 修改列表中的元素
1
2
3
4
5
6
7
8
In [101]: a = ['a', 'b', 'c', 'a', 'd']

In [102]: a[3] = 'd'

In [103]: a[4] = 'e'

In [104]: a
Out[104]: ['a', 'b', 'c', 'd', 'e']
  • 列表的长度
1
2
3
4
In [105]: a = ['a', 'b', 'c', 'a', 'd']

In [106]: len(a)
Out[106]: 5 #长度为5 注意索引只到4
  • 统计列表中指定元素的个数
1
2
3
4
In [110]: a = ['a', 'b', 'c', 'a', 'd']

In [111]: a.count('a')
Out[111]: 2
  • 将列表中的元素顺序反转
1
2
3
4
5
6
In [112]: a = ['a', 'b', 'c', 'a', 'd']

In [113]: a.reverse()

In [114]: a
Out[114]: ['d', 'a', 'c', 'b', 'a']
  • 排序(根据ascii码)
1
2
3
4
5
6
In [115]: a = ['a', 'b', 'c', 'a', 'd']

In [116]: a.sort()

In [117]: a
Out[117]: ['a', 'a', 'b', 'c', 'd']
  • 列表的扩展
1
2
3
4
5
6
7
8
In [120]: a = ['a', 'b', 'c', 'a', 'd']

In [121]: b = ['xxx', 'yyy']

In [122]: a.extend(b)

In [123]: a
Out[123]: ['a', 'b', 'c', 'a', 'd', 'xxx', 'yyy']

元组的语法和使用(元组就是不可变的列表)

元组中不可增,删,改。在取值的时候与列表操作类似,有以下常用方法

  • tuple.count(): 统计指定元素的个数

  • tuple.index(): 找到指定元素的索引

字典的语法和使用

  • 字典的定义
1
2
3
In [132]: a = {}  #定义了一个空字典

In [133]: a = {'a':1, 'b':2, 'c':3}
  • 字典中增加元素/修改元素
1
2
3
4
5
6
7
8
9
10
11
12
13
#字典是不重复且无序的,增加元素的操作和修改类似,如果元素存在即修改,如果元素不存在即添加

In [133]: a = {'a':1, 'b':2, 'c':3}

In [134]: a['d'] = 4

In [135]: a
Out[135]: {'a': 1, 'b': 2, 'c': 3, 'd': 4}

In [136]: a['d'] = 59

In [137]: a
Out[137]: {'a': 1, 'b': 2, 'c': 3, 'd': 59}
  • 删除字典中的元素
1
2
3
4
5
6
7
8
9
10
11
12
In [140]: a = {'a':1, 'b':2, 'c':3}

In [141]: a.pop('b') #因为字典是无序的 与列表中的pop删除最后一个元素的概念区分开 这里需要指定“键”
Out[141]: 2

In [142]: a
Out[142]: {'a': 1, 'c': 3}

In [143]: del a['a'] #万能删除依然好用~~~

In [144]: a
Out[144]: {'c': 3}
  • 指定key取值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

In [145]: a = {'a':1, 'b':2, 'c':3}

In [146]: a['a']
Out[146]: 1

In [147]: a['d'] #这种取值的方法如果没有找到,则报错
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-147-0b64a016a51f> in <module>()
----> 1 a['d']

KeyError: 'd'

In [148]: a.get('d') #使用get如果没有找到,则返回None

In [149]:

In [162]: 'a' in a #使用万能的in语法
Out[162]: True
  • 查找所有的”键”和所有的“值”
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
In [150]: a = {'a':1, 'b':2, 'c':3}

In [151]: a.keys()
Out[151]: ['a', 'c', 'b']

In [152]: a.values()
Out[152]: [1, 3, 2]

In [153]: a = {'a':1, 'b':2, 'c':3}

In [154]: a.items()
Out[154]: [('a', 1), ('c', 3), ('b', 2)]

In [155]: for k,v in a.items(): #执行效率低下(有dict2list的转换过程),数据量大不推荐使用
.....: print('key: ', k, 'value: ', v)
.....:
('key: ', 'a', 'value: ', 1)
('key: ', 'c', 'value: ', 3)
('key: ', 'b', 'value: ', 2)

In [170]: for key in a: #高效的字典遍历方法
.....: print(key, a[key])
.....:
('a', 1)
('c', 3)
('b', 2)
  • 使用子列表更新主列表中的元素(覆盖)
1
2
3
4
5
6
7
8
9
In [157]: a
Out[157]: {'a': 1, 'b': 2, 'c': 3}

In [158]: b = {'c': 59}

In [159]: a.update(b)

In [160]: a
Out[160]: {'a': 1, 'b': 2, 'c': 59}
  • dict.setdefault(k,v)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#根据k去取值,如果有则返回v,如果没有则添加这个元素
In [164]: a = {'a':1, 'b':2, 'c':3}

In [165]: a.setdefault('a')
Out[165]: 1

In [166]: a.setdefault('a', 59)
Out[166]: 1

In [167]: a.setdefault('d', 59)
Out[167]: 59

In [168]: a
Out[168]: {'a': 1, 'b': 2, 'c': 3, 'd': 59}

前些日志在研究saltstack的api,使用了https的方式来访问api,创建一对儿密钥/etc/pki/tls/certs/localhost.crt/etc/pki/tls/certs/localhost.key 过了几天后发现我实验的这台机器的Apache服务宕掉了,而且重启失败,故障信息如下

1
2
3
4
5
6
7
8
9
10
11
shell> service httpd restart
Stopping httpd: [FAILED]
Starting httpd: [FAILED]

shell> tail /var/log/httpd/error_log
[Mon Mar 28 10:46:36 2016] [notice] suEXEC mechanism enabled (wrapper: /usr/sbin/suexec)

shell> tail /var/log/httpd/ssl_error_log
[Mon Mar 28 10:49:19 2016] [warn] RSA server certificate CommonName (CN) `localhost' does NOT match server name!?
[Mon Mar 28 10:49:19 2016] [error] Unable to configure RSA server private key
[Mon Mar 28 10:49:19 2016] [error] SSL Library Error: 185073780 error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch
  • 当我发现重启失败且终端没有报错输出时,当时打开了/var/log/message/var/log/httpd/error_log两个log,重新重启Apache服务,发现message没有输出,而httpd的error_log有一行[notice] suEXEC mechanism enabled (wrapper: /usr/sbin/suexec)输出
  • 发现suEXEC之后,我百度了该关键字,得知是负责处理CGI和SSI程序的请求,当我看到SSL的时候,就突然想起之前做过的salt-api的实验,当时创建了一对儿密钥,该密钥过期时间大概是24小时,猜测可能是Apache的默认配置文件加载了mod_ssl模块,而且引用了我创建密钥对儿的默认位置,而该密钥却处于失效状态,所以Apache服务无法启动(这是当时的猜测)
  • 知道是SSL相关的问题之后,马上打开/var/log/httpd/ssl_error_log查看情况,有如下报错[warn] RSA server certificate CommonName (CN)localhost’ does NOT match server name!?` 当看到这一行报错的时候,已经确认上面猜测的第一点,就是Apache的默认配置文件加载了mod_ssl模块,而且指定密钥对儿的位置,就是我测试salt-api时创建密钥对儿的位置。而且还有一个错误就是我密钥对儿指定的hostname和Apache指定的hostname并不相同,基于密钥对主机名不符与密钥过期两点,造成了Apache无法启动的故障。
  • 确定了问题之后,解决方案有很多种,核心思想就是让Apache的ssl配置失效
    • 第一种办法,可以在Apache的配置中禁用mod_ssl模块/etc/httpd/conf.d/ssl.conf
    • 第二种办法,在/etc/httpd/conf.d/ssl.conf配置文件中,指定其他密钥对儿的路径
    • 第三种办法,我的salt-api已经测试完毕,可以把创建的密钥对儿删除或更名
  • 最终我是选择了第三种的方法,将原有的密钥对儿加了.bak后缀,之后重启Apache恢复正常,问题解决,回头再去查看/etc/httpd/conf.d/ssl.conf配置文件的时候,已经自动变成了/etc/httpd/conf.d/ssl.conf.bak相当于Apache找不到配置文件中指定的密钥对儿后,自动禁用了mod_ssl模块

如果你想了解suexec方面的东西,可以参考以下文章:

http://blog.csdn.net/hulihong/article/details/5416056

如果需要通过第三方来调用SaltStack时,使用SaltStack自带的Python API并不能很好的满足需求。可以通过使用SaltStack基于RESTful风格的HTTP API。该API模块并不是内置的,需要单独安装。

Salt REST API简介

这里简单的说明下,SaltStack官方支持三种REST API,分别是rest_cherry; rest_tonado和rest_wsgi

  • rest_cherry和rest_tonado两个模块支持监听所有IP的指定端口接收请求
1
2
3
shell> lsof -i:1559
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
salt-api 13443 root 14u IPv4 21888585 0t0 TCP *:web2host (LISTEN)
  • rest_wsgi只支持本机访问,只绑定了127.0.0.1
1
2
3
shell> lsof -i:1559
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
salt-api 13443 root 14u IPv4 21888585 0t0 TCP 127.0.0.1:web2host (LISTEN)

image

本文选择使用rest_cherry模块来实现SaltStack的HTTP API

安装Salt-API服务

一般情况下,salt-api会使用HTTPS,首次配置成功后,使用用户名和密码登陆,获得Token,Token创建后,默认有效期是12小时,在有效期之内,使用该Token可以代替使用用户名和密码来访问API(该有效时间可在salt-master配置文件中修改)

必备安装包

1
2
shell> yum -y install gcc make python-devel libffi-devel
shell> pip install pyOpenSSL==0.15.1

借助salt工具来生成证书

1
2
3
shell> salt-call --local tls.create_self_signed_cert
local:
Created Private Key: "/etc/pki/tls/certs/localhost.key." Created Certificate: "/etc/pki/tls/certs/localhost.crt."

salt-call是salt-minion的工具,如果没有这个命令,可以在master端安装minion,然后再执行以上命令

安装salt-api

1
shell> yum -y install salt-api

配置用户及权限

1
2
shell> useradd -M -s /sbin/nologin sa
shell> echo "sapassword" | passwd sa --stdin

在salt-master的配置文件最后添加如下配置

1
2
3
4
5
6
external_auth:
pam: #认证模式,pam指的是用Linux本身的用户认证模式
sa: #Linux系统中真实存在的用户名
- '*': #设置用户的权限,允许该用户操作哪些主机,*代表全部
- test.* #允许操作的模块及方法
- cmd.*

其他认证模式可以参考官方文档:http://docs.saltstack.com/en/latest/topics/eauth/index.html

配置示例一:多用户(官方文档)

1
2
3
4
5
6
7
8
external_auth:
pam:
thatch:
- 'web*':
- test.*
- network.*
steve:
- .*

配置示例二:指定用户组(官方文档)

1
2
3
4
5
external_auth:
pam:
admins%:
- '*':
- 'pkg.*'

使用%来表示用户组

配置示例三:操作模块组(官方文档)

1
2
3
4
5
6
external_auth:
pam:
thatch:
- '@wheel' # to allow access to all wheel modules
- '@runner' # to allow access to all runner modules
- '@jobs' # to allow access to the jobs runner and/or wheel module

点此查看wheel modules完整列表

点此查看runner modules完整列表


配置salt-api服务

在salt-master的配置文件最后添加如下配置

1
2
3
4
rest_cherrypy:
port: 1559 #默认监听所有IP的1559端口
ssl_crt: /etc/pki/tls/certs/localhost.crt #引用的正是前面创建的证书
ssl_key: /etc/pki/tls/certs/localhost.key

其他配置参数可以参考官方文档:https://docs.saltstack.com/en/latest/ref/netapi/all/salt.netapi.rest_cherrypy.html


启动服务

1
shell> service salt-api start

登陆获得Token

1
2
3
4
5
curl -sSk https://www.20150509.cn:1559/login \
-H 'Accept: application/x-yaml' \
-d username=sa \
-d password=sapassword \
-d eauth=pam

复制得到的Token

1
2
3
4
5
6
curl -sSk https://localhost:8000 \
-H 'Accept: application/x-yaml' \
-H 'X-Auth-Token: 697adbdc8fe971d09ae4c2a3add7248859c87079'\
-d client=local \
-d tgt='*' \
-d fun=test.ping

除了支持Token以外还支持使用cookies.txt文件来访问API,详情可查看官方文档


使用Python脚本来访问API

在salt-api官方文档中,对python访问API给出了如下的格式要求

1
2
3
4
5
6
7
8
9
10
11
[{
"client": "local",
"tgt": "*",
"fun": "test.fib",
"arg": ["10"]
},
{
"client": "runner",
"fun": "jobs.lookup_jid",
"jid": "20130603122505459265"
}]

以上的JSON代码中,指定了API去执行两个命令,一个模块命令,一个runner命令。Python代码实现如下:

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
import json
import urllib
import urllib2

#在python2.6x中,以下两行不是必须的
import ssl
ssl._create_default_https_context = ssl._create_unverified_context

url='https://www.20150509.cn:1559' #salt-api所在的“坐标”

def test():
pre_data = [{"client":"local", "tgt":"*", "fun":"test.ping"}] #根据上面官方文档的要求组成数组嵌套字典的形式
json_data = json.dumps(pre_data) #将其转化为json格式

header = {"Content-Type":"application/json", "Accept":"application/json", "X-Auth-Token":"697adbdc8fe971d09ae4c2a3add7248859c87079"}
#这里说明下,Content-Type是声明传递给API的数据是什么格式的,这里指定了json,是因为上面的pre_data数据被我转化成了json格式
#Accept是声明返回结果以什么样的格式显示,这里也指定了json格式来显示返回结果

request = urllib2.Request(url, json_data, header) #构造一次请求
response = urllib2.urlopen(request) #构造一次HTTP访问

html = response.read()
print html


if __name__=="__main__":
test()

指定Acceptapplication/json执行结果如下:

1
2
3
shell> python sa.py 
{"return": [{"vm3.salt.com": true, "vm2.salt.com": true, "ph1.salt.com": true, "ph2.salt.com": true, "vm1.salt.com": true, "vm4.salt.com": true, "localhost": true, "vm7.salt.com": true}]}
#

指定Acceptapplication/x-yaml执行结果如下:

1
2
3
4
5
6
7
8
9
10
shell> python sa.py 
return:
- localhost: true
ph1.salt.com: true
ph2.salt.com: true
vm1.salt.com: true
vm2.salt.com: true
vm3.salt.com: true
vm4.salt.com: true
vm7.salt.com: true

附录

RESTful API的日常操作

  • 运行远程模块
  • 查询指定job
  • 运行runner

稍后有时间会分别详细举出几个使用案例

REST URI 参考

1
2
3
4
5
6
7
8
9
10
11
/
/login
/logout
/minions
/jobs
/run
/events
/hook
/keys
/ws
/stats

详细用法可参考salt-api rest_cherry官方文档

参考文档

salt-api:https://github.com/saltstack/salt-api

rest_cherrypy:https://docs.saltstack.com/en/latest/ref/netapi/all/salt.netapi.rest_cherrypy.html

认证模式:http://docs.saltstack.com/en/latest/topics/eauth/index.html

在python中使用urllib2库去访问一个自签名的网站时,会出现如下报错: urllib2.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)>

出现以上错误的原因是因为python的版本问题,在python2.6(含2.6)以下版本中,在访问HTTPS的网站时,TLS握手期间不会检查服务器X509的证书签名是否是CA的可信任根证书。这种局面在python2.7 3.4 和 3.5版本中得到了修改。

所以,以下代码在python2.6版本中测试是完全没有问题的

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

import json
import urllib
import urllib2

url='https://www.20150509.cn:1559'

def test():

pre_data = [{"client":"local", "tgt":"*", "fun":"test.ping"}]

json_data = json.dumps(pre_data)

header = {"Content-Type":"application/json", "Accept":"application/json", "X-Auth-Token":"b91e7uj86g4f97cc**********b92778ujh4kedf"}

request = urllib2.Request(url, json_data, header)

response = urllib2.urlopen(request)

html = response.read()

print html


if __name__=="__main__":
test()

运行测试

1
2
shell> python sa.py 
{"return": [{"vm3.salt.com": true, "vm2.salt.com": true, "ph1.salt.com": true, "ph2.salt.com": true, "vm1.salt.com": true, "vm4.salt.com": true, "localhost": true, "vm7.salt.com": true}]}

在python2.7+版本就会报上述错误

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
shell> python sa.py 
Traceback (most recent call last):
File "sa.py", line 25, in <module>
test()
File "sa.py", line 17, in test
response = urllib2.urlopen(request)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 154, in urlopen
return opener.open(url, data, timeout)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 431, in open
response = self._open(req, data)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 449, in _open
'_open', req)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 409, in _call_chain
result = func(*args)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 1240, in https_open
context=self._context)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 1197, in do_open
raise URLError(err)
urllib2.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)>

解决方法:

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
import json
import urllib
import urllib2
import ssl #add line 1

ssl._create_default_https_context = ssl._create_unverified_context #add line 2

url='https://www.20150509.cn:1559'

def test():

pre_data = [{"client":"local", "tgt":"*", "fun":"test.ping"}]

json_data = json.dumps(pre_data)

header = {"Content-Type":"application/json", "Accept":"application/json", "X-Auth-Token":"b91e7uj86g4f97cc**********b92778ujh4kedf"}

request = urllib2.Request(url, json_data, header)

response = urllib2.urlopen(request)

html = response.read()

print html


if __name__=="__main__":
test()

参考文档:

http://https://www.python.org/dev/peps/pep-0476/

以下出现的MySQL问题均为本人亲历,所以本文的“问题汇总”实际为个人版本的“问题汇总”,如有其它MySQL问题,欢迎Email联系我共同讨论!

MySQL初始化问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
shell> mysql
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)

shell> service mysqld restart
Stopping mysqld: [ OK ]
MySQL Daemon failed to start.
Starting mysqld: [FAILED]

#日志中报错如下:
[ERROR] Fatal error: mysql.user table is damaged. Please run mysql_upgrade.
[ERROR] Aborting

#这种情况本人是在MySQL5.1到5.7版本升级时遇到的,升级到5.7后,数据库启动失败
#解决的办法就是重新初始化数据库

shell> rm -fr /var/lib/mysql
shell> mysqld --initialize --user=mysql
shell> service mysqld restart
Stopping mysqld: [ OK ]
Starting mysqld: [ OK ]

mysql-files文件问题

1
2
3
4
5
6
7
8
9
10
#MySQL启动失败,日志中报错如下:
[ERROR] Failed to access directory for --secure-file-priv. Please make sure that directory exists and is accessible by MySQL Server. Supplied value : /var/lib/mysql-files

#造成这种情况可能是因为mysql-files文件夹不存在或权限错误
#解决办法如下:
shell> touch /var/lib/mysql-files
shell> chown mysql:mysql /var/lib/mysql-files
shell> service mysqld restart
Stopping mysqld: [ OK ]
Starting mysqld: [ OK ]

CentOS6系列,自带的repo库中,默认安装的依然是MySQL5.1版本,过于老旧,而5.6+版本相比5.1版本在各个方面均有全名的提升,对性能要求较高的应用优先考虑5.6+版本。本篇文章介绍使用MySQL官方源安装MySQL5.7

1
2
3
4
shell> cd /usr/local/src
shell> wget http://repo.mysql.com//mysql57-community-release-el6-7.noarch.rpm
shell> rpm -ivh mysql57-community-release-el6-7.noarch.rpm
shell> yum install mysql-server #这里会默认安装mysql-community-server和对应版本的mysql-community-client

如果已经安装有5.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
shell> yum remove mysql
Loaded plugins: fastestmirror
Setting up Remove Process
Resolving Dependencies
--> Running transaction check
---> Package mysql.x86_64 0:5.1.73-5.el6_6 will be erased
--> Processing Dependency: mysql = 5.1.73-5.el6_6 for package: mysql-server-5.1.73-5.el6_6.x86_64
--> Running transaction check
---> Package mysql-server.x86_64 0:5.1.73-5.el6_6 will be erased
--> Finished Dependency Resolution

Dependencies Resolved

=====================================================================================
Package Arch Version Repository Size
=====================================================================================
Removing:
mysql x86_64 5.1.73-5.el6_6 @base 2.4 M
Removing for dependencies:
mysql-server x86_64 5.1.73-5.el6_6 @base 25 M

Transaction Summary
=====================================================================================
Remove 2 Package(s)

Installed size: 27 M
Is this ok [y/N]:
#卸载老版本的MySQL,默认会同时卸载掉对应的client端

#执行上面的安装部分...

#启动数据库可能会出现下面的错误
shell> service mysqld restart
Stopping mysqld: [ OK ]
MySQL Daemon failed to start.
Starting mysqld: [FAILED]

shell> mysql
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)

#查看日志出现如下报错
#[ERROR] Fatal error: mysql.user table is damaged. Please run mysql_upgrade.

#解决方法是重新初始化数据库
shell> rm -fr /var/lib/mysql
shell> mysqld --initialize --user=mysql
shell> service mysqld restart
Stopping mysqld: [ OK ]
Starting mysqld: [ OK ]

假如老版本的5.1由于某些原因,不能卸载或不允许卸载,那么安装5.7时,可以使用编译安装的方式,将新数据库启动的端口由3306改成3307,即可实现两个MySQL版本的数据库进程共存

本文介绍在CentOS6系列系统中,安装zabbix 3.0与grafana 2.5 搭配的监控系统
据了解在zabbix 3.0 LTS版本有50余项升级,zabbix是结合了众多监控系统的优点,是一款比较全面分布式监控系统。在与Grafana搭伙后,完美解决了Zabbix GUI审美疲劳的痛点,接下来进入正题(Zabbix 3.0安装部分完全按照官方文档的步骤实现)

前言

  1. 本文的Zabbix部分知识只介绍它的基础安装,Zabbix的使用以及配置优化并不在本文的介绍范围之内。
  2. 本文只介绍在CentOS6系列下的安装和部署,其他发行版与其他版本号暂不涉及
  3. 本文默认使用MySQL作为后端数据库支持

CentOS 6.x 基础环境配置部分

基础环境介绍

  • CentOS 6.7 64bit
  • 8CPU
  • 1G Mem
  • MySQL InnoDB

基础依赖环境配置

Apache

1.Zabbix官方文档要求Apache的版本要在1.3.12之后

1
2
3
4
5
6
7
8
9
10
11
12
shell> yum install httpd -y
Loaded plugins: fastestmirror, refresh-packagekit, security
Setting up Install Process
Loading mirror speeds from cached hostfile
* base: mirrors.neusoft.edu.cn
* epel: mirrors.yun-idc.com
* extras: mirrors.btte.net
* remi-safe: mirror.innosol.asia
* rpmforge: mirrors.neusoft.edu.cn
* updates: mirrors.btte.net
Package httpd-2.2.15-47.el6.centos.3.x86_64 already installed and latest version
Nothing to do

我这里已经安装了httpd 2.2版本,符合官方文档中的要求

2.启动httpd服务,并设置为开机自动启动

1
2
shell> service httpd start
shell> chkconfig httpd on

PHP

PHP的版本要求在5.4以上,但Linux 6.x系统自带repo中的PHP版本是5.3.3 不符合Zabbix官方文档的要求,需要使用Remi repo来安装更高版本的PHP

配置Remi Repo来安装高版本的PHP

1.下载Remi

1
shell> yum install http://rpms.famillecollet.com/enterprise/remi-release-6.rpm

2.配置Remi

1
2
3
使用习惯的文本编辑器(如 vim)打开 Remi 源配置文件 /etc/yum.repos.d/remi.repo
启用 Remi Repository修改 enabled=0 为 enabled=1
为 Remi Repository 设置合适的优先级在 [remi] 那一节的结尾另起一行添加下面的代码:priority=3

3.安装PHP

1
shell> yum install --enablerepo=remi php php-gd

4.根据Zabbix官方文档需求安装PHP扩展

1
shell> yum install php-bcmath php-ctype php-xml php-xmlreader php-xmlwriter php-session php-net-socket php-gettext php-mbstring php-gettext php-ldap php-mysql

Server

根据官方文档的要求,需要在服务器中安装一下软件支持

1
shell> yum install OpenIPMI OpenIPMI-devel libssh2 libssh2-devel fping libcurl libxml2 libxml2-devel net-snmp

MySQL

官方文档要求MySQL的版本要在5.0.3以上,CentOS 6.7默认的repo里提供的MySQL版本为5.1.73 符合官方文档要求

1
2
3
shell> yum install mysql mysql-server mysql-devel
shell> service mysqld start #首次启动需要初始化
shell> chkconfig mysqld on #添加开机自动启动

Zabbix安装部分

Zabbix 3.0的安装参考了官方文档中源码编译安装的方式,软件包的方式比较简单,大家可以参考官方文档自行试验,时间关系,这里暂不介绍rpm包的安装方式,后续有时间会补充提供这种安装方式的说明

源码安装的方式

下载Zabbix 3.0源码包并解压

Zabbix 3.0 源码官方下载地址: http://www.zabbix.com/download.php
选择Zabbix Sources下的Zabbix 3.0 LTS进行下载

1
shell> tar -zxvf zabbix-3.0.0.tar.gz  #解压缩

创建用户及组

1
2
shell> groupadd zabbix
shell> useradd -g zabbix zabbix

创建Zabbix数据库

1
2
3
4
5
6
7
8
9
shell> mysql -uroot -p<password>
mysql> create database zabbix character set utf8 collate utf8_bin;
mysql> grant all privileges on zabbix.* to zabbix@localhost identified by '<password>';
mysql> quit;
shell> cd database/mysql #在解压缩后的zabbix-3.0.0文件夹中
shell> mysql -uzabbix -p<password> zabbix < schema.sql
#如果你是为Zabbix Proxy来创建数据库,那么到这里就必须停止了,下面的不需要执行
shell> mysql -uzabbix -p<password> zabbix < images.sql
shell> mysql -uzabbix -p<password> zabbix < data.sql

编译安装Zabbix Server和Zabbix Agent

1
2
3
shell> ./configure --help #可以查看编译的参数项
shell> ./configure --enable-server --enable-agent --with-mysql --enable-ipv6 --with-net-snmp --with-libcurl --with-libxml2 #Zabbix Server与Agent安装参数参考
shell> make install

其他组件安装参考:

1
2
shell> ./configure --prefix=/usr --enable-proxy --with-net-snmp --with-sqlite3 --with-ssh2  #Zabbix Proxy安装参数参考
shell> ./configure --enable-agent #Zabbix Agent安装参数参考

编辑配置文件

如果Server与Agent采用了AIO(All In One)的部署方式,作为测试,Agent的配置文件可以不修改

接下来修改Server的配置文件

1
2
3
4
5
6
shell> vim /usr/local/etc/zabbix_server.conf
#以下为修改完成后的项目
#DBName和DBUser保持以下默认参数即可,只需设置DBPassword一项
DBName=zabbix
DBUser=zabbix
DBPassword=zabbix #上面配置数据时,我设置zabbix用户的密码为zabbix

启动服务

1
2
shell> zabbix_server  #启动Zabbix Server
shell> zabbix_agentd #启动Zabbix Agent

启动其他服务:

1
shell> zabbix_proxy  #启动Zabbix Proxy

安装Zabbix网站页面接口

1
2
3
shell> mkdir /var/www/html/zabbix
shell> cd frontends/php #在解压缩后的zabbix-3.0.0文件夹中
shell> cp -a . /var/www/html/zabbix

配置Zabbix

  • 在浏览器中打开如下网址: http://server_ip_or_name/zabbix

  • 在打开的页面中看到“Welcome to Zabbix 3.0”几个大字就算成功了一半了!点击Next stepWelcome

  • 第二个页面Check of pre-requisites 会检查PHP的一些配置参数(第一列是变量名;第二列是PHP配置文件实际值;第三项是Zabbix强制要求的最低值或固定值),默认情况下这个页面所有的检查项应该都是“OK”的,如果有红色的错误项,根据前面提示的变量名,去找PHP的配置文件,修改成“REQUIRED”要求的值就可以啦(默认PHP的配置文件/etc/php.iniCheck of pre-requisites

  • 第三个页面Configure DB connection 这一步骤会去尝试连接数据库。第一项数据库类型选择MySQL;DB Host 保持默认的localhost(因为这里采用了AIO的安装方式,数据库没有单独分离);DB Port修改成3306;DB Name:zabbix; User:zabbix;Password:zabbix。点击Next step如果出现报错,根据报错信息排查是否是配置错误(这些配置都是在前面设置过的,3306是MySQL默认的端口号)Configure DB connection

  • 第四个页面Zabbix server details 保持默认的Host:localhost和Port:10051配置即可,Name可以自定义设置,为这套监控系统起个名字Zabbix server details

  • 第五个页面Pre-installation summary 总览一下前面所有的配置Next stepPre-installation summary

  • 第六个页面Install 我在进入到这个页面后,出现了报错,提示Can not create the configuration file 下方官方也给出了手动解决这个问题的方法。按照提示,第一步点击给出的连接,下载zabbix官方提供的配置文件;第二步,根据提示,放在指定的位置保存为指定的文件,我这里提示保存为:/usr/share/zabbix/conf/zabbix.conf.php 按照提示操作完成后点击FinishInstall

  • 如果上面配置的都没有问题,第七个页面将会出现congratulations! ... 点击FinishInstall2

  • 第八个页面将会出现登陆页面,默认的登陆用户名为Admin 密码为zabbixlogin

Zabbix的使用简介

进入到Zabbix首页后,会发现3.0版本与之前的2.x版本的界面相比焕然一新,更养眼了,对解决2.x版本的审美疲劳起到了一定的作用。当然这只是最肤浅的外貌协会成员的结论,除了颜值高了,Zabbix还有50余项技术更新,变得愈发强大了~

  • Configuation–>Hosts–>status中,将Disabled变成Enabled状态,稍等片刻,如果Zabbix Agent启动正常的话,ZBX的图标就会亮起,表示Server与Agent之间通信正常Enabled
  • 监控首页会是如下状态(各个模块可以拖拽移动布局)Dashboard
  • 再瞅一眼监控图表的效果~Graphs1

那么问题来了,虽然3.0换了一层扁平简约的外观,但是图表展示还是一样的丑……为了解决这个问题,Grafana可以帮上大忙,接下来的部分就详细介绍如何使用Grafana给Zabbix监控图表披上一层华丽的外衣

RPM包安装方式


Grafana安装部分

截止至我写这篇文档的时候,Grafana的最新版本是2.6.0 而Grafana原生是不支持获取Zabbix数据的,需要通过grafana-zabbix插件来实现,grafana-zabbix插件的最新版本是2.5.1,github上写的很清楚,该插件服务于Grafana的2.5版本。经过测试,成功在2.6.0的Grafana上使用了grafana-zabbix的2.5.1版本。所以这里你可以任意选择2.5或2.6版本的Grafana来安装。

Grafana的下载及安装

1
2
3
shell> yum install https://grafanarel.s3.amazonaws.com/builds/grafana-2.6.0-1.x86_64.rpm  #这里只提供了yum的安装方式,其他安装方式可以参考附录中的Grafana官方安装文档
shell> service grafana-server start #启动Grafana服务
shell> chkconfig grafana-server on #添加开机自动启动

Grafana Zabbix插件的下载及安装

1
2
3
4
#https://github.com/alexanderzobnin/grafana-zabbix/releases/latest  #请到该网址下载2.5.1版本的grafana-zabbix插件
shell> tar -xvzf grafana-zabbix-2.5.1.tar.gz
shell> cp -r grafana-zabbix-2.5.1/zabbix/ /usr/share/grafana/public/app/plugins/datasource/
shell> service grafana-server restart

Grafana + Zabbix联通部分

  • 在浏览器地址栏输入 http://IP:3000就可以看到Grafana的登陆页面了。输入默认的用户名admin 密码admin登陆
  • 点击左侧的Data Sourses–>Add new
    • Type下拉框中选择Zabbix
    • Name 可以自由发挥~~
    • Http settings–>Url 填入http://zabbix-server-ip/zabbix/api_jsonrpc.php 这里填入的是Zabbix API接口
    • Http settings–>Access 选择 direct 使用直接访问的方式
    • Zabbix API details–>User 填入Admin
    • Zabbix API details–>Password 填入 zabbix
    • Save保存后再编辑,出现Test Connection按钮,点击可测试API配置是否正确。出现:Success Zabbix API version: 3.0.0 配置成功enter image description here

Grafana配置部分

至此仅差最后一步,将Zabbix的数据读取到Grafana来以图表展示,就打完收工啦!

  • 点击左侧的Dashboards–>Home–>在下拉菜单的底部选择+ New。这时新的页面中默认出现一个空的横行图表,左上角有绿色的竖线,右下角有+ ADD ROW添加新行的按钮。
  • 鼠标放在左上角的绿色竖线上,点击后弹出一个菜单,选择Add Panel。下面有五个选项,下面选择四个常用的分别介绍
  • 记得点击上面的保存按钮以保存新建的页面

Graph

这个选项是创建一个图表,类似于Zabbix的监控图表,是最常用的类型之一。

  • General-Title:设置该图表的名称
  • Metrics:在该项的右下角,选择正确的数据源(之前在Data Sources配置的Name)
  • Metrics-Group/Host/Application/Item:这些项目是必填项目,需要依次下拉选择

如果一张图需要展现两条线的数据,可以在左下角点击+ Query

  • Display Styles-Chart Options:这里可以选择以竖线展示,以折线展示或以来展示数据
    Grafana-Graph

Table

表格展示,类似于Excel表格的展现形式
enter image description here

  • 点击 - + 号可以调整该模块的大小(横向伸缩)
  • 点击Edit可以重新编辑该模块的数据源

Single stat

单统计模块,从字面意思就可以知道,该种模块仅可以展示一种数据,统计一种数据。这里需要重点说明就是Option选项下的参数

以统计磁盘使用大小一项来举例

  • Unit:要选择data下的bytes单位来统计
  • Decimals:小数设置保持默认的auto即可
  • Coloring:这里可以选择渲染背景色或字体色
    • Colors控制着三个颜色,可以自由发挥,一般绿色代表正常,黄色代表预警,红色代表警告
    • Thresholds可以设置以逗号分隔的三个数字,分别表示三个状态的阈值
    • Spark lines有两种显示模式,Show会在数据的下方展示折线;Background mode会在整个模块的背景展示折线

Text

这个模块很好理解,就是一个现实文字的模块,支持markdown语法,可以放在每个页面的头部,标记当前图表信息的归类。

Dashboards list

这个模块是用来展示页面列表用的。举个例子,如果一个监控系统中,涉及到了多个页面展示监控图表,就会用到这个功能,这个模块会列出你需要展示的页面的列表,方便在当前页面中,快速的切换到其他监控页面。

最终效果图

Final

页面自动刷新

点击右上角Last 6 hours, 在弹出的下拉框中,选择Time range下的Refreshing every选项,点击下拉框按钮,默认应该有off1m两个选项。点击1m 然后Apply设置。即为每一分钟刷新一次数据的意思。设置成功后,在原来Last 6 hours的后面会出现Refresh every 1m的橙色文字!


附录:参考文档

Zabbix 3.0官方文档

Remi官方文档

Grafana官方网站

Grafana官方安装文档

在使用yum安装php5.5的过程中,出现了如下依赖:
–> Finished Dependency Resolution
Error: Package: php-gd-5.4.45-4.el6.remi.x86_64 (remi)
Requires: libt1.so.5()(64bit)
通过yum provides 命令反查询后发现是由于缺少了t1lib这个软件包

1
2
3
4
5
6
7
8
shell> yum install --enablerepo=remi php php-gd
...
--> Processing Dependency: libt1.so.5()(64bit) for package: php-gd-5.4.45-4.el6.remi.x86_64
--> Finished Dependency Resolution
Error: Package: php-gd-5.4.45-4.el6.remi.x86_64 (remi)
Requires: libt1.so.5()(64bit)
You could try using --skip-broken to work around the problem
You could try running: rpm -Va --nofiles --nodigest

安装php的过程中出现了不可解决的依赖软件libt1.so.5()(64bit)

使用yum的反查询功能查出包含有这个库文件的软件包是哪一个
(在使用yum反查询后没有得到任何结果,后来排查得知是我yum的base repo设置有问题,导致yum读不到base中的软件库信息。多说一句,如果遇到以上问题,可以排查一下是不是服务器的base repo出现的问题,可以使用centos自带的centos-base.repo,也可以下载163的centos-base-163.repo库)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
shell> yum provides "*/libt1.so.5"
Loaded plugins: fastestmirror, refresh-packagekit, security
Loading mirror speeds from cached hostfile
* base: mirrors.yun-idc.com
* epel: mirrors.opencas.cn
* extras: mirrors.yun-idc.com
* remi-safe: mirror.innosol.asia
* rpmforge: mirrors.neusoft.edu.cn
* updates: mirrors.yun-idc.com
t1lib-5.1.2-6.el6_2.1.x86_64 : PostScript Type 1 font rasterizer
Repo : base
Matched from:
Filename : /usr/lib64/libt1.so.5

t1lib-5.1.2-6.el6_2.1.i686 : PostScript Type 1 font rasterizer
Repo : base
Matched from:
Filename : /usr/lib/libt1.so.5

接下来,解决这个问题只需yum install t1lib -y即可

Step1 修改配置文件

修改MySQL的配置文件(默认为/etc/my.cnf),在[mysqld]下添加一行skip-grant-tables

1
2
3
4
5
6
7
8
9
10
[root@PolarSnow hexo]# cat /etc/my.cnf 
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
character-set-server=utf8
innodb_file_per_table=1
skip-grant-tables

Step2 重启MySQL服务

service mysqld restart

Step3 再次进入MySQL命令行

mysql -uroot -p 输入密码时直接回车,就会进入MySQL数据库了

接下来按照常规流程修改root密码即可

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
52
53
54
55
56
57
[root@MasterDatabase ~]# mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 161391
Server version: 5.1.73-log Source distribution

Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| test |
| zabbix |
+--------------------+
4 rows in set (0.00 sec)

mysql> create user 'wordpress'@'%' identified by 'wordpress';
Query OK, 0 rows affected (0.00 sec)

mysql> create database wordpress;
Query OK, 1 row affected (0.01 sec)

mysql> grant all privileges on wordpress.* to 'wordpress'@'%';
Query OK, 0 rows affected (0.00 sec)


创建用户:
CREATE USER 'username'@'host' IDENTIFIED BY 'password';

CREATE USER 'username'@'192.168.5.9' IDENTIFIED BY 'password';
CREATE USER 'username'@'localhost' IDENTIFIED BY 'password';
CREATE USER 'username'@'%' IDENTIFIED BY '';
CREATE USER 'username'@'%';

授权:
GRANT privileges ON databasename.tablename TO 'username'@'host';

GRANT SELECT,INSERT ON DBname.tablename TO 'username'@'%';
GRANT ALL ON DBname.tablename TO 'username'@'%';
GRANT ALL ON DBname.* TO 'username'@'%';
GRANT ALL ON *.* TO 'username'@'%';
注意:使用以上命令授权的用户不能用来再给其他用户授权
如果想让该用户可以为其他用户授权,可以使用如下命令:
GRANT privileges ON databasename.tablename TO 'username'@'host' WITH GRANT OPTION;

设置/更改用户密码
SET PASSWORD FOR 'username'@'host'=PASSWORD('newpassword');
如果是修改当前登录的用户的密码,使用如下命令:
SET PASSWDORD=PASSWORD('newpassword')