首先创建一个触发器动作,触发报警会发送邮件
定义动作触发条件
定义动作执行的操作,这里是执行发送消息的操作,步骤1-5表示会发送5次消息,默认每次的间隔是30分钟
这里我们定义了1-5步执行的操作,就是每隔30分钟,将消息通过‘zabbix_send.py’这个脚本发送给Admin用户
如果问题两个小时之内没有确认,则会将在两个小时之后每隔十五分钟一次通知zabbix管理组,共发送两次消息
这里看到两个操作的步骤五重叠了,这里较短的自定义步骤持续时间为10分钟的会覆盖较长的步骤持续时间,也就是说第二个操作的5步骤会覆盖第一个操作的5步骤
定义恢复操作,问题解决之后会发送消息给Admin用户
定义更新操作,当其他用户更新问题时收到通知,比如问题被关闭,或者问题严重程度发生变化
到这里动作部分就完成了,如果要让其成功发送邮件,还需要配置用户和报警媒介
配置用户报警媒介
配置用户的收件人等信息
配置报警媒介类型,传入的三个参数分别为收件人,邮件主题,邮件内容
zabbix邮件报警的web界面配置完成了,还需要修改zabbix_server的配置文件,来支持使用脚本
vim /etc/zabbix/zabbix_server.confAlertScriptsPath=/usr/lib/zabbix/alertscripts
修改完成后重启zabbix-server
在/usr/lib/zabbix/alertscripts目录下添加要使用的报警脚本
并给邮件授予执行权限chmod +x zabbix_send.py
创建一个graph目录,并授予权限mkdir graph chmod 777 -R graph
邮件内容及详细注释如下: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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118#!/usr/bin/python
#coding=utf-8
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
import smtplib,sys,os,time,re,requests
from smtplib import SMTP
user='Admin' #定义zabbix用户名
password='zabbix' #定义zabbix用户密码
graph_path='/usr/lib/zabbix/alertscripts/graph' #定义图片存储路径
graph_url='http://192.168.179.132/chart.php' #定义图表的url
#api_url ="http://10.127.0.119/api_jsonrpc.php" #定义api的url
#header = {"Content-Type":"application/json" } #定义api的headers
loginurl="http://192.168.179.132/index.php" #定义登录的url
host='192.168.179.132'
to_email=sys.argv[1] #传入的第一个参数为收件人邮箱
subject=sys.argv[2] #传入的第二个参数为邮件主题
subject=subject.decode('utf-8')
smtp_host = 'smtp.163.com' #定义smtp主机地址
from_email = 'wanger@163.com' #定义发件人地址
mail_pass = 'asd1234' #发件人邮箱校验码
def get_itemid():
#获取报警的itemid
itemid=re.search(r'ITEM ID:(\d+)',sys.argv[3]).group(1)
return itemid
def get_graph(itemid):
#获取报警的图表并保存
session=requests.Session() #创建一个session会话
try:
loginheaders={
"Host":host,
"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"
}
#定义请求消息头
payload = {
"name":user,
"password":password,
"autologin":"1",
"enter":"Sign in",
}
#定义传入的data
login=session.post(url=loginurl,headers=loginheaders,data=payload)
#进行登录
graph_params={
"from" :"now-10m",
"to" : "now",
"itemids" : itemid,
"width" : "400",
}
#定义获取图片的参数
graph_req=session.get(url=graph_url,params=graph_params)
#发送get请求获取图片数据
time_tag=time.strftime("%Y%m%d%H%M%S", time.localtime())
graph_name='baojing_'+time_tag+'.png'
#用报警时间来作为图片名进行保存
graph_name = os.path.join(graph_path, graph_name)
#使用绝对路径保存图片
with open(graph_name,'wb') as f:
f.write(graph_req.content)
#将获取到的图片数据写入到文件中去
return graph_name
except Exception as e:
print e
return False
def text_to_html(text):
#将邮件内容text字段转换成HTML格式
d=text.splitlines()
#将邮件内容以每行作为一个列表元素存储在列表中
html_text=''
for i in d:
i='' + i + '<br>'
html_text+=i + '\n'
#为列表的每个元素后加上html的换行标签
return html_text
def send_mail(graph_name):
#将html和图片封装成邮件进行发送
msg = MIMEMultipart('related') #创建内嵌资源的实例
with open(graph_name,'rb') as f:
#读取图片文件
graph=MIMEImage(f.read()) #读取图片赋值一个图片对象
graph.add_header('Content-ID','imgid1') #为图片对象添加标题字段和值
text=text_to_html(sys.argv[3])
html="""
<html>
<body>
%s <br><img src="cid:imgid1">
</body>
</html>
""" % text
html=MIMEText(html,'html','utf-8') #创建HTML格式的邮件体
msg.attach(html) #使用attach方法将HTML添加到msg实例中
msg.attach(graph) #使用attach方法将图片添加到msg实例中
msg['Subject'] = subject
msg['From'] = from_email
try:
server=SMTP(smtp_host,"25") #创建一个smtp对象
server.starttls() #启用安全传输模式
server.login(from_email,mail_pass) #邮箱账号登录
server.sendmail(from_email,to_email,msg.as_string()) #发送邮件
server.quit() #断开smtp连接
except smtplib.SMTPException as a:
print a
def run():
itemid=get_itemid()
graph_name=get_graph(itemid)
send_mail(graph_name)
if __name__ =='__main__':
run()
当触发器达到阈值报警时,我们可以根据相关的报警来执行相关的命令使故障达到自我恢复的效果
这里我举一个ssh端口关闭并执行重启ssh的例子
在zabbix客户端配置文件中取消注释下面语句,以支持zabbix客户端执行远程命令
vim /etc/zabbix/zabbix_agentd.confEnableRemoteCommands=1
zabbix执行远程命令使用的是zabbix用户,确保’zabbix’用户具有已配置命令的执行权限。
vim /etc/sudoers1
2Defaults !requiretty #不需要提示终端登录
zabbix ALL=(ALL) NOPASSWD: ALL #允许'zabbix'用户在没有密码的情况下运行所有命令。
配置完成后,使用zabbix-get测试是否可以运行远程命令,如果返回数据,则表示远程命令可用
zabbix_get -s 192.168.179.132 -k “system.run[sudo df -h]”
vim /restart_ssh.sh1
2#/bin/bash
systemctl restart sshd
对脚本授予可执行权限chmod +x /restart_sshd.sh
创建动作
配置动作触发条件
配置动作执行的命令,这里为了方便查看效果,延迟两分钟执行
这里关闭ssh服务,使报警触发systemctl stop sshd
这里可以使用zabbix-get来获取监控的值。来查看是否成功执行命令
zabbix_get -s 192.168.179.132 -k net.tcp.port[192.168.179.132,22]
可以看到,zabbix已经成功执行脚本,重启ssh
具体脚本如下:
#!/usr/bin/python#coding=utf-8from email.mime.text import MIMETextfrom email.mime.multipart import MIMEMultipartfrom email.mime.image import MIMEImageimport smtplib,sys,os,time,re,requestsfrom smtplib import SMTPuser='Admin' #定义zabbix用户名password='zabbix' #定义zabbix用户密码graph_path='/usr/lib/zabbix/alertscripts/graph' #定义图片存储路径graph_url='http://192.168.179.132/chart.php' #定义图表的url#api_url ="http://10.127.0.119/api_jsonrpc.php" #定义api的url#header = {"Content-Type":"application/json" } #定义api的headersloginurl="http://192.168.179.132/index.php" #定义登录的urlhost='192.168.179.132'to_email=sys.argv[1] #传入的第一个参数为收件人邮箱subject=sys.argv[2] #传入的第二个参数为邮件主题 subject=subject.decode('utf-8')smtp_host = 'smtp.163.com' #定义smtp主机地址from_email = 'wanger@163.com' #定义发件人地址mail_pass = 'asd1234' #发件人邮箱校验码def get_itemid(): #获取报警的itemid itemid=re.search(r'ITEM ID:(\d+)',sys.argv[3]).group(1) return itemiddef get_graph(itemid): #获取报警的图表并保存 session=requests.Session() #创建一个session会话 try: loginheaders={ "Host":host, "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8" } #定义请求消息头 payload = { "name":user, "password":password, "autologin":"1", "enter":"Sign in", } #定义传入的data login=session.post(url=loginurl,headers=loginheaders,data=payload) #进行登录 graph_params={ "from" :"now-10m", "to" : "now", "itemids" : itemid, "width" : "400", } #定义获取图片的参数 graph_req=session.get(url=graph_url,params=graph_params) #发送get请求获取图片数据 time_tag=time.strftime("%Y%m%d%H%M%S", time.localtime()) graph_name='baojing_'+time_tag+'.png' #用报警时间来作为图片名进行保存 graph_name = os.path.join(graph_path, graph_name) #使用绝对路径保存图片 with open(graph_name,'wb') as f: f.write(graph_req.content) #将获取到的图片数据写入到文件中去 return graph_name except Exception as e: print e return Falsedef text_to_html(text): #将邮件内容text字段转换成HTML格式 d=text.splitlines() #将邮件内容以每行作为一个列表元素存储在列表中 html_text='' for i in d: i='' + i + '<br>' html_text+=i + '\n' #为列表的每个元素后加上html的换行标签 return html_textdef send_mail(graph_name): #将html和图片封装成邮件进行发送 msg = MIMEMultipart('related') #创建内嵌资源的实例 with open(graph_name,'rb') as f: #读取图片文件 graph=MIMEImage(f.read()) #读取图片赋值一个图片对象 graph.add_header('Content-ID','imgid1') #为图片对象添加标题字段和值 text=text_to_html(sys.argv[3]) html=""" <html> <body> %s <br><img src="cid:imgid1"> </body> </html> """ % text html=MIMEText(html,'html','utf-8') #创建HTML格式的邮件体 msg.attach(html) #使用attach方法将HTML添加到msg实例中 msg.attach(graph) #使用attach方法将图片添加到msg实例中 msg['Subject'] = subject msg['From'] = from_email try: server=SMTP(smtp_host,"25") #创建一个smtp对象 server.starttls() #启用安全传输模式 server.login(from_email,mail_pass) #邮箱账号登录 server.sendmail(from_email,to_email,msg.as_string()) #发送邮件 server.quit() #断开smtp连接 except smtplib.SMTPException as a: print adef run(): itemid=get_itemid() graph_name=get_graph(itemid) send_mail(graph_name)if __name__ =='__main__': run()
]]>yum install -y mailx
vim vim /etc/mail.rc
1
2
3
4
5set from=wang210@163.com #定义发件人
set smtp=smtp.163.com #定义smtp服务器
set smtp-auth-user=wang210@163.com
set smtp-auth-password=asdASD123
set smtp-auth=login
echo 'test1'|mail -s "testmail" wang210@126.com
vim /usr/lib/zabbix/alertscripts/mail.sh
这是zabbix默认的脚本路径,可以通过zabbix_server配置文件修改1
2
3
4
5#/bin/bash
to=$1
subject=`echo $2|tr '\r\n' '\n'`
message=`echo $3|tr '\r\n' '\n'`
echo "$message"|mail -s "$subject" $to >>/var/log/mailx.log 2>&1
touch /var/log/mailx.log
chown -R zabbix.zabbix /var/log/mailx.log
chmod +x /usr/lib/zabbix/alertscripts/mail.sh
./mail.sh wang210@126.com “主题” “内容”
脚本参数的变量全为大写,是zabbix内置的宏
更多关于zabbix的宏可以查看 官方文档宏的介绍
除了使用脚本媒介,也可以使用email作为媒介,相比之下,使用email更简单
操作,恢复操作,或者更新操作必须存在一个
可以根据自己的需要配置触发条件
默认标题:
1 | {TRIGGER.STATUS}:{TRIGGER.NAME} |
消息内容:
1 | 报警主机:{HOST.NAME} |
默认标题:
1 | {TRIGGER.STATUS}:{TRIGGER.NAME} |
消息内容:
1 | 恢复主机:{HOST.NAME} |
systemctl stop zabbix_agent
systemctl start zabbix_agent
配置微信报警需要注册企业微信
点击‘我的企业’到最下面获取
单击应用与小程序,选择下面的创建应用,应用名字自己随便起,最好有象征意义
然后打开新创建的应用,记录下AgentID和Secret
1 | git clone https://github.com/X-Mars/Zabbix-Alert-WeChat.git |
使用pip安装,需要先下载pip1
python get-pip.py
安装requests库1
pip install requests
Corpid,Secret,Agentid填写自己企业微信的信息,修改这三个参数即可,当然也可以选择使用标签ID,部门ID,取消注释即可
修改完成后测试脚本是否可用1
2python wechat.py 企业微信ID test text
{u'invaliduser': u'', u'errcode': 0, u'errmsg': u'ok'}
收件人填写企业微信的用户ID
消息内容与标题与邮件报警配置相同,只要把发送的媒介通过WeChat发送即可
恢复操作也是把媒介改成通过WeChat发送
重启虚拟机测试,企业微信收到邮件
]]>函数是python为了代码最大程度的重用和最小化代码冗余而提供的最基本的程序结构。函数也是一种设计工具,使用函数,我们也可以把复杂的系统分解为可管理的部件
函数的相关语句和表达式
语句 | 例子 |
---|---|
Calls | my_function(‘Fir Arg’,’Sec Arg’) |
def | def myfunction(fir_arg,sec_arg): |
return | return fir_arg+sec_arg |
global | global x;x=new_value |
nonlocal | nonlocal x;x=new_value |
yield | def my_sqr(x): for i in range(x): yield i **2 |
lambda | funcs=[lambda x: x*2,lambda x:x3] |
def是可执行的代码。在python里,只有def执行之后,才会生成相应的函数。要是def没有执行,相应的函数就不会生成。def语句在if、while语句甚至是其他def语句里也是合法的。
def语句将创建一个函数并将其赋值给一个变量名:
def <变量名>([参数1,参数2,…]):
<语句>
def语句的首行定义函数名,并引用函数对象,函数名的本质就是函数的内存地址。
参数个数是0或以上数目。
语句里,可以包含return语句,在调用函数时,会返回一个值。当没有return时,默认返回值为None。
函数里,也可以使用yield语句来生成返回值。
因为def是执行语句,因此函数是实时生成的
1 | def hanshu(x,y): |
在这个函数里,x*y的结果取决于x和y的对象类型,因为python本身不定义变量,因此传递的值的类型与返回的类型都不一定是固定的类型。
作用域针对的是变量。在使用同一个变量名时,会出现作用域问题。
1 | 10 #全局变量 x= |
变量名使用时,查找顺序:
1 | def newdef(): |
在函数内,想改变全局变量,可以使用global语句来定义此变量为全局变量。
1 | 'global' g= |
被嵌套函数的作用域就是上级函数,在这里,想调用inner函数,必须是在函数outer里面,不能直接使用。可以使用返回内部函数的方法来提取内部函数:
1 | def outer(): |
工厂函数:根据要求的对象,一个能够记住嵌套作用域的变量值的函数。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
30def printx(x):
def printy(y): #嵌套函数
return x*y #返回x*y的值
return printy #返回嵌套的函数
3) #定义x值为3后的嵌套函数赋值 a=printx(
2) a(
6
3) a(
9
```
#### nonlocal语句
nonlocal让内部函数中的变量在上一层及以下层函数中生效(父级级父级以下)
```python
x=1
def func1():
x=2
def func2():
nonlocal x
x=3
return x
func2()
print(x)
func1()
3
x
1
因为x并不是全局变量,所以只有在调用函数时nonlocal语句才会生效,这里x=3,当直接输出x而不调用函数时那么x=1
参数:argement或parameter,对象作为输入值传递给函数的方式。
参数传递时的简要关键点:
传递参数为可变对象与不可变对象时:
不可变对象通过值进行传递——数值、字符串等
可变对象是通过指针进行传递——列表、字典等
1 | 3 a= |
在这里,b[:]方式会新生成一个列表对象,因此函数里的y与setlist(b[:])是两个不同的对象。这种方法可以避免可变参数的修改。1
2
3
4
5
6
7
8
9
10def setlist(y):
y.append(3)
1,2] a=[
setlist(a[:])
a
[1, 2]
setlist(a)
a
[1, 2, 3]
参数传递是由特定匹配规则的:
传递参数时,要注意顺序:非关键字参数->关键字参数->字典参数
1 | def myfunc(a,b): |
语法 | 位置 |
---|---|
func(value) | 调用者 常规参数:通过位置进行匹配 |
func(name=value) | 调用者 关键字参数:通过变量名匹配 |
func(*sequence) | 调用者 迭代传递所有元素 |
func(**dict) | 调用者 以‘键’为关键字,‘值’为相应值的方式传递字典所有元素 |
def func(name) | 函数 常规参数:通过位置或变量名进行匹配 |
def func(name=value) | 函数 默认参数值:如果没有在调用中传递的话 |
def func(*name) | 函数 匹配并收集(在元组中)所有包含位置的参数 |
def func(**name) | 函数 匹配并收集(在字典中)所有包含关键字的参数 |
def func(*arg,name) | 函数 参数必须在调用中按照关键字传递 |
常规参数函数用法:1
2
3
4
5
6def myfunc(a,b):
result=a+b
print(result)
1,2) myfunc(
3
关键字参数函数:
1 | def myfunc(a,b): |
迭代传递参数用法:1
2
3
4
5
6def myfunc(a,b,c):
result=a+b+c
print(result)
1,2,3]) myfunc(*[
6
在字典中匹配所有参数用法:1
2
3
4
5
6
7
8def myfunc(a,b,c):
result=a+b+c
print(result)
'a':1,'b':2,'c':3}) myfunc(**{
6
1,**{'b':2,'c':3}) myfunc(
6
默认参数函数用法:1
2
3
4
5
6
7def myfunc(a,b=3):
print(a+b)
#当有默认参数存在时,可以只传入其他的参数
3) myfunc(
6
3,2) myfunc(
5
可变参数函数用法:
可变参数,可以传递任意个参数
*args方式是把所有常规参数调用与迭代调用放进一个元组里:1
2
3
4
5
6
7
8def myfunc(*a):
result=''.join(a)
print (result)
'1,','2,','3') myfunc(
1,2,3
'first,',*['second,','third']) myfunc(
first,second,third
**args方法是把任意个关键字参数与字典调用方式存放在变量名为args的字典里1
2
3
4
5
6
7def myfunc(**a):
print(a)
'1',b='2') myfunc(a=
{'a': '1', 'b': '2'}
'1',b='2',**{'c':'3'}) myfunc(a=
{'a': '1', 'b': '2', 'c': '3'}
必须使用关键字传递的方法:
函数里的参数:
常规——有/无默认值
args——存放在列表
**args——存放在字典
在python3开始,在args与args中间可以加入一个“必须使用关键字传递的参数”
使用方法为是0个或多个常规参数+或args+“必须使用关键字传递的参数”+0个或1个args。1
2
3
4
5
6
7
8
9
10def myfunc(*,b,**c):
print(b,c)
'b':4}) myfunc(**{
4 {}
def myfun(*a,b,**c):
print(a,b,c)
2,**{'b':4,'c':5}) myfun(
(2,) 4 {'c': 5}
特殊参数的传递:
在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
28#这是一个求最小值的函数
def min1(*a):
reg=a[0]
for i in a[1:]:
if i <reg:
reg=i
print(reg)
2,3,5,1,6,8) min1(
1
#这里将最大和最小值的函数作为参数传入到求最大和最小值的函数里
def lessthan(x,y):
return x<y
def morethan(x,y):
return x>y
def minmax(test,*args):
res=args[0]
for i in args[1:]:
if test(i,res):
res=i
print(res)
2,3,5,1,6) minmax(lessthan,
1
2,3,5,1,6) minmax(morethan,
6
1 | def mysum(s): |
嵌套列表里面的值相加1
2
3
4
5
6
7
8
9
10
11
121,2,[3,4,5],6,[7,[8,9],10]] li=[
def sumlist(a):
sum=0
for i in a:
if not isinstance(i,list): #判断遍历的i是否是列表
sum += i
else:
sum += sumlist(i)
return sum
sumlist(li)
55
在python里函数也是以对象的形态出现。函数名也是以变量名形式存放。因此函数也可以跨模块,以参数传递等形式。函数对象也能调用根本无关的操作:属性存储与注释。
间接函数调用:1
2
3
4
5
6def func(x):
print(x)
func2=func
2) func2(
2
把函数放进列表或元组里:1
2
3
4
5
6
7
8
9
10
11
12
13def myfunc(func_name,arg1):
func_name(arg1)
def func_name(arg1):
print (arg1)
1),(func_name,2),(func_name,3)] li=[(func_name,
for i in li:
myfunc(i[0],i[1])
1
2
3
lambda会生成函数对象,但不赋值给任何变量。
lambda表达式:
lambda [<arg1>
][,<arg2>
][,<arg3>
]….:expression using args
参数不是必须的,但没有参数就没有相对意义。
lambda简单说明:
lambda是一个表达式,而不是一个语句,也不是一个的代码块。——生成一个对象。1
2
3
4
5lambda a:a*2 myfunc=
4) myfunc(
8
lambda a,b:a*b)(5,4) (
20
当我们把函数对象放进列表里等操作的时候,使用def感觉很臃肿,这时可以使用lambda来简化过程。1
2
3
4
5
6
7lambda x: x**2, funclist=[
lambda x: x**3,
lambda x: x**4]
0](2) funclist[
4
1](3) funclist[
27
使列表中的每个值都加101
2
31,2,3,4] l=[
lambda x: x+10,l)) list(map(
[11, 12, 13, 14]
filter与map相似,但是针对返回的bool结果判断,结果为真,保留元素;结果为假,弃用元素。结果也是保存在可迭代对象里:1
2lambda x: x>1,[-1,0,1,2,3,4,5])) list(filter(
[2, 3, 4, 5]
reduce函数是在functools模块里的,因此我们需要导入这个函数。
这个方法是第一次从可迭代对象里提取两个元素当作函数的参数传入,按前面的函数进行运算,保存返回值,当可迭代对象里还有元素的时候,之前的返回值为第一个参数,可迭代对象里取下一个继续运算,知道可迭代对象空。最后返回函数的返回值。1
2
3
4
5from functools import reduce
lambda x,y: x+y,[1,2,3,4]) reduce(
10
lambda x,y:x if x>y else y,[3,5,2,6,7,4,1,9]) reduce(
9
1 | rpm -ivh https://repo.zabbix.com/zabbix/4.0/rhel/7/x86_64/zabbix-release-4.0-1.el7.noarch.rpm |
1 | yum install zabbix-server-mysql |
1 | rpm -qa |grep mariadb #查看当前安装的mariadb的包 |
1 | wget https://dev.mysql.com/get/archives/mysql-5.7/mysql-5.7.21-linux-glibc2.12-x86_64.tar.gz #从官网下载源码包 |
1 | groupadd mysql --创建mysql用户组 |
1 | cat >>/etc/my.cnf <<EOF #写入配置文件 |
1 | touch /var/log/mysqld.log #创建日志文件并授权 |
1 | cat /var/log/mysqld.log|grep root@localhost |
1 | mkdir /var/run/mysqld |
vim /etc/my.cnf #修改配置文件1
2
3
4
5
6
7
8skip-grant-tables #跳过密码认证
default_password_lifetime=360 #修改密码超时时间
不然修改密码之后密码会过期,会提示让你重新设置密码
You must reset your password using ALTER USER statement before executing this statement.
/usr/local/mysql/bin/mysql -uroot -p #登录MySQL
use mysql #切换MySql数据库
update mysql.user set authentication_string =password('root'), host = '%' where user = 'root'; #修改MySQL密码
flush privileges;
1 | echo 'PATH=/usr/local/mysql/bin:$PATH' >>/etc/profile #将MySQL二进制文件加入环境变量 |
1 | mysql> create database zabbix character set utf8 collate utf8_bin; |
修改以下参数为创建数据库时的信息,并重启zabbix-server
vim /etc/zabbix/zabbix_server.conf1
2
3
4
5
6DBName=zabbix
DBHost=192.168.179.132
DBUser=zabbix
DBPassword=zabbix
systemctl enable zabbix-server
systemctl start zabbix-server
启动的时候启动失败,查看系统日志,查找关键词1
usr/sbin/zabbix_server: error while loading shared libraries: libmysqlclient.so.18: cannot open shared object file: No such file or directory
原来是缺少一个文件,yum安装解决yum -y install mysql-libs
1 | zcat /usr/share/doc/zabbix-server-mysql*/create.sql.gz | mysql -uzabbix -p zabbix |
1 | systemctl stop firewalld |
1 | yum -y install wget vim lsof lrzsz pcre-devel zlib-devel make gd-devel libjpeg-devel libpng-devel libxml2-devel bzip2-devel libcurl-devel libmcrypt libmcrypt-devel mcrypt mhash net-snmp-devel |
1 | cat >>/etc/yum.repos.d/nginx.repo <<EOF |
1 | nginx -t 测试配置是否有错 |
useradd -s /sbin/nologin php-fpm
1 | yum install -y gcc gcc-c++ make zlib zlib-devel pcre pcre-devel libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel libxml2 libxml2-devel glibc glibc-devel glib2 glib2-devel bzip2 bzip2-devel ncurses ncurses-devel curl curl-devel e2fsprogs e2fsprogs-devel krb5 krb5-devel openssl openssl-devel openldap openldap-devel nss_ldap openldap-clients openldap-servers |
1 | wget http://mirrors.sohu.com/php/php-7.2.6.tar.gz |
1 | sed -i 's/post_max_size = 8M/post_max_size = 32M/g' /usr/local/php/etc/php.ini |
1 | cp /usr/local/php/etc/php-fpm.conf.default /usr/local/php/etc/php-fpm.conf |
vim phpinfo.php1
2
3<?php
phpinfo();
?>
测试是否能连接nginx,这里出现一个错误,访问动态页面一直显示文件没有发现,修改nginx配置文件的PHP脚本路径变量和修改文件权限后一直没有用,后来我将路径的变量去掉,添加网站真实路径后解决
1 | yum install zabbix-agent |
1 | cp -r /usr/share/zabbix/.* /usr/share/nginx/html/ |
egrep -v ‘(^.*#|^$)’ /etc/nginx/conf.d/default.conf1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18server {
listen 80;
server_name 192.168.179.132;
access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm index.php;
}
error_page 404 /404.html;
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html$fastcgi_script_name;
include fastcgi_params;
}
}
重启nginx访问会报这个错
百度之后得知是权限不足引起的,运行一下命令可以解决,这里一定要777,不然到时候安装完成不能创建配置文件1
chmod -R 777 /etc/zabbix/web
在访问浏览器的时候不出图,请教我学长之后得出是因为nginx上配置了图片缓存,去掉缓存解决
安装完成可能会遇到连接不上zabbix-server的错误,查看zabbix-server日志如下,这个解决方法有两种,第一种就是创建一个mysql.sock然后重启mysql服务器1
2mkdir /var/lib/mysql
ln -s /tmp/mysql.sock /var/lib/mysql/mysql.sock
第二种就是编辑zabbix_server.conf文件,将DBSocket修改为自己数据库的mysql.sock,然后重启 zabbix_server
监控CPU idle
基本就是图形界面,创建监控项之前先测试一下key值是否可用,当然需要安装zabbix_get工具,使用yum install zabbix-get来安装1
zabbix_get -s 192.168.179.132 -k system.cpu.util[all,idle,avg1]
监控磁盘IO利用的工具是iostat
yum install -y sysstat
编辑zabbix-agent的配置文件
vim /etc/zabbix/zabbix_agentd.d/userparameter.conf1
UserParameter=disk.status[*],/usr/local/zabbix/scripts/disk-status.sh $1
vim /usr/local/zabbix/scripts/disk-status.sh1
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
if [ $# -ne 1 ];then
echo "Follow the script name with an argument"
fi
case $1 in
rrqm)
iostat -dxk 1 1|grep -w sda |awk '{print $2}'
;;
wrqm)
iostat -dxk 1 1|grep -w sda |awk '{print $3}'
;;
rps)
iostat -dxk 1 1|grep -w sda|awk '{print $4}'
;;
wps)
iostat -dxk 1 1|grep -w sda |awk '{print $5}'
;;
rKBps)
iostat -dxk 1 1|grep -w sda |awk '{print $6}'
;;
wKBps)
iostat -dxk 1 1|grep -w sda |awk '{print $7}'
;;
avgrq-sz)
iostat -dxk 1 1|grep -w sda |awk '{print $8}'
;;
avgqu-sz)
iostat -dxk 1 1|grep -w sda |awk '{print $9}'
;;
await)
iostat -dxk 1 1|grep -w sda|awk '{print $10}'
;;
svctm)
iostat -dxk 1 1|grep -w sda |awk '{print $13}'
;;
util)
iostat -dxk 1 1|grep -w sda |awk '{print $14}'
;;
*)
echo -e "\e[033mUsage: sh $0 [rrqm|wrqm|rps|wps|rKBps|wKBps|avgqu-sz|avgrq-sz|await|svctm|util]\e[0m"
esac
touch +x /usr/local/zabbix/scripts/disk-status.sh #给脚本添加执行权限
浏览器打开192.168.179.132/index.php
依次点击配置——>模板——>创建模板
添加模板名称以及群组,最后点击添加
在创建的模板上点击创建应用集,名字最好与磁盘io相关
这里所有的数据类型都是浮点数
这需要为每一个监控项都创建图形
点击需要监控的主机,然后单击模板,为主机添加模板链接
可以看到我收集到的图形是乱码的
首先查看zabbix字体目录,它定义的路径是“fonts”,它是一个相对路径,绝对路径为/usr/share/zabbix/fonts,
vim /usr/share/zabbix/include/defines.inc.php //搜索ZBX_FONTPATH
而字体文件为“ZBX_GRAPH_FONT_NAME”所定义的“graphfont”,它是一个文件,绝对路径为/usr/share/zabbix/fonts/graphfont.ttf
我们可以从Windows系统中选择一个中文字体然后放到zabbix的字体目录下
Windows字体目录位于C:\Windows\Fonts下,找到仿宋常规字体将他拷入zabbix字体目录下
然后修改PHP文件,将字体文件修改为simsong
1 | yum install java #elastic需要安装Java依赖 |
vim /root/elasticsearch-6.1.4/config/elasticsearch.yml #主要修改es的一些配置信息
启动过程出现的报错1
[WARN ][o.e.b.BootstrapChecks ] [PWm-Blt] max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536]
解决办法:
vim /etc/security/limits.conf1
2
3
4* soft nofile 65536
* hard nofile 131072
* soft nproc 2048
* hard nproc 4096
1 | [WARN ][o.e.b.BootstrapChecks ] [PWm-Blt] max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144] |
解决办法:
vim /etc/sysctl.confvm.max_map_count=655360
修改完成执行命令:
sysctl -p
cd elasticsearch-6.1.4/bin
这里不能使用root用户运行elastic,可以自己新建一个普通用户,还要把目录授予普通用户权限
./elasticsearch
然后我们可以打开浏览器输入192.168.179.133:9200可以查看es的状态,或者可以装一个head插件
这里我采用的源码安装,其实二进制安装是比较简单的,但我执行到最后node的二进制文件无法执行,因此只能源码安装,时间有点长,打了两局王者荣耀才装完1
2
3
4
5
6yum groupinstall "Development Tools" #安装编译必要的工具
wget https://nodejs.org/dist/v8.11.4/node-v8.11.4.tar.gz #下载node的源码包
tar -zxvf node-v8.11.4.tar.gz #解压源码包
cd node-v8.11.4
./configure && make && make install #执行编译安装
echo $? #查看执行结果,输出0表示安装成功
node.js默认安装路径在/usr/local/bin/目录下
grunt是基于Node.js的项目构建工具,可以进行打包压缩、测试、执行等等的工作,head插件就是通过grunt启动npm install -g grunt-cli
1 | git clone git://github.com/mobz/elasticsearch-head.git #克隆head插件仓库 |
vim /elasticsearch/elasticsearch-6.4.0/config/elasticsearch.yml1
2http.cors.enabled: true # elasticsearch中启用CORS
http.cors.allow-origin: "*" # 允许访问的IP地址段,* 为所有IP都可以访问
npm run start #启动head插件
在浏览器输入http://192.168.179.133:9100/ 即可使用head插件
添加如下内容1
2
3HistoryStorageURL=192.168.179.133:9200
HistoryStorageTypes=str,text,log,uint,dbl
HistoryStorageDateIndex=1
添加如下内容1
2
3
4global $DB, $HISTORY;
$HISTORY['url'] = 'http://192.168.179.133:9200';
// Value types stored in Elasticsearch.
$HISTORY['types'] = ['str', 'text', 'log','uint','dbl'];
systemctl restart zabbix-server
至此,es收集zabbix历史数据完成
语句 | 角色 | 例子 |
---|---|---|
赋值 | 创建引用值 | a=’Apple’,b=’bike’ |
调用 | 执行函数 | log.write(‘mylog’) |
打印调用 | 打印对象 | print(1,’hello’) |
if/elif/else | 选择动作 | if a in b: print(a) |
for/else | 序列迭代 | for i in list: print(i) |
while/else | 一般循环 | while True: print(‘True’) |
pass | 空占位符 | for i in list: pass |
break | 循环/迭代退出 | while True:if a==b: break |
continue | 循环继续 | for i in list: if i<5: continue |
def | 函数定义 | def add(a,b): print(a+b) |
return | 函数返回 | def add(a,b): return a+b |
import | 模块访问 | import os |
from | 属性访问 | from sys import stdin |
class | 创建类 | class myclass(): def myprint(): print(‘myprint’) |
try/except/finally | 捕获异常 | try: open(‘/tmp/file’) except: print(‘no file’) |
raise | 触发异常 | raise <’error type’> |
assert | 调试检查 | assert a<0,’a is too large’ |
with/as | 环境管理器 | with open(file) as f: f.read() |
del | 删除引用 | del_list[i] del_list[i:j] del obj.attr |
在python里是不使用{}或者别的符号来限制语句的开始和结尾的,一个语句的开始(除了复合语句),就是开头,换行就是结束。在开头,不能随意增加空格:1
2
3
4
5
6
7print (1)
1
print (1)
File "<stdin>", line 1
print (1)
^
IndentationError: unexpected indent
在复合语句里也是同样的,当你使用缩进时,必须一致:1
2
3
4
5
6
7def add(str):
str=str
print(str)
File "<stdin>", line 3
print(str)
^
IndentationError: unindent does not match any outer indentation
复合语句有单行写法和多行写法。从冒号后面就是复合语句的开始。
单行:复合语句只有一行时,可使用单行写法,但是复合语句所包含的语句不是单行时,需要使用对齐的缩进来表示复合语句1
2
3
4
5
6
7
8
9
10#单行语句
if 1>0: print(1)
...
1
#多行语句
if 1>0:
1 int=
print(int)
...
1
一般语句里,一行的结束就是此语句的结束。
在简单语句可以使用分号来隔开多个语句。1
23;b=3;print(a+b) a=
6
使用列表,元组,字典的时候按照一定的方式可以把一个语句分成多行:1
21:'first', dict={
2:'second'}
当我们所写的语句有bug,会出现一些错误,程序会中断运行。
但我们在这个时候,不想让程序中断但还是需要提示报错的时候可以使用try:1
2
3
4
5
6
7
8
9
10
11
12
13while True:
_input=input("please input digit:")
try:
print("{:d} *10 is {:d}".format(int(_input),int(_input)*10))
break
except:
print("{} is not a number".format(_input))
please input digit:a
a is not a number
please input digit:1
1 *10 is 10
变量名可以使大小写字母,数字和下划线,但只能以大小写字母和下划线开头,不能以数字开头。变量名是区分大小写的,保留字符是不能使用的。
python3.0里的保留字符:
false class finally is
None continue for lambda
True def from nonlocal
and del dlobal not
as elif if or
assert else import pass
break except in raise
特殊变量名:
main等,前后都有两个下划线的变量名,有很多是有特殊意义的
从python3.0开始print变成了函数,但返回值为None,print函数的格式如下:
print([object,…][,sep=’’][,end=’\’][file=sys.stdout])
在这里,object是要打印的内容。object可以是任意对象。默认是没有。
sep是两个object之间隔开的字符。默认是一个空格。
end是结尾,默认为换行。
file为输出目标,默认为标准输出流。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17>> print(1,2,3,sep=';')
1;2;3
1,2,3,sep=':') print(
1:2:3
1,2,3,end='') print(
1 2 3
1,2,3,end='');print (4,5,6,end='') print(
1 2 34 5 6
1,2,3,end='\n');print (4,5,6,end='') print(
1 2 3
4 5 6
1,2,3,file=open(r'D:\ruanjian\1.txt','wt')) print(
r'D:\ruanjian\1.txt') file=open(
file.read()
'1 2 3\n'
在if语句里的<’test’>位置里的就是判断语句,结果为True,就能进入子语句,判断语句包含:
1 | 1<2 |
当我们使用and和or的时候,返回结果不一定是True或False:
and:当其中一个或多个测试值为false的时候,取第一个false的值1
2
3False
1 and [] and {}
[]
and:当全部值得测试值为True的时候,取最后一个值1
2
3
4
5
61 and 2 and True
True
1 and 2 and True
True
1 and 2 and True and 3
3
or:当其中一个或多个值为True的时候,取第一个True的值1
2
3
40 or [1] or {1:'1'}
[1]
1 or 0 or 2
1
or:当全部值为false的时候,去左后一个false值1
2
3
40 or [] or {}
{}
False or 0 or {}
{}
三元表达式的格式如下:
<’value1’>if <’’test’> else <’value2’>
当测试值为真的时候取<’value1’>,假的时候取<’value2’>1
2
3
4
5
6
7
81 if True else 2
1
1 if False else 2
2
'True' if 1>2 else 'False'
'False'
'True' if 1<2 else 'False'
'True'
这个还可以如下运用:
[<’value2’>,<’value1’>][<’test’>]1
2
3
4
5
6
7
82,1][True] [
1
2,1][False] [
2
'False','True'][1>2] [
'False'
'False','True'][1<2] [
'True'
whil语句一般格式:1
2
3
4while <'test1'>:
<'statement1'>
else:
<'statement2'>
只要测试语句为真,会一直循环<’statement1’>。当test1为假的时候会运行else语句里的内容。从这里,退出循环的方法有:
1.在<’statement1’>里的语句更改<’test1’>的结果为False
2.在<’statement1’>里的语句里增加break语句来跳出循环
3.在<’statement1’>里的语句里增加exit()来退出python循环,不过这里会退出整个的python程序
例子1
2
3
4
5
60;b=10 a=
while a<b:
print(a,end='')
a+=1
0123456789
break语句用来退出最近所在的for语句或while语句。
continue语句是用来跳到最近所在的for语句或者while语句的结尾。1
2
3
4
5
6
7
80;b=10 a=
while a<b:
a+=1
if a==3: continue
if a ==7: break
print (a,end='')
12456
pass语句是占位的空语句,在有些复合语句里,可能没有具体的语句,但需要正常运行,这就需要设置空语句(pass)来代替
例子1
2
3
4
5if True:
print('true')
else: pass
true
else语句,只有在for语句和while语句正常结束后,会运行:1
2
3
4
5
6
7
80;b=10 a=
while a<b:
print(a,end='')
a+=1
else:
print('end')
0123456789end
for语句在python里是一个通用的序列迭代器:可以遍历任何有序的序列对象内的元素。可用于字符串、列表、元组、其他内置可迭代对象以及之后我们能通过类所创建的新对象。
一般格式:1
2
3
4for <target> in <object>:
<statements>
else:
<statements>
在这里object需是可迭代的对象。每次从object里提取一个元素付给target,之后循环statements里的语句。
例子1
2
3
4for i in a:
print (i,end='')
12345
使用for循环时,其他开发语言会使用一个变量,定义起始,结束,递增值。但python里只能做迭代。这个时候可以使用range函数来代替。
range函数格式:
range([起始值,]结束值,[递增值])
在这里,起始值默认是0,递增值默认为1。1
2
3
4
510) a=range(
for i in a:
print(i,end='')
0123456789
当迭代后的元素为固定长度的元组。列表的时候:1
2
3
4
5
6for a,b,c in [(1,2,3),(4,5,6),(7,8,9)]:
print (a,b,c)
1 2 3
4 5 6
7 8 9
嵌套循环(不一定是固定长度):1
2
3
4
5
6
7
8for l in [(1,2,3),(4,5,6),(7,8,9)]:
for i in l:
print(i,end='')
print()
123
456
789
文件访问方式如下:
__next__()
报错为stoplteration。在python中任何这类对象都认为是可迭代的。在python里迭代工具(比如for)会调用__next__()
来获取数据,并以stoplteration来确认何时离开。
尽量不要使用readlines()函数,因为这个会一次性得把所有内容读取到内存里(转换为列表),运行速度会比较慢。
为了支持手动迭代代码,python支持next()函数,它会自动读取__next__()
函数。
next(X)等同于X.__next__()
。1
2
3
4
5
6
7
8
9
10
11
12r'D:\ruanjian\1.txt') file=open(
file.__next__()
'hello,world'
0) file.seek(
0
next(file)
'hello,world'
next(file)
Traceback (most recent call last):
File "<pyshell#135>", line 1, in <module>
next(file)
StopIteration
这个会从第一行开始读取内容,但是这个文本文件就一行,所以读完之后再读会报错。
迭代协议里,当时用for函数进行迭代时,会传递给iter()内置函数,以便可迭代对象中获取迭代器。返回的对象中有next()方法1
2
3
4
5
6
7
8
9
10
11
12
131,2,3] li=[
i=iter(li)
next(i)
1
next(i)
2
next(i)
3
next(i)
Traceback (most recent call last):
File "<pyshell#141>", line 1, in <module>
next(i)
StopIteration
对于文件来说,不需要转换成iter类型的这一步,
因为文件对象就是自己的迭代器。1
2
3r'D:\ruanjian\1.txt') file=open(
is iter(file) file
True
但列表,元组,字符串就不是了。1
2
3
4
5
6
7'123';l=[1,2,3];t=(1,2,3) s=
is iter(s) s
False
is iter(l) l
False
is iter(t) t
False
如果要使用next方法就需要先将字符串,列表,元组转换成迭代器
除了文件以及像列表这样的实际的序列外,其他类型也有其适用的迭代器。例如,遍历字典键的经典方法是明确的获取其键的列表。1
2
3
4
5
6
7'a':1,'b':2,'c':3} dic={
for key in dic.keys():
print(key,dic[key])
a 1
b 2
c 3
这个迭代器也可以直接对字典进行迭代:1
2
3
4
5
6
7 iter1=iter(dic)
iter1.__next__()
'a'
next(iter1)
'b'
next(iter1)
'c'
遍历列表时,使用for循环来修饰它:1
2
3
4
5
61,2,3,4,5] li=[
for i in range(len(li)):
li[i]+=10
li
[11, 12, 13, 14, 15]
但这样看来并不简便,我们可以使用产生所需列表的一个单个表达式来完成上面的循环1
2
3
41,2,3,4,5] li=[
10 for i in li ] li=[i+
li
[11, 12, 13, 14, 15]
这个先是运算[i+10 for i in li]之后,再把此值赋给li,具体的运算是先是对li进行迭代,每次把单个值赋给i,在进行i+10,成为新列表的单个元素。
我们可以使用如下方法,将列表的某一项排除1
2
3
41,2,3,4,5] li=[
10 for i in li if i != 3] li=[i+
li
[11, 12, 14, 15]
也可以在列表中进行循环嵌套,可以看到y的循环嵌套在了x循环里1
2for x in [1,2,3] for y in [10,20,30]] [x+y
[11, 21, 31, 12, 22, 32, 13, 23, 33]
map也可用在迭代1
2r'D:\ruanjian\1.txt'))) list(map(str.upper,open(
['HELLO,WORLD']
map函数是把后面的可迭代的每个值当做前面的参数传入。
上面的语句可以如下解释:1
2
3
4
5
6 tmp=[]
for line in open(r'D:\ruanjian\1.txt'):
tmp.append(str.upper(line))
tmp
['HELLO,WORLD']
相应的也有sorted会对迭代对象进行排序后生成列表1
2r'D:\ruanjian\1.txt')) sorted(open(
['hello,world']
numerate也会对迭代对象进行运算后生成可迭代列表。enumerate就是在原有的顺序中添加序列号。1
2r'D:\ruanjian\1.txt'))) list(enumerate(open(
[(0, 'hello,world')]
sum、any、all、max、min也可使用迭代器。1
2
3
43,5,1,6,4]),min([3,6,8,2,4]) max([
(6, 2)
1,[],'True']),all([1,[],'True']) any([
(True, False)
在python3中函数生成的是可迭代的特定对象:1
2
3
45) range(
range(0, 5)
5)) list(range(
[0, 1, 2, 3, 4]
python3的这种方式会延迟计算,在提取内容的时候计算结果,这样会节省内存空间,不需要提前计算后放进内存,迭代对象迭代完成后不能再次读取1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16def printlist(list1):
for i in list1:
print('function print:{}'.format(i))
yield 'Result: {}'.format(i)
1,2,3,4,5] li=[
s=printlist(li)
s.__next__()
function print:1
'Result: 1'
s.__next__()
function print:2
'Result: 2'
s.__next__()
function print:3
'Result: 3'
其中数字、字符串、元组是不可变的,列表、字典是可变的。
对不可变类型的变量重新赋值,实际上是重新创建一个不可变类型的对象,并将原来的变量重新指向新创建的对象(如果没有其他变量引用原有对象的话(即引用计数为0),原有对象就会被回收)。
   1.正负数   2.十六进制(表示方式为0x或者0X开头。例如:0xff)   3.八进制(表示方式为0o或者0O开头。例如:0o632457)   4.二进制 (表示方式为0b或者0B开头。例如:0b101100)
1 | 10 s= |
使用int(str,base)可以将非十进制的数转换成整数
,其中str是文本形式的数字,base可以为2,8,16数字,分别代表二进制,八进制,十六进制,最高到36位,最低为21
2
3
4
5
6
7
8
9
10 >>> int('0b10010',2)
18
'0o52415',8) int(
21773
'0x134ab',16) int(
79019
's',32) int(
28
'yz',36) int(
1259
当然也可以进行16进制转二进制八进制,八进制可以转其他进制1
2
3
4
5
6
7
8
9
10
11
120b1001) hex(
'0x9'
0o1234) hex(
'0x29c'
0b101) oct(
'0o5'
0xff) oct(
'0o377'
0xff) bin(
'0b11111111'
0o7777) bin(
'0b111111111111'
1 | 12 a= |
power:幂函数,功能与运算符**一样
1 | >>> pow(2,3) |
sqrt:取当前数的平方根
1 | >>> import math |
max:最大值
1 | >>>max(2,3,4,5,1,9,6) |
min:最小值
1 | 2,3,4,5,1,9,6) min( |
abs与fabs:取绝对值,fabs取出的是浮点数
1 | -1) abs( |
round:四舍五入(当小数为5的时候会向靠近偶数的一端进)
1 | >>> round(3.5) |
ceil:向上取整
1 | >>> math.ceil(1.7) |
floor:向下取整
1 | >>> math.floor(1.7) |
cmp:python2中的比较函数,当前面数值大返回-1,一样大返回0,后面数值大返回1
1 | 1,2) cmp( |
随机数函数
- 取0-1之间的随机小数:
1 | >>> import random |
- 取自定义数里的随机数:(可以取多个元素)1
2
3
4
5
6
7
8>>> random.choice([1,2,3,4,5])
2
>>> random.choice([1,2,3,4,5])
3
>>> random.sample([1,2,3,4,5,6,7,8,9],2)
[3, 7]
>>> random.sample([1,2,3,4,5,6,7,8,9],3)
[4, 9, 3]
- 随机打乱顺序:1
2
3
4>>> a=[1,2,3,4,5,8]
>>> random.shuffle(a)
>>> a
[1, 8, 2, 3, 4, 5]
- 获取N位随机数:(二进制)1
2
3
4
5
6>>> random.getrandbits(6)
55
>>> random.getrandbits(6)
48
>>> random.getrandbits(7)
104
modf:把浮点数的整数位和小数位单独取出来
1 | >>> math.modf(1.4) |
log:指数函数。默认e为底数,结果为浮点数。也可以自定义底数
1 | >>> math.log(4,2) |
格式化输出:格式化输出保留有效数字,格式化输出的是字符串
1 | 2.345,'0.2f') s=format( |
Decimal模块:在使用浮点数的时候,因为计算机是使用二进制表示,所以会出现精度问题,可以使用Deciamal模块来解决精度问题
1 | 4.2 a= |
格式化输出——format:使用format进行进制转换
1 | 20 a= |
字符串(python2默认使用ascii编码,使用Unicode编码须在字符串前加u,python3使用unicode编码)
a=’str’
a=u’str’
1 | >>> 'abc'+'def' |
1 | a="text" |
1 | >>> ord('d') |
这里利用ascii编码进行大小写转换
1 | >>> Text="" #初始化Text |
这里利用字符串的方法进行转换
1 | >>> str='asdFGHzxcVBN' |
除此之外,还可以使用字符串的大小写方法进行大小写转换
ascii编码对照表
二进制 | 十进制 |十六进制 |图形|
—|—|—|—|
0010 0000|32|20|(空格)
0010 0001|33|21|!
0010 0010|34|22|”
0010 0011|35|23|#
0010 0100|36|24|$
0010 0101|37|25|%
0010 0110|38|26|&
0010 0111|39|27|’’
0010 1000|40|28|(
0010 1001|41|29|)
0010 1010|42|2A|*
0010 1011|43|2B|+
0010 1100|44|2C|,
0010 1101|45|2D|-
0010 1110|46|2E|.
0010 1111|47|2F|/
0011 0000|48|30|0
0011 0001|49|31|1
0011 0010|50|32|2
0011 0011|51|33|3
0011 0100|52|34|4
0011 0101|53|35|5
0011 0110|54|36|6
0011 0111|55|37|7
0011 1000|56|38|8
0011 1001|57|39|9
0011 1010|58|3A|:
0011 1011|59|3B|;
0011 1100|60|3C|<
0011 1101|61|3D|=
0011 1110|62|3E|>
0011 1111|63|3F|?
0100 0000|64|40|@
0100 0001|65|41|A
0100 0010|66|42|B
0100 0011|67|43|C
0100 0100|68|44|D
0100 0101|69|45|E
0100 0110|70|46|F
0100 0111|71|47|G
0100 1000|72|48|H
0100 1001|73|49|I
0100 1010|74|4A|J
0100 1011|75|4B|K
0100 1100|76|4C|L
0100 1101|77|4D|M
0100 1110|78|4E|N
0100 1111|79|4F|O
0101 0000|80|50|P
0101 0001|81|51|Q
0101 0010|82|52|R
0101 0011|83|53|S
0101 0100|84|54|T
0101 0101|85|55|U
0101 0110|86|56|V
0101 0111|87|57|W
0101 1000|88|58|X
0101 1001|89|59|Y
0101 1010|90|5A|Z
0101 1011|91|5B|[
0101 1100|92|5C|\
0101 1101|93|5D|]
0101 1110|94|5E|^
0101 1111|95|5F|_
0110 0000|96|60|`
0110 0001|97|61|a
0110 0010|98|62|b
0110 0011|99|63|c
0110 0100|100|64|d
0110 0101|101|65|e
0110 0110|102|66|f
0110 0111|103|67|g
0110 1000|104|68|h
0110 1001|105|69|i
0110 1010|106|6A|j
0110 1011|107|6B|k
0110 1100|108|6C|l
0110 1101|109|6D|m
0110 1110|110|6E|n
0110 1111|111|6F|o
0111 0000|112|70|p
0111 0001|113|71|q
0111 0010|114|72|r
0111 0011|115|73|s
0111 0100|116|74|t
0111 0101|117|75|u
0111 0110|118|76|v
0111 0111|119|77|w
0111 1000|120|78|x
0111 1001|121|79|y
0111 1010|122|7A|z
0111 1011|123|7B|{
0111 1100|124|7C||
0111 1101|125|7D|}
0111 1110|126|7E|~
capitalize():字符串首字母大写
1 | 'hello world' str= |
title():字符串中单词的首字母大写
1 | str.title() |
upper():字符串转换成大写
1 | str.upper() |
swapcase():字符串大小写互转
1 | 'HellO wORld' str= |
center():居中对齐
1 | 'hello' str= |
ljust():居左对齐
1 | 11,'_') str.ljust( |
rjust():居右对齐
1 | 11) str.rjust( |
expandtabs():修改tab空格的个数
1 | >>> str='hello\tworld' |
zfill():将字符串扩充到指定长度,前面使用0填充
1 | >>> str.zfill(20) |
strip():删除字符串两边(左边lstrip或右边rstrip)的指定字符(默认为空格和换行符)
1 | >>> str=' hello world ' |
1 | 'hello,world' str= |
find/rfind():分别从字符串前后开始查找第一个匹配到的字符串的位置,找不到就返回-1
1 | str='hello,world' |
index/rindex():与find方法类似,但是找不到会报错
1 | 'l') str.index( |
replace(old,new[,count]):替换字符串,count代表替换个数
1 | 'l','L') str.replace( |
isdigit、isdecimal、isnumeric三者的区别
isdigit()
True: Unicode数字,byte数字(单字节),全角数字(双字节),罗马数字
False: 汉字数字
Error: 无
isdecimal()
True: Unicode数字,,全角数字(双字节)
False: 罗马数字,汉字数字
Error: byte数字(单字节)
isnumeric()
True: Unicode数字,全角数字(双字节),罗马数字,汉字数字
False: 无
Error: byte数字(单字节)
split([sep[,maxsplit]])/rsplit([sep[,maxsplit]]):分别从左右按照sep字符串分隔,最多分隔maxsplit此,默认无数次
1 | >>> str='asd,fgh,jkl' |
splitlines()以\n或者\r或者\n\r分隔
1 | 'asd\nfgh\njkl' str= |
partition(sep):将分隔符也作为一个元素列出来
1 | 'http://www.baidu.com'.partition('://') |
1 | 'asdfg' str= |
python字符串格式化输出的三种方式
格式化操作符(%) | 说明 |
---|---|
s | 获取传入对象的str方法的返回值,并将其格式化到指定位置 |
r | 与s一样,但输出方式是repr方式,而不是str |
c | 整数:将数字转换成其unicode对应的值,10进制范围为 0<=i<=1114111(py27则只支持0-255);字符:将字符添加到指定位置 |
d | 有符号十进制(整数),将整数、浮点数转换成十 进制表示,并将其格式化到指定位置 |
i | 有符号整数 |
u | 无符号整数 |
o | 将整数转换成八 进制表示,并将其格式化到指定位置 |
x | 将整数转换成十六进制表示,并将其格式化到指定位置 |
X | 与x一样,A-F是大写 |
e | 浮点指数,将整数、浮点数转换成科学计数法,并将其格式化到指定位置(小写e) |
E | 与e一样,E为大写 |
f | 将整数、浮点数转换成浮点数表示,并将其格式化到指定位置(默认保留小数点后6位) |
F | 浮点数十进制 |
g | 浮点e或f,自动调整将整数、浮点数转换成 浮点型或科学计数法表示 |
G | 浮点E或F,自动调整将整数、浮点数转换成 浮点型或科学计数法表示 |
% | 当字符串中存在格式化标志时,需要用 %%表示一个百分号 |
注:Python中百分号格式化是不存在自动将整数转换成二进制表示的方式
举例1
2
3
4
5
6
7
8
9
10
11
12"%s|%r|%c" %("this is str","this is repr","C")
"this is str|'this is repr'|C"
"%d|%i|%o|%x|%X|" %(3,5,12,13,14)
'3|5|14|d|E|'
"%e|%E|%f|%F|%g|%G" %(1.5E3,1.5e3,13.5,13.5,1.5e13,13.5E15)
'1.500000e+03|1.500000E+03|13.500000|13.500000|1.5e+13|1.35E+16'
"%(string)-10s"%({'string':'1'})
'1
>>> "%(float)+10.2F"%({'float':3.1})
' +3.10'
>>> "%(float)-10.2f"%({'float':3.1})
'3.10 '
语法:{}.format(value)
参数:
(value):可以是整数,浮点数,字符串,字符甚至变量。
Returntype:返回一个格式化字符串,其值在占位符位置作为参数传递。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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80#位置参数
'wanger' username=
123456 password=
print ("{}'s password is {}".format(username,password))
wanger's password is 123456
>>> username='wanger'
>>> password=123456
>>> print ("{1}'s password is {0}".format(password,username))
wanger's password is 123456
#下标参数
>>> si=['KB','MB','GB','TB','PB','EB','ZB','YB']
>>> '1000{0[0]}=1{0[1]}'.format(si)
'1000KB=1MB'
#浮点数精度
>>> '{:.4f}'.format(3.1415926)
'3.1416'
>>> '{:>10.4f}'.format(3.1415926)
' 3.1416'
>>> 'this is a test {t[0]}'.format(t='hello')
'this is a test h'
>>> 'this is a test {t[1]}'.format(t='hello')
'this is a test e'
#使用模块作为参数
>>> import sys
>>> sys.platform
'win32'
>>> "{0.platform}".format(sys)
'win32'
>>> 'my laptop platform is {s}'.format(s=sys.platform)
'my laptop platform is win32'
>>> 'my laptop platform is (s.platform)'.format(s=sys)
'my laptop platform is (s.platform)'
#关键字参数
>>> 'my name is {name} ,age is {age}'.format(name='wanger',age='25')
'my name is wanger ,age is 25
```
当占位符{}为空时,Python将按顺序替换通过str.format()传递的值。
str.format()方法中存在的值本质上是元组数据类型,元组中包含的每个单独值都可以通过索引号调用,索引号以索引号0开头。
第三段代码的变量si是一个列表,{0}就代表format()方法的第一个参数,那么{0[0]}就代表列表的第一个元素,{0[1]}就代表列表的第二个元素
这个例子说明格式说明符可以通过利用(类似) Python 的语法
访问到对象的元素或属性。这就叫做复合字段名 (compound field names) 。
以下复合字段名都是“ 有效的 ” 。
• 使用列表作为参数,并且通过下标索引来访问其元素(跟上
一例类似)
• 使用字典作为参数,并且通过键来访问其值
• 使用模块作为参数,并且通过名字来访问其变量及函数
• 使用类的实例作为参数,并且通过名字来访问其方法和属性
• 以上方法的任意组合
###### format_spec参数
表达式:format_spec ::= [[fill]align][sign][#][0][width][,][.precision][type]
- fill ::= <'any character'>
- align ::= "<"'左对齐' | ">"‘右对齐’ | "="‘在数字里,符号左对齐,数字右对齐 | "^"‘居中’
- sign ::= "+" | "-" | " "(当sign=’+‘时,即使是正数也会显示符号,-只有为负数的时候才显示负号,为空格时,会在正数前面留下符号位)
- width ::= integer (定义输出的宽度)
fill和align以及后面的width相当于str方法中的center,ljust,rjust
```python
>>> '{:+^15}'.format('start')
'+++++start+++++'
>>> '{:+^15}'.format('end')
'++++++end++++++'
>>> '{:*<15}'.format('end')
'end************'
>>> '{:*>15}'.format('start')
'**********start'
>>> '{:=+20}'.format(10)
'+ 10'
>>> print("{:=10}\n{:=+20}\n{:-^10}\n{:=-13}".format(10,10,'-',-15))
10
+ 10
----------
- 15
#只有在数字显示里,显示二进制数,八进制数,十六进制数的时候,需要显示前面的0b,0o,0x的时候才会用到
1 | "{0:8b},{0:8o},{0:8x}".format(10) |
,符号是表示数字时每三位中间加,
1 | '{:,}'.format(100000000000) |
0是固定宽度前面补0
.precision ::= integer(精度显示)
1 | >>> '{:010.5}'.format(3.1415926) |
type ::= “b” | “c” | “d” | “e” | “E” | “f” | “F” | “g” | “G” | “n” | “o” | “s” | “x” | “X” | “%” (跟之前使用%表示的相等)
- 当为字符时:使用s,默认就是s
- 当为整数时:b,o,x和X是二进制、八进制、十六进制,c是数字按Unicode转换成字符,d是正常十进制,默认就是d。也可以使用n来代替d
1 | "{0:d},{0:b},{0:o},{0:x},{0:X}".format(10) |
- 为浮点数时:e和E是指数,f和F是浮点数。g和G是同一的,也可以使用n来代替g, %是显示百分比1
2"{0:e},{0:F},{0:g},{0:n},{0:%}".format(10.3)
'1.030000e+01,10.300000,10.3,10.3,1030.000000%'
f-strings也称为“格式化字符串文字”,f字符串是f在开头有一个字符串文字,其中以 {} 包含的表达式会进行值替换。表达式在运行时进行评估,然后使用format协议进行格式化。其中以 {} 包含的表达式会进行值替换。
简单举例1
2
3
4
5
6
7>>> name='wanger'
>>> age=25
>>> f"hello,I'm {name},my age {age} "
"hello,I'm wanger,my age 25 "
#也可以使用大写F
>>> F"hello, I'm {name},my age {age} "
"hello, I'm wanger,my age 25 "
当然也可以进行简单的计算1
2>>> f"{2*3}"
'6'
也可以调用函数1
2
3
4
5
6>>> def test(input):
... return input.lower()
...
>>> name='WangEr'
>>> f"{test(name)} is funny"
'wanger is funny'
还可以选择直接调用方法1
2
3'WangEr' name=
f"{name.lower()} is funny"
'wanger is funny'
在使用字典的时候。如果要为字典的键使用单引号,请记住确保对包含键的f字符串使用双引号。1
2
3comedian = {'name': 'wanger', 'age': 25}
f"The comedian is {comedian['name']}, aged {comedian['age']}."
'The comedian is wanger, aged 25.'
1 | >>> str='asd,dfg;zxc ert uio' |
[]表示里面字符任意匹配。[;, ]表示;或者,或者空格,\s*表示任意个前面字符
字符串开头或结尾匹配
比如要看一个地址是否是http://或者ftp://开头
或者查看文件后缀是不是TXT格式
可以这样查看
1 | 'http://www.baidu.com' url= |
用shell通配符
我们还可以使用shell通配符来检查文件的结尾,这需要用到fnmatch模块
fnmatch不区分大小写,fnmatchcase是区分大小写的
1 | from fnmatch import fnmatch,fnmatchcase |
匹配和搜索特定格式的文本
普通匹配可以使用find方法,如果是特定格式的话还是会用到正则模块
1 | '2018/10/24' date1= |
在正则模块re中\d表示单个数字,+表示一个或多个前面的字段
1 | import re |
\1,\2,\3分别代表前面匹配模式中的第一个括号匹配到的,第二个括号匹配到的,第三个括号匹配到的,使用subn方法可以看到匹配到几次
1 | import re |
最短匹配模式
用正则表达式匹配某个文本模式,而他找到的是最长匹配,如果要匹配最短字符,可以用下面的方法
1 | >>> strpat=re.compile(r'\"(.*)\"') |
删除字符串中不需要的字符
去掉字符串开头,中间或者结尾不想要的字符串,比如空白
1 | 'hello world \n' s= |
合并拼接字符串
1 | >>> a='hello' |
1 | 'aaaa') os.mkdir( |
os.rmdir(name) #删除一个目录
os.remove(name) #删除一个文件1
2
3
4
5
6'aaaa') os.rmdir(
'aaaa') os.path.isdir(
False
'test.txt') os.remove(
'test.txt') os.path.isfile(
False
os.getcwd() #获取当前路径,相当于Linux下的pwd命令
os.path.abspath(file|dir) #获取文件或者目录的绝对路径
os.path.basename(name) #获取文件名或文件夹名
os.path.dirname(name) #获取文件或文件夹的路径1
2
3
4
5
6
7
8 os.getcwd()
'/root/SuXinProject'
'.') os.path.abspath(
'/root/SuXinProject'
'/root/user.sh') os.path.dirname(
'/root'
'/root/user.sh') os.path.basename(
'user.sh'
os.path.splitext #分离文件名与扩展名
os.path.split #分离目录与文件名
os.path.join(path,name) #连接目录与文件名或目录1
2
3
4
5
6'/root/user.sh') os.path.split(
('/root', 'user.sh')
'/root/user.sh') os.path.splitext(
('/root/user', '.sh')
'/root/','user.sh') os.path.join(
'/root/user.sh'
os.chdir(dir) #切换目录
os.listdir(dir) #列出目录下的所有目录和文件
os.path.getsize(file|dir) #获取文件的大小,如果是目录则直接返回0
os.stat(name) #获取文件属性
os.system(commond) #执行系统命令
os.rename(old,new) #文件重命名1
2
3
4
5
6
7
8
9
10
11'/root') os.chdir(
'.') os.listdir(
['.vnc', 'mysql-5.7.21-linux-glibc2.12-x86_64.tar.gz', '.pydistutils.cfg', '.cache', '.git', 'file', '.mozilla', '.rnd', 'GUESS', 'Music', 'run.sh', '.finalshell', '.viminfy.tmp', '.config', 'docker-logspout-elk', 'Desktop', 'sed.txt', '100oush.sh', 'pid2.txt', '.cshrc', 'mynginx', '.bash_profile', 'etcd', 'sh.txt', 'oushu.sh', '.docker', '.viminfx.tmp', 'pid.sh', 'test', '.pycharm_helpers', 'user.sh', 'net', 'jiujiu.sh', '.dbus', 'sum100.sh', '.ssh', '.bashrc', 'LinEnum', 'sysinfo.sh', '.esd_auth', 'for100oushu.sh', 'pid1.txt', '.local', 'SuXinProject', 'phone.sh', '.ansible', '.viminfz.tmp', 'Documents', '.viminfo.tmp', 'study', '.ICEauthority', 'Pictures', 'for99.sh', '.bash_logout', '.pid.sh.swp', 'qiuhe.sh', 'pid.txt', '.viminfo', '.npm', 'fors00oushu.sh', '.pki', '99.sh', '.gitconfig', 'etcd-v3.2.10-linux-amd64', 'nohup.out', 'Public', 'user1.sh', 'diff.txt', '.Xauthority', '.virtualenvs', '.node_repl_history', '.pip', '.bash_history', 'Downloads', 'Videos', 'killpid.sh', 'Templates', 'daemon.json', 'beijing', 'dif', '.tcshrc', 'kill.sh', '.mysql_history', 'biao.txt', 'blog']
'./user.sh') os.path.getsize(
299
'./user.sh') os.stat(
posix.stat_result(st_mode=33261, st_ino=143152, st_dev=64769L, st_nlink=1, st_uid=0, st_gid=0, st_size=299, st_atime=1543135673, st_mtime=1542818209, st_ctime=1542818209)
'whoami') os.system(
root
0
'99.sh','999.sh') os.rename(
os.getuid() #获取用户id
os.getgid() #获取用户组id
os.environ[‘环境变量名称’]=’环境变量值’ #设置环境变量
os.environ[‘环境变量名称’] #获取环境变量
os.getenv(‘环境变量名称’) #获取环境变量1
2
3
4
5
6
7
8
9 os.getuid()
0
os.getgid()
0
'PYTHON']='/usr/local/bin' os.environ[
'PYTHON'] os.environ[
'/usr/local/bin'
'PYTHON') os.getenv(
'/usr/local/bin'
os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]]) # 从上到下或从下到上遍历树来生成目录树中的文件名
1 | for root, dirs, files in os.walk("."): |
Browser:浏览器
URI:uniform resource
indentifier:统一资源标识符
URL:uniform resource locator:统一资源定位符
统一:路径格式的统一
protocal://address/to/resouce_path
web资源:用URL标识,并且让用户客户端代理(浏览器)能够访问的文件
HTML:把多种web资源整合成一个HTML文档,并能够让浏览器访问显示的一种语言
http/1.0版本:
1.引入MIME机制(为了实现能够传输分文本信息)
MIME:multi Internet mail extension:多用途互联网邮件交换协议,将非文本数据在传输之前重新编码为文本格式,接收方能够利用相反的方式将其重新还原为原来的格式,还能调用相应的应程序显示此文件
扩展:SMTP:simple mail transfer protocol:简单邮件传输协议
2.请求与响应头域
3.响应对象以一个响应状态行开始
4.响应对象不止限于文本
5.开始支持客户端通过POST方法向web服务器提交数据,支持GET、HEAD、POST方法
6.支持长连接(但默认还是使用短连接),
7.缓存机制(加快速度),以及身份验证
动态网页:web服务器存储的文档是非HTML文档,而是动态语言,动态语言生成的脚本能够接受用户的参数后形成HTML文档,把生成的文档返回给客户端
http/1.1是目前使用最广泛的协议版本,在http1.0中使用长连接需要添加请求头Connection:Keep-Alive,而在http1.1默认支持长连接,除非特殊声明不支持(HTTP请求首部加上Connection:Close),http1.1引入了许多关键优化:keepalive连接。chunked编码传输,字节范围请求,请求流水线等
HTTP1.1协议中共定义了八种方法来表明Request-URI指定的资源的不同的操作方式:
1. OPTIONS:返回服务器针对特定资源所支持的HTTP请求方法,也可以利用向web发送’*’的请求来测试服务器的功能性
2. HEAD:向服务器索要与GET请求相一致的响应,只不过想硬体将不会被返回,这一方法可以在不必传输整个响应内容的情况下,就可以获取包含在响应消息头中的元信息
3. GET:向特定的资源发出请求。注意:GET方法不应被用于产生“副作用”的操作中,例如在web app中,其中一个原因是GET可能会被网络爬虫等随意访问
4. POST:向指定资源提交数据进行数据请求(例如提交表单或者上传文件).数据被包含在请求体中,POST请求可能会导致新的资源的建立或已有资源的修改
5. PUT:向指定资源位置上传其最新内容
6. DELETE:请求服务器删除Request-URI所标识的资源
7. TRACE:回显服务器收到的请求,主要用于测试和诊断
8. CONNECT:http/1.1协议中预留给能够将连接改为管道方式的代理服务器
http/2.0是下一代http协议,目前应用还非常少,主要特点有:
多路复用(二进制分帧):在二进制分帧层上,http2.0将所有传输的信息分割为更小的消息和帧,并对他们采用二进制格式的编码
头部压缩:当一个客户端向相同服务器请求许多资源时,向来自同一个网页的图像,将会有大量的请求看上去几乎同样的,这就需要压缩技术对付这种几乎相同的信息
随时复位:http1.1一个缺点是当http信息有一定长度大小数据传输时,你不能方便地随时停止他,中断TCP连接的代价是昂贵的,使用http2的RST_STREAM将能够方便停止一个信息传输,启动新的信息,在不中断连接的情况下提高带宽利用效率
服务器端推流:server Push:客户端请求一个资源X,服务器端判断也许客户端还需要资源Z,在无需事先询问客户端情况下将资源Z推送到客户端,客户端接受到后,可以缓存起来以备后用.优先权和依赖:每个流都有自己的优先级别,会表明哪个流是最重要的,客户端会指定哪个流是最重要的,有一些依赖参数,这样一个流可以依赖另一个流,优先级别可以在运行时动态改变,当用户滚动页面时,可以告诉浏览器哪个图像是最重要的,你也可以在一组流中进行优先筛选,能够突出抓住重点流
http报文:请求报文(http request)和响应报文(http response)
请求报文语法:1
2
3<method><request-URI><version>
<headers>
<entity-body>
响应报文语法:1
2
3 <version><status><reason-phrase>
<headrers>
<entity-body>
1xx:纯信息,已经弃用
200:“成功“类的信息
301:永久重定向
302:临时重定向
304:浏览器缓存
403:请求不到首页,权限被拒绝
404:资源找不到
500:服务器内部错误,程序代码错误
502:找不到后端的错误
504:请求超时
1.单线程web服多器(Single-threaded web servers):此种架构方式中,web服多器一次处理一个请求.结束后读取井处理下一个请求.在某请求处理辻程中,其它所有的清求将被阻塞,因此;在并发请求较多的场景中将会出现严重的性能问题(即一次只能处理一个请求)
2.多进程/多线程web服灸器:此种架构方式中, web服多器生成多个进程或线程并行处理多个用戸请求,进程或线程可以按需或事先生成、有的web服务器应用程序为每个用戸请求生成一个単独的进程或线程来进行响应,不过, 一旦并发请求数量达到成千上万吋,多个同吋进行的进程或线程将会消耗大量的系統资源(即每个进程只能响应一个请求,并且一个进程对应一个线程)
3.I/O多路复用web服努器:为了能够支持更多的并友用户清求,越来越多的web服努器正在采用多种复用的架构–即同歩监控所有的连接靖求的活动状态,当一个连接的状态发生改变时(如数据准各完毕或发生某错误)将为其执行一系列特定操作;在操作完成后此连接将重新变回暂时的稳定态并返回至打开的连接列表中,直到下次的状态改变,由于其多路复用的特性,进程或线程不会被空闲的连接所占用,因而可以提供高效的工作模弌.(
这种架构可以理解为一个进程可以生成多个线程,每个请求交给一个线程程迸行处理)
http://www.sec-wiki.com/skill/安全技能(里面渗透逆向编程都有介绍)
http://blog.knownsec.com/Knownsec_RD_Checklist/ 知道创宇研发技能表v3.0
https://www.shentoushi.top/network 渗透师 (网络安全学习网址导航)
https://www.anquanquan.info/ 安全圈info(网络安全学习导航网址)
https://secquan.org 圈子社区
https://github.com/cxf210/Scanners-Box
http://edu.gooann.com/ 谷安网校
https://edu.aqniu.com/ 安全牛课堂
http://www.jikexueyuan.com/ 极客学院
http://www.hetianlab.com/ 合天
http://www.moonsos.com/ 米安网
http://www.ichunqiu.com/ i春秋
http://www.honyaedu.com/ 红亚
http://www.baimaoxueyuan.com/ 白帽学院
http://www.simplexue.com/ctf/index 西普学院
http://www.imooc.com/course/list 慕课
http://www.secbox.cn/ 安全盒子
http://www.freebuf.com/ freebuf
http://bobao.360.cn/ 360安全播报
https://github.com/cxf210/Scanners-Box github上的资源库
https://github.com/cxf210/docker
https://github.com/cxf210/fuzzdb
https://github.com/cxf210/webshell
github上的webshell
http://drops.wooyun.org/ 乌云知识库
http://wiki.wooyun.org/ WooYun WiKi
https://www.91ri.org/ 91ri
https://www.t00ls.NET/tools 土司
https://bbs.77169.com/forum.php 华盟网
http://www.ijiandao.com/ 爱尖刀
http://www.secist.com/ 即刻安全
http://www.secwk.com/article/index.html 威客众测
http://bluereader.org/ 深蓝阅读
http://www.shentou.org/ 黑客安全军火库
http://netsecurity.51cto.com/ 51cto
http://security.csdn.net/ csdn
http://www.80sec.com/ 80sec team
https://security.alibaba.com/blog.htm?spm=0.0.0.0.knOqaI 阿里巴巴安全响应中心
http://security.tencent.com/index.PHP/blog 腾讯安全应急响应中心博客
http://security.360.cn/blog 360安全应急响应中心博客
http://sec.baidu.com/index.php?research/list 百度安全应急响应中心博客
http://security.tencent.com/index.php/blog > http://217.logdown.com/ 217
https://laolisafe.com/ 大老李的博客
http://mannix.top/ mannix的博客
http://www.raosong.cc/ 折戟博客
http://www.blue-lotus.net blue-lotus 蓝莲花
http://blog.0ops.net/ 0ops
http://blog.amanhardikar.com/#home
http://le4f.net/ e4f
http://www.programlife.net/ 代码疯子
http://www.hackdog.me/ redrain’blog
http://www.syjzwjj.com/ 俊杰
http://syclover.sinaapp.com/ 三叶草安全小组
http://appleu0.sinaapp.com/ appleU0大大
http://bl4ck.in/ tomato表哥
http://www.sco4x0.com/ 4叔叔
http://laterain.sinaapp.com/ 白神
http://0nly3nd.sinaapp.com/ 0nly3nd
http://hijacks.in/ LateRain’blog
http://www.waitalone.cn/ 独自等待
http://evilcos.me/ 余弦
http://www.moonsec.com/ 暗月
http://www.cnblogs.com/xuanhun/ 玄魂
https://www.leavesongs.com/ 离别歌
http://huaidan.org/ 鬼仔
http://www.03sec.com/ sky的自留地
http://joychou.org/ jc老师
http://www.unhonker.com/ 90’s blog
http://www1.taosay.net/ 道哥的黑板报
http://blog.knownsec.com/ 知道创宇
http://www.sadk.org/ 焠安
http://www.cnseay.com/ seay’blog
http://blog.aptsec.net/ AptSec Team
http://lcx.cc/ 网络安全研究中心
http://www.kali.org.cn/ kali中文网
http://xiao106347.blog.163.com/ xiao106347 kali折腾
http://www.wooyun.org/ 乌云
http://bbs.blackbap.org/ 习科
http://www.1937cn.net/ 1937
http://forum.cnsec.org/ 暗组
http://www.k33nteam.org/ keen team
http://forum.eviloctal.com/ 邪恶八进制
http://www.evil0x.com/ 邪恶十六进制
http://www.myhack58.com/ 黑吧安全吧
http://www.cnhonkerarmy.com/ 中国红客红盟
http://www.chinahacker.com/ 中国黑客联盟
http://www.hxhack.com/ 华夏黑客联盟
http://www.heikexiehui.com/ 中国黑客协会官网
http://www.hackbase.com/ 黑基
http://www.2cto.com/ 红黑联盟
http://bbs.2cto.com/ 红黑联盟论坛
http://www.hackwd.com/
http://www.heishou.com.cn/ 黑手安全网
https://www.sitedirsec.com/ 非安全中国网
http://www.zatokasztuki.com/ 学生技术联盟
http://www.52pojie.cn/ 吾爱破解
http://bbs.pediy.com/ 看雪论坛
https://www.chinapyg.com/ 飘云阁论坛
https://0x00sec.org/ 国外逆向论坛
https://github.com/onethawt/reverseengineering-reading-list/blob/master/README.md 逆向工程阅读清单
https://github.com/RPISEC/Malware/blob/master/README.md 恶意软件分析
http://www.he11oworld.com/ hello word
http://www.w3school.com.cn/ w3school
http://www.runoob.com/ 菜鸟
http://www.51zxw.net/
https://github.com/
http://navisec-Git.qiniudn.com/
http://c.biancheng.net/cpp/
http://www.liaoxuefeng.com/
http://www.php100.com/
https://ruby-china.org/wiki
http://bbs.csdn.net/forums/Java/
http://outofmemory.cn/tutorial/
http://zhuanlan.zhihu.com/Evi1m0/19706178 Evi1m0: 书籍推荐
http://www.douban.com/doulist/3339701/ 信息安全必读书单
http://www.douban.com/doulist/1363865/ 信息安全经典书籍
http://www.zhihu.com/question/21390646
http://my.oschina.net/bluefly/blog/335409?utm_source=tuicool&utm_medium=referralWeb安全核心书单
连载
《安全参考》http://www.douban.com/group/topic/72383272/(2013年第一期--2015年第一期)全集
《书安》(更新中)
http://www.secbox.cn/hacker/8205.html 书安SecBook第一期《icloud iOS安全大揭秘》
http://www.secbox.cn/hacker/7366.html 书安SecBook第二期《信息安全攻防赛》
渗透实战文章可以看看里的杨凡(http://blog.sina.com.cn/s/articlelist_1758675673_4_1.html)
和法克文章(http://pan.baidu.com/share/link?shareid=249629&uk=2198816663)
链接:https://pan.baidu.com/s/1tt9O4etSxkFzPsRCamOInA
提取码:dt8o 个人收集的一些ctf工具包
https://github.com/zardus/ctf-tools github上的ctf工具
http://www.52pojie.cn/forum.php?mod=viewthread&tid=388015 吾爱破解工具包
http://down.52pojie.cn/ 爱盘 – 在线破解工具包,教程
http://www.52pojie.cn/thread-341238-1-1.html 吾爱破解论坛专用破解虚拟机
ctf常用工具包请看http://tieba.baidu.com/p/3933947157里面群文件
http://www.zhihu.com/topic/19558642 黑客知乎话题
http://www.zhihu.com/topic/20011446 ctf知乎话题
http://www.zhihu.com/topic/19561983 信息安全知乎话题
http://zhuanlan.zhihu.com/evilcos/19961466 余弦知乎专栏
http://blog.idf.cn/2015/02/ctf-field-guide
http://tieba.baidu.com/p/3933947157 ctf大全
https://ctftime.org/event/list/upcoming 各种CTF赛事预告
(ps:国内各个高校或企业举办的比赛请进http://tieba.baidu.com/p/3933947157里面的群)
https://ctf.pediy.com/ 看雪ctf
http://reversing.kr/
http://pwnable.kr/
http://exploit-exercises.com/
http://overthewire.org
http://security.cs.rpi.edu/courses/binexp-spring2015/ bin 干货区
http://www.52pojie.cn/forum-67-1.html 『2014CrackMe大赛』
https://github.com/Audi-1/sqli-labs
http://redtiger.labs.overthewire.org/
http://prompt.ml/
http://xss.pkav.net/xss/
http://www.doscn.org/xss/
http://xss-quiz.int21h.jp/
http://escape.alf.nu/
https://xss-game.appspot.com/ 谷歌的xss游戏
http://ctf.nuptsast.com/login 南邮大学ctf
http://hackinglab.cn/ 网络信息安全攻防学习平台
https://www.91ctf.com/session 安恒竞赛平台
http://ctf.bugku.com/new bugkuctf练习平台
http://captf.com/ ctf题目
http://cafebabe.cc/nazo/ 脑洞开发,与ctf只有那么一点关系,有85关了
http://1111.segmentfault.com/ 光棍节程序员闯关秀
http://www.helloisa.com/test/
http://www.fj543.com/hack/ 黑客丛林之旅
http://monyer.com/game/game1/ 梦之光芒的小游戏
http://oj.xctf.org.cn/ XCTF_OJ练习平台
http://hackgame.blackbap.org/ 习科黑客游戏
http://ctf.3sec.cn/ Jlu.CTF
http://www.baimaoxueyuan.com/ctf 白帽学院ctf挑战赛
http://www.ichunqiu.com/tiaozhans i春秋ctf挑战
http://ctf.idf.cn/ idf 实验室
http://www.dvwa.co.uk/ DVWA
http://ctf.moonsos.com/pentest/index.php 米安网ctf
http://www.hetianlab.com/CTFrace.html 合天ctf
http://www.shiyanbar.com/ctf/index 实验吧(前名西普学院)
http://hkyx.myhack58.com/ 黑吧安全网-红客闯关游戏
http://202.108.211.5/ 实训竞赛系统
https://ctf365.com/
https://hack.me/s/
https://ringzer0ctf.com/challenges
https://www.hackergateway.com/
http://challengeland.co/
http://www.hackertest.net/
http://www.wechall.net
https://www.vulnhub.com/
http://insight-labs.org/
http://wargame.kr/
https://ctflearn.com/
http://canyouhack.it/
https://pentest.training/index.php
http://hackit.sinaapp.com/
http://webhacking.kr/
http://fun.coolshell.cn/
http://ringzer0team.com/challenge
https://backdoor.sdslabs.co/
https://www.enigmagroup.org/pages/challenges
http://overthewire.org/wargames/natas/natas2.html
http://smashthestack.org/ 漏洞利用练习网站
]]>直接百度:writeup(一边看一边总结,有道笔记,印象笔记什么的,最好能复现)
http://drops.wooyun.org/?s=writeup&submit=%E6%90%9C%E7%B4%A2
http://bobao.360.cn/ctf/
https://github.com/ctfs/ 各种 writeup
http://sec.yka.me/ CTF Writeup Summary
https://ctf-team.vulnhub.com/ Write Ups
http://hebin.me/
https://blog.csdn.net/gyt478922579/article/details/53204891?locationNum=11&fps=1
https://blog.csdn.net/xuqi7/article/details/51635360
centos6系统使用的ftp是2.0以上的版本,而centos7使用的是3.0.2版本
在centos7下只能在pub下创建文件夹,而且pub用户属主必须是ftp或者将pub目录授予777的权限,也就是说ftp用户在pub目录下必须具有写的权限。
在这之前需要确保配置文件这几个选项为YES,这几个选项在配置文件里都是默认开启的,还有selinux要处于Permissive状态1
2
3anon_mkdir_write_enable=YES
anon_upload_enable=YES
anonymous_enable=YES
首先,ftp的访问跟ftp/pub的权限是没关系的,在正常情况下,授予ftp目录777的权限,是拒绝用户访问的
如果将ftp目录的属主和属组都修改成ftp用户,将ftp目录的权限修改回755,也是不能访问的
将配置文件的umask修改成000,并且重启服务,还是不能访问,但是如果我将ftp的目录的属主和属组都修改成ftp,而ftp的目录权限修改成557,那么ftp服务就可以正常访问了
当我把ftp的属主和属组又修改成root之后,ftp服务又不能访问了
我再把ftp的属主和属组都修改成ftp,,ftp服务还是可以正常的访问
如果我再将ftp的目录权限修改成335,而属主和属组都是root,那么ftp也是可以访问的
保持权限不变,而属主和属组改为ftp,那么ftp服务还是不能访问
我再修改ftp目录的权限为445,将ftp目录的属主和属组都改为root,ftp服务还是可以访问的
ftp目录的权限不变,修改ftp目录的属主和属组为ftp,ftp是可以进行访问的
这里属主和属组都不改变,分别修改ftp目录的权限为665和225,结果ftp服务都不能访问
也就是说不能给ftp用户写的权限,否则不能访问ftp。那如果我修改一下默认目录试试呢,我将ftp默认访问路径修改成/var/test,再次进行测试发现test目录的权限也是不能有写权限,否则不能访问
因此,我们可以得出结论:访问ftp服务的匿名用户不能有写权限,这也就是为什么ftp目录下匿名用户不能创建子目录的原因
关于条件测试命令可以使用man test命令查看
1.test 测试语句
2.[ 测试语句 ]
3.[[ 测试语句 ]]
4.((测试语句))
其中1和2除了语法不一样,功能基本是一样的,而第3种语法他可以使用通配符进行匹配,第四种语法除了用于整数的比较,更多的还是进行一些整数的运算,不过平时经常用到的还是第2、3种语法结构。
1 | -b: 文件是否存在,并且为块文件 |
1 | [root@docker ~]# touch wanger #新建一个普通文件 |
1 | -z string :字符串长度是否为0 |
1 | [root@docker ~]# name=wanger #定义一个变量 |
test num1 数值测试操作符 num2
[ num1 数值测试操作符 num2 ]
[[ num 数值测试操作符 num2 ]]
((num1数值测试操作符num2))
1 | num1 -eq num2 : 数字1是否等于数字2 |
注意:以上几种操作符不能用在(())格式中,在(())中应使用”< > = != >= <=”比较符号来进行数值的比较
1 | [root@docker ~]# test 6 -le 5 && echo 0 ||echo 1 |
1 | -a : 相当于&&,表示逻辑与,两端条件都为真,结果为真 |
1 | test=”123” #定义test变量 |
1 | #!/bin/bash |
1 | #!/bin/bash |
1 | #!/bin/bash |
1 | #!/bin/bash |
1 | #!/bin/bash |
1 | #!/bin/bash |
1 | #!/bin/bash |
1 | #!/bin/bash |
1 | #!/bin/bash |
1 | #!/bin/bash |
1 | #!/bin/bash |
第一种 markdown最高可以设置六级标题,前面#号的数量代表标题的等级,#号后面要带一个空格1
2
3
4
5
6# 一级标题
## 二级标题
### 三级标题
#### 四级标题
##### 五级标题
###### 六级标题
演示
第二种 这种只能表示一级和二级标题,=和-的数量没有限制,只要大于一就行1
2
3
4一级标题
=======
二级标题
------
演示
1 | **加粗** |
演示
加粗
斜体
加粗斜体删除线
无序列表可以有三种写法,使用*或+或- :1
2
3
4
5
6
7
8
9
10
11
12
13
14使用 * :
* 无序列表1
* 无序列表2
* 无序列表3
使用 + :
+ 无序列表4
+ 无序列表5
+ 无序列表6
使用 - :
- 无序列表7
- 无序列表8
- 无序列表9
演示
使用 * :
使用 + :
使用 - :
演示
演示
为人民服务
——毛主席
比较短的或是单行的代码可以使用反引号包裹,若是有多行的代码要使用3个反引号,这里为了转义我用\将反引号隔开,顺便说一下,如果不想让一些符号用作markdown语法,可用\进行转义。1
2
3
4
5
6`短的或者单行代码`
`\``
多行代码{
print ‘人生苦短,我用Python’
}
`\``
演示短的或者单行代码
1
2
3多行代码{
print ‘人生苦短,我用Python’
}
在markdown里使用表格有点麻烦,使用|来分隔不同的单元格,使用-来分隔表头和其他行,使用:来设置表格的对齐方式:---
表示左对齐,不加:也表示左对齐:--:
表示居中对齐---:
表示右对齐1
2
3
4
5|name|age|sex|
|:-----|:--:|----:|
|wanger|23 |nan |
|lisi |20 |nv |
|wangwu|22 |nan |
演示
name | age | sex |
---|---|---|
wanger | 23 | nan |
lisi | 20 | nv |
wangwu | 22 | nan |
可以在一行中用三个以上的星号、减号、底线来建立一个分隔线,同时需要在分隔线的上面空一行。1
2
3---
___
***
演示
超链接与图片格式的最大区别就是图片格式多一个’!’,图片的title和链接的title表示你的鼠标指向图片或者链接描述的时候出现的内容,title与图片地址和链接地址之间有空格,title属性可以不加。
![图片描述](图片地址 "title")
[链接描述](链接地址 "title")
1 | ![微信公众号](/uploads/wechat-qcode.jpg "微信公众号") |
演示
个人博客
之前参照了网上修改的方法老是出现报错,折腾了两天还是不行,后来在修改网站图标的时候才知道是因为我配置文件格式写错了,网上的很多方法都是在主题的配置文件里改,但我改了并没有生效,也许是姿势有问题,后来在主题的配置文件里修改竟然生效了,在配置文件里搜索’Sidebar Avatar’,找到如下字段:1
2
3
4
5
6# Sidebar Avatar
avatar:
# in theme directory(source/images): /images/avatar.gif
# in site directory(source/uploads): /uploads/avatar.gif
# You can also use other linking images.
url: /images/avatar.jpg
在url: 后面加上头像的存放地址,我的头像放在了站点目录/source/images/目录下,修改完配置后执行命令:hexo clean
hexo g
hexo d
刚开始想用Swiftype来着,后来才知道Swiftype在去年就停止免费服务了,又想着去用Algolia,但我实在太笨,找不到地址在哪里,网站访问的也很慢,于是准备用hexo自带的Local Search
npm install hexo-generator-searchdb --save
编辑 站点配置文件,新增以下内容到任意位置:
1 | search: |
编辑 主题配置文件,启用本地搜索功能:
1 | # Local search |
具体可以参考官方的文档Next使用文档
目前我的博客评论用的是来必力,分享用的是Add This,站内搜索用的是local search,感觉用起来还是挺不错的
1 | $ hexo new "My New Post" |
More info: Writing
1 | $ hexo server |
More info: Server
1 | $ hexo generate |
More info: Generating
1 | $ hexo deploy |
More info: Deployment
]]>