自动化脚本

Linux主机批量执行命令

SUSE 11下批量安装snmp和sysstat

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
# /bin/bash
a=$(cat ip.txt|wc -l)
for((i=1;i<=$a;i++));
do
IP=$(sed -n $i'p' ip.txt) #打印匹配的行
PASSWORD=$(sed -n $i'p' password.txt)
echo
echo -e "\033[47;30m 目前安装: \033[0m" #设置字体背景颜色47,字体颜色30,
echo -e "\033[47;30m $IP \033[0m"
/usr/bin/expect << EOF
set timeout 5 #设置超时时间
spawn ssh root@$IP #默认都是使用root账号
expect {
"*yes/no" {send "yes\r" ; exp_continue}
"*assword: " {send "$PASSWORD\r"}
}
expect "*#*" {send "mkdir -p /tmp/soft/snmp/\r"}
expect "*#*" {send "scp root@192.168.11.95:/tmp/soft/snmp/* /tmp/soft/snmp/\r"}
expect {
"*yes/no" {send "yes\r" ; exp_continue}
"*assword: " {send "rootadmin\r"}
}
expect "*#*" {send "rpm -i /tmp/soft/snmp/net-snmp-5.4.2.1-8.12.16.1.x86_64.rpm /tmp/soft/snmp/perl-SNMP-5.4.2.1-8.12.16.1.x86_64.rpm\r"}
expect "*#*" {send "\r"}
expect "*#*" {send "rpm -i /tmp/soft/snmp/sysstat-8.1.5-7.45.24.x86_64.rpm\r"}
expect "*#*" {send "service snmpd start\r"}
expect "*#*" {send "echo rocommunity ITsvs617 192.168.11.0/24 >> /etc/snmp/snmpd.conf\r"}
expect "*#*" {send "cat /etc/snmp/snmpd.conf\r"}
expect "*#*" {send "service snmpd restart\r"}
expect eof #结束expect匹配
EOF
echo
echo -e "\033[47;30m 按任意键继续 \033[0m"
read -n 1 #读入一个字符
echo
echo -e "\033[47;30m 继续运行 \033[0m"
done

More info:设置输出的字体颜色

Python 3 Study

字符串,列表,元组,字典,集合

购物车

(1)丶要求用户输入总资产,例如:2000。
(2)丶显示商品列表,让用户根据序号选择商品,加入购物车。
(3)丶购买,如果商品总额大于总资产,提示账户余额不足,否则,购买成功。
(4)丶附加:可充值、某商品移除购物车。
例:

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
#!/usr/bin/env python
# -*- coding=utf-8 -*-
goods = [
{"name": "电脑", "price": 1999},
{"name": "鼠标", "price": 10},
{"name": "游艇", "price": 20},
{"name": "美女", "price": 998},
]
zongzichang=0
i1=input('请输入你的总资产:')
zongzichang=int(i1)
#输出商品列表,包括商品名和价格
for i1 in goods:
print(i1['name'], i1['price'])
#{"电脑":{"num":1,"single_price":1999}}
car_dir={}
while True:
i2=input('请输入购买的商品(输入q来退出购买):')
if 'q' == i2:
break
for items in goods:
if items['name'] == i2:
name=items['name']
if i2 in car_dir.keys():
car_dir[name]['num']+=1
else:
car_dir[i2]={"num":1,'single_price':items['price']}
else:
pass
print(car_dir)
sum=0
for i3 in car_dir:
price=car_dir[i3]['num']*car_dir[i3]['single_price']
sum=sum+price
if sum <= zongzichang:
print('购买成功')
else:
print('账户余额不足,请充值')

元素分类

(1)丶有如下值集合 [11,22,33,44,55,66,77,88,99,90…],将所有大于 66 的值保存至字典的第一个key中,
将小于 66 的值保存至第二个key的值中,即: {‘k1’: 大于66的所有值, ‘k2’: 小于66的所有值}。
例:

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/env python
# -*- coding=utf-8 -*-
a = [11,22,33,44,55,66,77,88,99,90]
b = {
"key1":[],
"key2":[],
}
for i in a:
if i > 66:
b["key1"].append(i)
else:
b["key2"].append(i)
print(b)

用户登录隐藏密码(三次输入机会)。

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/env python
# -*- coding=utf-8 -*-
import getpass #模块功能让用户输入的内容不可见
time=1
while True:
user=input('请输入用户名:')
password=getpass.getpass("请输入密码:") #隐藏用户输入的内容
if user == 'Hello' and password == 'Python':
print(user,password)
break
else:
pass
time+=1
if time >3:
break

输出商品列表

(1)丶用户输入序号,显示用户选中的商品。
例:

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/env python
# -*- coding=utf-8 -*-
#商品列表有4个,我设置了可以输入4次
li = ["手机", "电脑", '鼠标垫', '游艇']
time=1
for key,i in enumerate(li,1):
print(key,i)
while True:
xuanze=int(input('请输入序号:'))
print(li[xuanze-1])
time+=1
if time > 4:
break

查找列表元组字典

(1)丶查找所有的元素,移除每个元素的空格,并查找以 a或A开头 并且以 c 结尾的所有元素,放在列表中并统计次数。
例:

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
#!/usr/bin/env python
# -*- coding=utf-8 -*-
name={
"li":["alec", " aric", "Alex", "Tony", "rain"],
"tu":("alec", " aric", "Alex", "Tony", "rain"),
"dic":{'k1': "alex", 'k2': ' aric', "k3": "Alex", "k4": "Tony"},
}
new_dic={}
for i1 in name:
if isinstance((name[i1]),list) or isinstance((name[i1]),tuple):
for i2 in name[i1]:
i3=i2.strip()
if (i3.startswith("a") or i3.startswith("A")) and i3.endswith("c"):
print(i3)
if i3 in new_dic:
new_dic[i3]+=1
else:
new_dic[i3]=1
else:
for i4 in name[i1].values():
i5=i4.strip()
if (i5.startswith("a") or i5.startswith("A")) and i5.endswith("c"):
print(i5)
if i5 in new_dic:
new_dic[i5]+=1
else:
new_dic[i5]=1
print(new_dic)

寻找差异

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#! /usr/bin/env python
# -*- coding:utf-8 -*-
# 数据库中原有
old_dict = {
"1":{'hostname':'c1','cpu_count':2,'mem_capicity':80},
"2":{'hostname':'c1','cpu_count':2,'mem_capicity':80},
"3":{'hostname':'c1','cpu_count':2,'mem_capicity':80},
}
# 新汇报的数据
new_dict = {
"1":{'hostname':'c1','cpu_count':2,'mem_capicity':800},
"3":{'hostname':'c1','cpu_count':2,'mem_capicity':80},
"4":{'hostname':'c2','cpu_count':2,'mem_capicity':80},
}
del_set=set(old_dict.keys()).difference(set(new_dict.keys())) #{'2'},需要删除的key,放在set集合里
add_set=set(new_dict.keys()).difference(set(old_dict.keys())) #{'4'},需要新增的key,放在set集合里
update_set=set(old_dict.keys()).intersection(set(new_dict.keys())) #{'1','3'},交集key,放在set集合里

三元运算

例:

1
2
3
4
5
#!/usr/bin/env python
# -*- coding=utf-8 -*-
arg1,arg2 = 1,2
result = arg1 if arg1>arg2 else arg2 #如果条件成立,那么将 "arg1" 赋值给result变量,否则,将"arg2"赋值给result变量
print(result)

函数

函数一

(1)丶写函数,检查传入字典的每一个value的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。

例:

1
2
3
4
5
6
7
8
9
10
#!/usr/bin/env python
# -*- coding=utf-8 -*-
def zidian(args):
for key,value in args.items():
if len(value) > 2:
args[key]=value[0:2]
return args

dic = {'k1':"alex",'k2':[11,22,33,44],"k3":(11,22,33),"k4":"liyunliang"}
print(zidian(dic))

函数二

(1)丶写函数,检查获取传入列表或元组对象的所有奇数位索引对应的元素,并将其作为新列表返回给调用者。
例:

1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/env python
# -*- coding=utf-8 -*-
def liebiao(args):
new_list=[]
for i in range(len(args)):
if i%2 == 1:
new_list.append(args[i])
else:
pass
return new_list
list = [11,22,33,44,55,66,77]
print(liebiao(list))

函数三

(1)写函数,检查用户传入的对象(字符串、无嵌套的列表和元组)的每一个元素是否含有空内容。
例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/env python
# -*- coding=utf-8 -*-
def space_jiancha(args):
for i in args:
if isinstance(i,int): #判断是否是int类型,int类型不能使用isspace
pass
else:
if i.isspace():
return True
break
return False

list =[11,22,"liyunliang"," "]
ret=space_jiancha(list) #ret等于True或False
if ret:
print("用户传入的对象有空格")
else:
print("用户传入的对象没有空格")

def和lambda定义函数区别

(1)丶lambda用于非常简单的函数,一行完成,如下两个函数功能相同。
例:

1
2
3
4
5
6
7
8
9
#!/usr/bin/env python
# -*- coding=utf-8 -*-
def sumnumber(args1,args2):
return args1+args2

my_lambda=lambda args1,args2:args1+args2

print(sumnumber(1,2))
print(my_lambda(1,2))

斐波那契数列取第十个值

例:

1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/env python
# -*- coding=utf-8 -*-
# 0 1 1 2 3 5 8 13 21 34 55 89
def f1(end,arg1,arg2):
if end == 10:
return arg1
arg3 = arg1 + arg2
r = f1(end+1,arg2,arg3)
return r
ret= f1(1,0,1)
print(ret)

冒泡排序

例:

1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/env python
# -*- coding=utf-8 -*-
li = [112,3,6,50,40,1] #将列表中数字从小到大依次排列
print(li)
for i in range(1,len(li)):
for j in range(len(li)-i):
if li[j] > li[j+1]:
temp = li[j]
li[j] = li[j+1]
li[j+1] = temp
print(li)

装饰器

单层装饰

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/env python
# -*- coding:utf-8 -*-
def outer(func): #装饰器outer
def inner(*args,**argss): #可接收任意参数
print("你好!")
r = func(*args,**argss)
print("再见!")
return r
return inner
@outer #相当于outer(f2)
def f2(a1,a2): #此函数若需要添加一些额外的功能,不改变原函数代码的情况可以使用装饰器
return a1 + a2
print(f2(1,2)) #输出为:'你好!' '再见!' 3

二层装饰

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
#!/usr/bin/env python
# -*- coding:utf-8 -*-
def outer(func): #装饰器outer
def inner(*args,**argss): #可接收任意参数
print("你好!")
r = func(*args,**argss)
print("再见!")
return r
return inner
def outer_1(func): #装饰器outer_1
def inner(*args,**argss):
print("欢迎来到测试系统!")
r = func(*args,**argss)
return r
return inner
@outer_1 #相当于outer_1(f2)
@outer #相当于outer(f2)
def f2(a1,a2): #此函数若需要添加一些额外的功能,不改变原函数代码的情况可以使用装饰器
return a1 + a2
@outer_1
@outer
def f3(a1,a2,a3):
return a1 + a2 +a3
print(f2(1,2))
print(f3(1,2,3))

内置函数

常用

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
abs()     #取绝对值
all() #循环参数,如果每个元素为真,那么all的返回值为真,0,None,空值为假,其余为真
any() #循环参数,只要一个元素为真,则返回值为真
bin() #二进制,0b表示
oct() #八进制,0o表示
int() #十进制
hex() #十六进制,0x表示
bool() #转换成布尔值,返回真或假
bytes() #转换为字节类型
str() #转换为字符类型
chr() #接收一个数字,找到对应的字符,c=chr(65) ,c的值为A
ord() #接收一个字符,找到对应的数字, c=ord("A"),c的值为65
dir() #查看帮助
help() #查看帮助
divmod() #取商和余数
enumrate() #为可迭代的对象添加序号
eval() #执行一个字符串形式的表达式,有返回值
filter() #过滤器,循环可迭代的对象,获取每一个参数,函数(参数),filter(函数,可迭代的对象)
map() #map(函数,可迭代的对象)
globals() #获取所有全局变量,返回一个字典
locals() #获取所有局部变量,返回一个字典
id() #查看变量的内存地址,如a="li",id(a)
input() #接受一个标准输入数据,返回为 string 类型,与python2的写法不同,2为raw_input()
isinstance() #判断一个变量是否是某种类型,返回True/False
len() #输出一个变量的长度,可测量str,列表,元组,字典的长度
max() #取最大值
min() #取最小值
pow() #取幂数
round() #对小数四舍五入
range() #可创建一个整数列表,一般用在 for 循环中,用法为:range(start, stop[, step]),>=start,<stop,step为步长
sorted() #对所有可迭代的对象进行排序操作,sort只用于列表,用法为:sorted(iterable, key=None, reverse=False),reverse=True表示降序,False表示升序(默认),生成新的对象,数字和字符串无法比较,字符串根据bytes值排序
sum() #求和
type() #查看对象的类型
open() #打开文件,用法为:open(name[, mode[, buffering]]),name为文件名,mode为打开方式,buffering可省略
list() #可定义一个列表,也可用于将元组转换为列表。
tuple() #可定义一个元组,也可用于将列表转换为元组。
dict() #可创建一个字典
set() #可创建一个无序不重复元素集,可进行关系测试,删除重复数据,还可以计算交集、差集、并集等。

用法示例

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
abs(-1)    #返回值为1
all([1,0]) #0为假,返回False
any([1,0]) #1为真,返回True
bin(17) #十进制转二进制
act(17) #十进制转八进制
hex(17) #十进制转十六进制
int('0b11',base=2) #二进制转换为十进制,输出为3,0b可有可无,base=2表示二进制
int('0o11',base=8) #八进制转换为十进制,输出为9,0o可有可无
int('0x11',base=16) #十六进制转换为十进制,输出为17 ,0x可有可无
bool(1) #返回值为True
bytes("liyunliang",encoding="utf-8") #str转换为bytes,以uft-8的格式编码
str(b"liyunliang",encoding="utf-8") #bytes转换为str,以utf-8的格式编码
chr(65) #输出为字符A
ord("A") #输出为数字65
dir(hash) #查看hash有关的用法
help(hash) #查看hash有关的用法
divmod(10,3) #输出为元组(3,1)
li = [11,22,33]
for k,v in enumerate(li, 1): #不指定为1的话默认从0开始
print(k,v) #输出为1 11 2 22 3 33
eval("1+2") #输出为数字3
eval("a+2",{"a":1}) #输出为数字3
def f1(x):
if x > 22:
return True
else:
return False
ret=filter(f1,[11,22,33,44]) #ret为可迭代的filter对象
for i in ret:
print(i) #输出为过滤得到的数字33和44
ret=map(f1,[11,22,33,44]) #ret为可迭代的map对象
for i in ret:
print(i) #输出为False,False,True,True
id(1) #查看数字1的内存地址
u=input("请输入用户名:") #则输入的数据为用户名
isinstance(1,(int)) #判断1是否属于int类型,返回True,判断单个类型()可加可不加;isinstance(1,(int,str)),判断1是否属于int或者str类型
len("li") #返回值为2
max([11,22,33]) #返回值为33
min([11,22,33]) #返回值为11
pow(2, -1) #返回值为0.5,2的-1次方
round(0.654,2) #返回值为0.65,2表示保留两位小数
sorted([22,44,11,33]) #返回值为[11,22,33,44]
sorted([11,22,44,33],key=lambda x: x*-1) #返回值为[44,33,22,11],利用key来降序
sorted([11,22,44,33],reverse=True) #返回值为[44,33,22,11]
sum([11,22,33,44]) #返回值为110
type(1) #可查看1的类型

f = open('test.txt','r') #以只读的方式打开test.txt
f.read([size]) #size未指定则返回整个文件,如果文件大小>2倍内存则有问题.f.read()读到文件尾时返回""(空字串)
f.readline() #读取一行
f.readlines([size]) #返回包含size行的列表,size 未指定则返回全部行
for line in f: print line #通过迭代器访问
f.write("hello\n") #如果要写入字符串以外的数据,先将他转换为字符串.
f.tell() #返回一个整数,表示当前文件指针的位置(就是到文件头的比特数).
f.seek(偏移量,[起始位置]) #用来移动文件指针.
f.close() #关闭文件
with open('test.txt','r') as f: #以只读的方式打开文件test.txt,不需要close文件
模式说明:
r #以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
rb #以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。
r+ #打开一个文件用于读写。文件指针将会放在文件的开头。
rb+ #以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。
w #打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
wb #以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
w+ #打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
wb+ #以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
a #打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
ab #以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
a+ #打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
ab+ #以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。

用户登录(密码文件)

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
#!/usr/bin/env python
# 基于密码数据文件的用户登录逻辑
import hashlib
def register(user,pwd):
'''
提供用户注册功能
:param user:
:param pwd:
:return:
'''
with open('db','a',encoding="utf-8") as f1:
f1.write(user+'|'+jiami(pwd)+'\n')

def jiami(pwd):
'''
提供密码MD5加密功能
:param pwd:
:return:
'''
temp = hashlib.md5(bytes('curry',encoding="utf-8"))
temp.update(bytes(pwd,encoding="utf-8"))
return temp.hexdigest()

def login(user,pwd):
'''
提供用户登录功能
:param user:
:param pwd:
:return:
'''
with open('db','r',encoding="utf-8") as f2:
for line in f2:
u = line.strip().split("|")[0]
p = line.strip().split("|")[1]
if u == user and p == jiami(pwd):
return True
else:
return False

def chpwd(user,pwd):
'''
提供用户修改密码功能
:param user:
:param pwd:
:return:
'''
new_data = ""
with open('db','r',encoding="utf-8") as f3:
for line in f3:
u = line.strip().split("|")[0]
p = line.strip().split("|")[1]
if u == user and p == jiami(pwd):
new_pwd = input("请输入新的密码:")
line = line.replace(p,jiami(new_pwd)) #文件内容替换
else:
pass
new_data += line
with open('db','w',encoding="utf-8") as f4:
f4.write(new_data)
print("密码更改成功")

def main():
'''
主函数
:return:
'''
i = input("1.登录,2.注册,3.修改密码")
if i == "2":
user = input("用户名:")
pwd = input("密码:")
register(user,pwd)
elif i == "1":
user = input("用户名:")
pwd = input("密码:")
ret = login(user,pwd)
if ret:
print("登录成功")
else:
print("登录失败")
elif i == "3":
user = input("用户名:")
pwd = input("密码:")
chpwd(user,pwd)

if __name__ == "__main__":
main()

加密

(1)丶设计一个函数,对传入的字符串(假设字符串中只包含小写字母和空格)进行加密操作,
加密的规则是a变d,b变e,c变f,…….,x变a,y变b,z变c,空格不变,返回加密后的字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env python
# -*- coding=utf-8 -*-
def jiami(arg):
temp = ''
for i in arg:
if i == ' ':
temp += i
elif ord(i) < 120:
temp += chr(ord(i) + 3)
else:
temp += chr(ord(i) - 23)
return temp

inp = input("请输入字符串(只包含小写字母和空格):")
new_inp = jiami(inp)
print(new_inp)

不常用

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
ascii()       #对象的类中找_repr_,获取其返回值
例:
class Foo:
def _repr_(self):
return "hello"

r=ascii(Foo())
print(r) #返回值为<__main__.Foo object at 0x013E8B10>

bytearray() #字节列表
callable() #是否可执行,返回True/False,例如函数可执行,返回True
compile() #接收一个字符串,把该字符串编译为python可执行的代码
exec() #与eval类似,无返回值,只执行代码
例:
exec("for i in range(10):print(i)")
hash() #得到一个对象的哈希值,如字典key,hash("liyun"),输出为哈希值:-416968271
issubclass() #用于判断参数 class 是否是类型参数 classinfo 的子类,语法为:issubclass(class, classinfo)
例:
class A:
pass
class B(A):
pass
issubclass(B,A) #返回值为True
iter() #用来生成迭代器,语法为:iter(object[, sentinel])
例:
for i in iter([11,22,33]):
print(i)
obj = iter([11,22,33]) #创建一个可迭代的对象
print(next(obj)) #从11开始取值,每次取下一个值
reversed() #反转,生成一个可迭代的对象
例:
for i in reversed([11,44,33]):
print(i) #输出为33 44 11
slice() #根据索引切片
例:
[11,22,33,44,55,66][slice(1,5,2)] #输出为[22,44],列表截取1-4元素布长为2的切片
zip() #用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组
例:
li1 = [1,2,3,4]
li2 = ["a","b","c","d"]
r = zip(li1 ,li2)
for i in r:
print(i) #输出为:(1,'a') (2,'b') (3,'c') (4,'d')

正则表达式re

常用符号

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
'^'  #匹配字符串的开头,若放在[]内,则表示非。
re.findall('^s','sb') #输出为:['s']
re.findall('[^s]','bssim') #输出为:['b', 'i', 'm']

'$' #匹配字符串的末尾。
re.findall('b$','sb') #输出为:['b']

'.' #匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。
re.findall('.','bssim\nc') #输出为:['b', 's', 's', 'i', 'm', 'c']

'*' #匹配0个或多个的表达式。
re.findall('.*m','bssim\nc') #输出为:['bssim']
re.findall('.*c','bssim\nc') #输出为:['c']

'+' #匹配1个或多个的表达式。
re.findall('.+c','bssim\nc') #输出为:[]
re.findall('.+m','bssim\nc') #输出为:['bssim']

'?' #匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式
re.findall('.?m','bssim\nc') #输出为:['im']
re.findall('.m?','bssim\nc') #输出为:['b', 's', 's', 'im', 'c']

'|' #或运算
re.findall('s|i','bssim\nc') #输出为:['s', 's', 'i']

'{m}' #匹配前一个字符m次
re.findall('ab{2}','abb abc abbcbbb') #输出为:['abb', 'abb']

'{n,m}' #匹配前一个字符n到m次
re.findall("ab{1,3}","abb abc abbcbbb") #输出为:['abb', 'ab', 'abb']

'(...)' #分组匹配

'\' #后面接常用符号,可将其普通化,接普通字符,可将其特殊化

'\A' #从字符开头匹配
re.findall("\Aabc","alexabc") #从开头匹配'abc',输出为:[],匹配不到

'\Z' #匹配字符结尾,同'$'

'\d' #匹配数字0-9
re.findall('\d','ab1cd2ef3') #输出为:['1','2','3']

'\D' #匹配非数字
re.findall('\D','ab1cd2ef3') #输出为:['a','b','c','d','e','f']

'\w' #匹配字母和数字和下划线
re.findall('\w','a1$_#c2') #输出为:['a','1','_','c','2']

'\W' #匹配非字母和数字和下划线
re.findall('\W','a1_$#c2') #输出为:['$','#']

'\s' #匹配空白字符,如换行符等
re.findall('\s','a\t\nb') #输出为:['\t','\n']

'\S' #匹配任何非空白字符,除换行符等除外

'\1' #表示对应的分组在此处出现一次,如'(ab)(cd)\1\2',则\1实际指的是(ab),\2指的是(cd)

方法

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
re.findall()            #把所有匹配到的字符放到以列表中的元素返回
re.findall(string, start, end) #可以与re.compile()一起使用,字符串指定位置start到end查找
re.findall('\d+a','b13ac4ad') #输出['13a', '4a']
re.findall('(\d+)a','b13ac4ad') #输出['13', '4'],找到13a和4a,并去掉a输出
re.findall('((\d+)a)','b13ac4ad') #输出[('13a', '13'), ('4a', '4')],组内再分组
re.findall('(\w+){4}','lishizheng') #输出['g'],(\w)虽然重复了四次,但是表达式只有一个,默认输出末尾字符

re.match(pattern, string, flags) #从头开始匹配,re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。
r1 = re.match('h\w+','hello world')
r2 = re.match('(h)(\w+)','hello world')
r3 = re.match('(?P<n1>h)(?P<n2>\w+)','hello world')
print(r1.group(),r1.groups(),r1.groupdict()) #输出为hello () {} ,用法和search相同
print(r2.group(),r2.groups(),r2.groupdict()) #输出为hello ('h', 'ello') {}
print(r3.group(),r3.groups(),r3.groupdict()) #输出为hello ('h', 'ello') {'n1': 'h', 'n2': 'ello'}

re.search(pattern, string, flags) #匹配整个字符串,直到找到一个匹配,返回一个match对象,未匹配成功返回None
re.search(pattern, string, flags).group() #group()默认等于group(0),即所有的元素,输出为字符串
re.search('www', 'www.runoob.com').span()) #可查看匹配的位置

re.sub(pattern, repl, string, count,flag) #匹配字符并替换,pattern为正则,repl为需要替换成的字符串,也可为函数,string为原始字符串,count为匹配模式后替换的最大数量,flag为标志位
re.sub('[0-9]','|', 'a1b2c3d e8',count=2) #输出为新的字符串:'a|b|c3d e8'
re.sub('[0-9]','|', 'a1b2c3d e8') #没有count或者等于0默认全部替换,输出为新的字符串:'a|b|c|d e|'

re.compile() #编译正则表达式
rule = re.compile('[0-9]',re.I) #将正则编译放到一个变量
rule.split('a1b2c3d e8') #根据这个规则来进行分割,输出为:['a', 'b', 'c', 'd e', '']
rule.findall('run88oob123google456', 0, 10) #查找字符串0-10的位置的所有数字,输出为:['8','8','1','2']

re.finditer(pattern, string, flags=0) #和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。

re.split() #将匹配到的格式当做分割点对字符串分割成列表
re.split('[0-9]', 'a1b2c3d e8') #输出为:['a', 'b', 'c', 'd e', '']
re.split('(ab)','123ab456ab789',1) #输出为:['123', 'ab', '456ab789'],加()表示连表达式匹配一起输出,1表示匹配一次,默认匹配多次

flag说明
re.I #使匹配对大小写不敏感
re.L #做本地化识别(locale-aware)匹配
re.M #多行匹配,影响 ^ 和 $
re.S #使 . 匹配包括换行在内的所有字符
re.U #根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
re.X #该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。

正则表达式之计算器

用户输入数学表达式,含+-/和(),计算结果,例如:’1 - 2 ((60-30 +(-40/5) (9-25/3 + 7 /399/42998 +10 568/14 )) - (-43)/ (16-3*2))’

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#! /usr/bin/env python
# -*- coding:utf-8 -*-
import re
def f1(arg):
sum1 = eval(arg) #执行一个字符串形式的算术表达式
return sum1

inp = input("请输入您要计算的数学表达式,其中包含加减乘除:")
exp = inp
while True:
list = re.split('\(([^()]+)\)', exp , 1) #根据第一个括号内不含括号的表达式进行分割
if len(list) == 3:
temp1 = f1(list[1])
temp2 = list[0] + str(temp1) +list[2]
exp = temp2
else:
sum = f1(list[0])
break
print("%s = %d" %(inp,sum))

常用模块

time

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import time             #导入time模块,如果执行`from time import time`,则调用时少写一个time
print(time.clock()) #返回处理器时间,3.3开始已废弃 , 改成了time.process_time()测量处理器运算时间,不包括sleep时间,不稳定,mac上测不出来输出为:8.552505542023591e-07
print(time.altzone) #返回与utc时间的时间差,以秒计算,输出为:-32400
rint(time.asctime()) #返回时间格式"Fri Aug 19 11:14:16 2016",输出为:Tue Mar 27 13:45:09 2018
print(time.localtime()) #返回本地时间 的struct time对象格式,输出为:time.struct_time(tm_year=2018, tm_mon=3, tm_mday=27, tm_hour=13, tm_min=45, tm_sec=9, tm_wday=1, tm_yday=86, tm_isdst=0)
print(time.gmtime(time.time()-800000)) #返回utc时间的struc时间对象格式,输出为:time.struct_time(tm_year=2018, tm_mon=3, tm_mday=17, tm_hour=23, tm_min=31, tm_sec=49, tm_wday=5, tm_yday=76, tm_isdst=0)
print(time.asctime(time.localtime())) #输出为:Tue Mar 27 13:45:09 2018
print(time.ctime()) #输出为:Tue Mar 27 13:45:09 2018
truct = time.strptime("2016/05/22","%Y/%m/%d") #将日期字符串 转成 struct时间对象格式
print(string_2_struct) #输出为:time.struct_time(tm_year=2016, tm_mon=5, tm_mday=22, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=6, tm_yday=143, tm_isdst=-1)
struct_2_stamp = time.mktime(string_2_struct) #将struct时间对象转成时间戳
print(struct_2_stamp) #输出为:1463846400.0
print(time.gmtime(time.time()-86640)) #将utc时间戳转换成struct_time格式,输出为:time.struct_time(tm_year=2018, tm_mon=3, tm_mday=26, tm_hour=5, tm_min=49, tm_sec=7, tm_wday=0, tm_yday=85, tm_isdst=0)
print(time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime())) #将utc struct_time格式转成指定的字符串格式,输出为:2018-03-27 05:53:07
print(time.strftime('%Y%m%d%H%M',time.localtime(time.time()))) #取本地时间的时间戳,输出为:201803271406
print(time.strftime('%Y%m%d%H%M',time.localtime())) #取本地时间的时间戳,输出为:201803271406
print(time.strftime('%Y%m%d%H%M')) #取本地时间的时间戳,输出为:201803271406

datetime

1
2
3
4
5
6
7
8
9
10
import datetime    #导入datetime模块
print(datetime.datetime.now()) #输出为:2018-03-27 13:56:12.918226
print(datetime.date.fromtimestamp(time.time())) #输出为:2018-03-27
print(datetime.datetime.now() + datetime.timedelta(3)) #当前时间加三天,输出为:2018-03-30 13:58:55.264512
print(datetime.datetime.now() + datetime.timedelta(-3)) #当前时间减三天,输出为:2018-03-24 13:58:55.264512
print(datetime.datetime.now() + datetime.timedelta(hours=3)) #当前时间加三小时,输出为:2018-03-27 16:58:55.264512
print(datetime.datetime.now() + datetime.timedelta(minutes=30)) #当前时间加30分钟
print(datetime.datetime.now() + datetime.timedelta(weeks=1)) #当前时间加一周
c_time = datetime.datetime.now()
print(c_time.replace(minute=3,hour=2)) #时间替换

sys

1
2
3
4
5
6
7
8
9
import sys         #导入sys模块
sys.argv #命令行参数List,执行python文件时可以传入多个参数,参数以列表的形式保存,第一个元素是程序本身路径
sys.exit(n) #退出程序,正常退出时exit(0)
sys.version #获取Python解释程序的版本信息
sys.maxint #最大的Int值
sys.path #返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值,默认当前路径优先,python\lib\site-packages 路径存放所有第三方安装的模块
sys.platform #返回操作系统平台名称
sys.stdout.write('please:')
val = sys.stdin.readline()[:-1]

进度条作业

1
2
3
4
5
6
7
8
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import sys,time
for i in range(31):
sys.stdout.write('\r') #清除屏幕输出
sys.stdout.write('%s%% | %s' %(int(i/30*100),int(i/30*100)*'*'))
sys.stdout.flush() #刷新,每一次都输出
time.sleep(0.5)

将用户传入的参数变为文件夹

#例如文件名为createdir.py,则执行`python create.py a b c`就会在当前目录新建a,b,c三个目录
1
2
3
4
5
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import sys,os
for i in range(1,len(sys.argv)):
os.mkdir(sys.argv[i])

pickle和json

用于序列化和反序列化的两个模块,提供了四个功能:dumps、dump、loads、load,pickle用于python内部,json可与其他语言共用

1
2
3
4
pickle.loads()     #将字符串转化为python数据类型列表,元组,字典,可从文件中读取列表,元组,字典类型的数据,主要使用带s的    
pickle.load()
pickle.dumps() #将python数据类型转化为字符串,与open结合可将列表,元组,字典类型的数据放进文件中
pickle.dump()

购物车相关

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import pickle
account_info ={
1:{
'name':'liyunliang',
'passwd':'lylapqh',
'tel':'13888675421',
'balance':15000
}
}
f = open('account_db','wb')
f.write(pickle.dumps(account_info)) #将字典的信息写进数据文件中
# pickle.dump(account_info,f) 和上面等价
f.close()
1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import pickle
account_file = open('account_db','rb')
account_dic = pickle.loads(account_file.read()) #将数据文件读到字典里
# account_dic = pickle.load(account_file) 和上面等价
account_file.close()
account_dic[1]['balance'] -= 500 #购物后找到对应人账户余额减去商品价格
f = open('account_db','wb')
f.write(pickle.dumps(account_dic)) #将新的字典写入数据文件
f.close()

os

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
os.getcwd()                 #获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname") #改变当前脚本工作目录;相当于shell下cd
os.curdir #返回当前目录: ('.')
os.pardir #获取当前目录的父目录字符串名:('..')
os.makedirs('dir1/dir2') #可生成多层递归目录
os.removedirs('dirname1') #若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname') #生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname') #删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname') #列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove() #删除一个文件
os.rename("oldname","new") #重命名文件/目录
os.stat('path/filename') #获取文件/目录信息
os.sep #操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
os.linesep #当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
os.pathsep #用于分割文件路径的字符串
os.name #字符串指示当前使用平台。win->'nt'; Linux->'posix'
os.system("bash command") #运行shell命令,直接显示
os.environ #获取系统环境变量
os.path.abspath(path) #返回path规范化的绝对路径
os.path.split(path) #将path分割成目录和文件名二元组返回
os.path.dirname(path) #返回path的目录。其实就是os.path.split(path)的第一个元素
os.path.basename(path) #返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
os.path.exists(path) #如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path) #如果path是绝对路径,返回True
os.path.isfile(path) #如果path是一个存在的文件,返回True。否则返回False
os.path.isdir(path) #如果path是一个存在的目录,则返回True。否则返回False
os.path.join(path1[, path2[, ...]]) #将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
os.path.getatime(path) #返回path所指向的文件或者目录的最后存取时间
os.path.getmtime(path) #返回path所指向的文件或者目录的最后修改时间

hashlib

用于加密相关的操作,代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法

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
import hashlib

# ######## md5 ########
hash = hashlib.md5()
# help(hash.update)
hash.update(bytes('admin', encoding='utf-8'))
print(hash.hexdigest())
print(hash.digest())

######## sha1 ########
hash = hashlib.sha1()
hash.update(bytes('admin', encoding='utf-8'))
print(hash.hexdigest())

# ######## sha256 ########
hash = hashlib.sha256()
hash.update(bytes('admin', encoding='utf-8'))
print(hash.hexdigest())

# ######## sha384 ########
hash = hashlib.sha384()
hash.update(bytes('admin', encoding='utf-8'))
print(hash.hexdigest())

# ######## sha512 ########
hash = hashlib.sha512()
hash.update(bytes('admin', encoding='utf-8'))
print(hash.hexdigest())

以上加密算法虽然依然非常厉害,但时候存在缺陷,即:通过撞库可以反解。所以,有必要对加密算法中添加自定义key再来做加密。
# ######## md5 ########
hash = hashlib.md5(bytes('898oaFs09f',encoding="utf-8"))
hash.update(bytes('admin',encoding="utf-8"))
print(hash.hexdigest())

hmac

python内置还有一个 hmac 模块,它内部对我们创建 key 和 内容 进行进一步的处理然后再加密

1
2
3
4
import hmac 
h = hmac.new(bytes('898oaFs09f',encoding="utf-8"))
h.update(bytes('admin',encoding="utf-8"))
print(h.hexdigest())

random

1
2
3
4
import random
print(random.random()) #随机生成0-1之间的小数
print(random.randint(1, 2)) #随机生成1或者2
print(random.randrange(1, 10)) #随机生成1-10中的一个数

4位的随机数验证码。

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/usr/bin/env python
# -*- coding=utf-8 -*-
import random
while True:
temp=""
for i in range(4):
num = random.randrange(0,4)
if num == 0 or num == 2:
rad1 = random.randrange(0,10)
temp += str(rad1)
else:
rad2 = random.randrange(65,91)
temp += chr(rad2) #chr()为找到数字对应的字符
print(temp)
shuru = str(input("请输入验证码:"))
if shuru == temp:
break
else:
pass

XML

XML是实现不同语言或程序之间进行数据交换的协议,XML文件格式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<data>
<country name="Liechtenstein">
<rank updated="yes">2</rank>
<year>2023</year>
<gdppc>141100</gdppc>
<neighbor direction="E" name="Austria" />
<neighbor direction="W" name="Switzerland" />
</country>
<country name="Singapore">
<rank updated="yes">5</rank>
<year>2026</year>
<gdppc>59900</gdppc>
<neighbor direction="N" name="Malaysia" />
</country>
<country name="Panama">
<rank updated="yes">69</rank>
<year>2026</year>
<gdppc>13600</gdppc>
<neighbor direction="W" name="Costa Rica" />
<neighbor direction="E" name="Colombia" />
</country>
</data>

操作XML

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
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from xml.etree import ElementTree as ET #解析文件或者字符串,做修改,都在内存中进行,原对象不改变,如需修改得重新write写入
str_xml = open('xo.xml', 'r').read() #打开文件,读取XML内容,内容为xml格式的字符串
print(ET.XML(str_xml)) #将xml公司的字符串解析成xml特殊对象,获取xml文件的根节点
print(ET.parse("xo.xml")) #直接解析xml文件
print(ET.parse("xo.xml").getroot()) #获取xml文件的根节点
print(ET.parse("xo.xml").getroot().tag) #顶层标签
root = ET.parse("xo.xml").getroot() #与下面的相同
root = ET.XML(str_xml)

for child in root: #遍历XML文档的第二层
print(child.tag, child.attrib) #第二层节点的标签名称和标签属性
for i in child: #遍历XML文档的第三层
print(i.tag,i.text) #第二层节点的标签名称和内容

for node in root.iter('year'): #遍历XML中所有的指定的year节点
print(node.tag, node.text) #节点的标签名称和内容

for node in root.iter('year'): #循环所有的year节点
new_year = int(node.text) + 1 #将year节点中的内容自增1
node.text = str(new_year)
node.set('name', 'SubHy') #设置属性
node.set('age', '18')
del node.attrib['name'] #删除属性
tree = ET.ElementTree(root) #保存文件
tree.write("newnew.xml", encoding='utf-8')

缩进的保存一个XML文件

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
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from xml.etree import ElementTree as ET
from xml.dom import minidom
def mkxml(elem,filename):
rough_string = ET.tostring(elem,'utf-8')
reparsed = minidom.parseString(rough_string)
raw_str = reparsed.toprettyxml(indent="\t")
f = open(filename,'w',encoding='utf-8')
f.write(raw_str)
f.close()


root = ET.Element("famliy") # 创建根节点
# son1 = ET.Element('son', {'name': '儿1'}) #创建大儿子
son1 = root.makeelement('son', {'name': '儿1'})
# son2 = ET.Element('son', {"name": '儿2'}) #创建小儿子
son2 = root.makeelement('son', {"name": '儿2'})
# grandson1 = ET.Element('grandson', {'name': '儿11'}) #在大儿子中创建两个孙子
grandson11 = son1.makeelement('grandson', {'name': '儿11'})
# grandson2 = ET.Element('grandson', {'name': '儿12'})
grandson12 = son1.makeelement('grandson', {'name': '儿12'})
son1.append(grandson11) #把孙子添加到儿子1节点中
son1.append(grandson12)
root.append(son1) #把儿子添加到根节点中
root.append(son2)
mkxml(root,"xxxoo.xml")

xml命名空间,例如以H代指一个字符串”http://www.company.com"

1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from xml.etree import ElementTree as ET
ET.register_namespace('H',"http://www.company.com") #some name
# build a tree structure
root = ET.Element("{http://www.company.com}STUFF")
body = ET.SubElement(root, "{http://www.company.com}MORE_STUFF", attrib={"{http://www.company.com}hhh": "123"})
body.text = "STUFF EVERYWHERE!"
# wrap it in an ElementTree instance, and save as XML
tree = ET.ElementTree(root)
tree.write("page.xml",xml_declaration=True,encoding='utf-8',method="xml")

requests第三方模块

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 requests,json
ret = requests.get('https://github.com/timeline.json') #无参数示例,get请求
print(ret.url) #输出请求网址的地址字符串类型'https://github.com/timeline.json'
print(ret.text) #返回请求解析得到的字符串内容
print(ret.content) #返回解析的二进制数据
print(ret.cookies) #输出请求网址的cookies信息
print(ret.headers) #输出请求网址的headers所有信息
print(ret.status_code) #输出请求页面的状态(状态码)
print(ret.history) #输出请求的历史记录(以列表的形式显示)
print(requests.codes.ok) #requests请求状态码,为200
ret.encoding = 'utf-8' #当解析到的输出乱码时,可设置编码

payload = {'key1': 'value1', 'key2': 'value2'}
ret = requests.get("http://httpbin.org/get", params=payload) #有参数示例,get请求
print(ret.url) #返回字符串'http://httpbin.org/get?key1=value1&key2=value2'
print(ret.text)

ret = requests.post("http://httpbin.org/post", data=payload) #基本POST请求示例
print(ret.text)

url = 'https://api.github.com/some/endpoint'
payload = {'some': 'data'}
headers = {'content-type': 'application/json'}
ret = requests.post(url, data=json.dumps(payload), headers=headers) #发送请求头和数据实例
print(ret.text)
print(ret.cookies)

QQ号是否在线检测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/usr/bin/env python
# -*- coding:utf-8 -*-
#输入参数:QQ号码 String。返回数据:String,Y = 在线;N = 离线;E = QQ号码错误;A = 商业用户验证失败;V = 免费用户超过数量
import requests
from xml.etree import ElementTree as ET
def qqonlinedetect(args):
r = requests.get('http://www.webxml.com.cn//webservices/qqOnlineWebService.asmx/qqCheckOnline?qqCode='+args)
result = r.text
node = ET.XML(result) #解析XML格式内容
if node.text == "Y": #获取内容
return True
else:
return False
if __name__ == "__main__":
ret = qqonlinedetect(input("请输入QQ号:"))
if ret:
print("您的QQ号在线")
else:
print("您的QQ号离线")

列车时刻表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import urllib
import requests
from xml.etree import ElementTree as ET
#使用内置模块urllib发送HTTP请求,或者XML格式内容,该例中车次为:K113
"""
f = urllib.request.urlopen('http://www.webxml.com.cn/WebServices/TrainTimeWebService.asmx/getDetailInfoByTrainCode?TrainCode=K113&UserID=')
result = f.read().decode('utf-8')
"""
#使用第三方模块requests发送HTTP请求,获取XML格式内容
r = requests.get('http://www.webxml.com.cn/WebServices/TrainTimeWebService.asmx/getDetailInfoByTrainCode?TrainCode=K113&UserID=')
result = r.text
root = ET.XML(result) # 解析XML格式内容
for node in root.iter('TrainDetailInfo'):
print(node.find('TrainStation').text,node.find('StartTime').text,node.find('KM').text)

configparser

configparser用于处理特定格式的文件,其本质上是利用open来操作文件。
xx文件如下

1
2
3
4
5
6
[section1]  # 节点
k1 = v1 # 值
k2:v2 # 值

[section2] # 节点
k1 = v1 # 值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import configparser
config = configparser.ConfigParser()
config.read('xx', encoding='utf-8')
ret = config.sections() #获取所有节点
ret = config.items('section1') #获取指定节点下所有的键值对
ret = config.options('section1') #获取指定节点下所有的键
v = config.get('section1','k1') #获取指定节点下的key
has_sec = config.has_section('section1') #检查指定节点是否在config中,返回True/False
config.add_section("SEC_1") #添加一个节点,可以写到原文件,也可生成新文件
config.write(open('xx', 'w'))
config.remove_section("section1") #移除一个节点
config.write(open('xx', 'w'))
has_opt = config.has_option('section2', 'k1') #检测指定节点和key是否在config中,同时存在返回True,否则返回False
config.remove_option('section1', 'k1') #删除指定节点下的key及对应的值
config.write(open('xx', 'w'))
config.set('section1', 'k10', "123") #新增一个节点,新增对应的key和值
config.write(open('xx', 'w'))

logging

用于便捷记录日志且线程安全的模块。
注:只有【当前写等级】大于【日志等级】时,日志文件才被记录。
日志等级:

1
2
3
4
5
6
7
8
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0

单文件日志记录

1
2
3
4
5
6
7
8
9
10
11
12
import logging
logging.basicConfig(filename='log.log', #定义日志的格式,以及写等级
format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S %p',
level=10) #level=10也可以换成level=logging.DEBUG

logging.debug('debug')
logging.info('info')
logging.warning('warning')
logging.error('error')
logging.critical('critical')
logging.log(10,'debug') #用法和logging.debug一致

多文件日志记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import logging
# 定义文件
file_1_1 = logging.FileHandler('l1_1.log', 'a', encoding='utf-8')
fmt = logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s")
file_1_1.setFormatter(fmt)
file_1_2 = logging.FileHandler('l1_2.log', 'a', encoding='utf-8')
fmt = logging.Formatter()
file_1_2.setFormatter(fmt)
# 定义日志
logger1 = logging.Logger('s2', level=logging.DEBUG)
logger1.addHandler(file_1_1)
logger1.addHandler(file_1_2)
# 写日志
logger1.critical('1111')

subprocess

用于执行shell命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import subprocess
ret1 = subprocess.check_output(["echo","lyl"]) #执行命令不显示结果,如果正确执行 ,则返回执行结果(字节方式),否则抛异常
ret2 = subprocess.call("echo lyl") #执行命令并显示结果,如果正确执行 ,则返回0,否则抛异常
ret3 = subprocess.check_call("echo lyl") #执行命令并显示结果,如果正确执行 ,则返回0,否则抛异常
ret4 = subprocess.Popen("echo lyl") #执行命令并显示结果,如果正确执行,返回值为Popen对象
print(ret1,ret2,ret3,ret4)

# 进入某环境,依赖再输入,如:python
obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
obj.stdin.write("print(1)\n") #执行的命令
obj.stdin.write("print(2)")
obj.stdin.close()
cmd_out = obj.stdout.read() #输出
obj.stdout.close()
cmd_error = obj.stderr.read() #错误
obj.stderr.close()
print(cmd_out) #输出:1,2
print(cmd_error)

out_error_list = obj.communicate()
print(out_error_list) #输出:('1\n2\n', '')

out_error_list = obj.communicate('print("hello")') #可直接接收命令并输出
print(out_error_list) #输出:('hello\n', '')

shutil

可进行高级的文件、文件夹、压缩包处理

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
shutil.copyfileobj(open('old.xml','r'), open('new.xml', 'w'))         #拷贝文件
shutil.copyfile('f1.log', 'f2.log') #拷贝文件
shutil.copymode('f1.log', 'f2.log') #仅拷贝权限,内容、组、用户均不变,文件不存在会报错
shutil.copystat('f1.log', 'f2.log') #仅拷贝状态的信息,包括:mode bits, atime, mtime, flags,文件不存在会报错
shutil.copy('f1.log', 'f2.log') #拷贝文件和权限
shutil.copy2('f1.log', 'f2.log') #拷贝文件和状态信息
shutil.copytree("G:\mysite", "G:\mysite1",ignore=shutil.ignore_patterns('*.pyc', 'tmp*')) #递归拷贝文件夹,忽略pyc类型的文件和tmp开头的文件
shutil.rmtree("G:\mysite1") #递归的删除文件夹
shutil.move("G:\mysite", "G:\mysite1") #递归的去移动文件,它类似mv命令,其实就是重命名

# shutil.make_archive(base_name, format,...)
# 创建压缩包并返回文件路径,例如:zip、tar
#base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
# 如:www =>保存至当前路径
#如:/Users/wupeiqi/www =>保存至/Users/wupeiqi/
# format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
# root_dir: 要压缩的文件夹路径(默认当前目录)
# owner: 用户,默认当前用户
# group: 组,默认当前组
# logger: 用于记录日志,通常是logging.Logger对象
shutil.make_archive("G:\\aaaaa","zip",root_dir="G:\mysite") #将G:\mysite下的文件打包到G:\aaaaa.zip

# shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的
import zipfile
z = zipfile.ZipFile('laxi.zip', 'w') #压缩后的文件为laxi.zip
z.write('log.log') #往压缩文件添加内容
z.write('xx')
z.close()
z = zipfile.ZipFile('laxi.zip', 'a') #以追加的方式打开
z.write('a1.py') #往压缩文件中追加文件
z.close()
z = zipfile.ZipFile('laxi.zip', 'r') #解压缩
z.extractall() #全部解压
print(z.namelist()) #查看压缩包里的文件
z.extract(member="log.log") #指定文件解压
z.close()

import tarfile
tar = tarfile.open('your.zip','w') #压缩后的文件为you.zip
tar.add('log.log', arcname='new.log') #往压缩文件添加内容并改文件名
tar.add('xx', arcname='cmdb.log')
tar.close()
tar = tarfile.open('your.zip','r')
print(tar.getnames()) #查看压缩包里的文件
tar.extractall() #全部解压
tar.extract(member="new.log")
tar.close()

paramiko

paramiko是一个用于做远程控制的模块,使用该模块可以对远程服务器进行命令或文件操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('192.168.1.2', 22, 'root', 'rootadmin') #使用用户名和密码远程执行命令
# private_key_path = '/home/auto/.ssh/id_rsa' #密钥认证来远程执行
# key = paramiko.RSAKey.from_private_key_file(private_key_path)
# ssh.connect('192.168.1.2', 22, 'root', key)
stdin, stdout, stderr = ssh.exec_command('df -h')
print (stdout.read())
ssh.close()

import os,sys,paramiko
t = paramiko.Transport(("192.168.229.70",22))
t.connect(username="root",password="rootadmin")
# pravie_key_path = '/home/auto/.ssh/id_rsa' #密钥认证
# key = paramiko.RSAKey.from_private_key_file(pravie_key_path)
# t.connect(username='root',pkey=key)
sftp = paramiko.SFTPClient.from_transport(t)
sftp.put("a1.py","/tmp/test.py") #服务器上传文件
sftp.get("/mancenter-3.9.3.war","G:\\mancenter.war") #服务器下载文件
t.close()

模块拾遗

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env python
# -*- coding:utf-8 -*-
print(vars()) #python自带的全局变量
print(__doc__) #py文件的注释
print(__package__) #指定文件所在的包,用.分割,当前文件返回None
print(__loader__)
print(__file__) #当前文件路径
print(__name__) #如果是主文件,在当前文件执行而不是调用,__name__ == "__main__",否则等于模块名
print(__cached__) #其他文件的缓存值,当前为None
print(__builtins__) #内置函数在这里面
def f1():
print("执行了")
return True

if __name__ == "__main__": #调用主文件前,必须加这个条件,只有当执行自身的文件才会执行f1(),被导入不执行f1()
f1()

os.path添加路径到sys.path

(1)丶当前文件路径为0410\s2.py,想添加0410\li路径,添加路径后直接导入li下的s1.py文件

1
2
3
4
5
6
import os,sys
temp1 = os.path.dirname(__file__) #当前文件路径
temp2 = "li"
temp = os.path.join(temp1,temp2) #路径拼接
sys.path.append(temp) #路径添加到sys.path
import s1

字符串格式化

百分号方式

%[(name)][flags][width].[precision]typecode
(1)丶(name) 可选,用于选择指定的key
(2)丶flags 可选,可供选择的值有:

  • 右对齐;正数前加正好,负数前加负号;
  • 左对齐;正数前无符号,负数前加负号;
    空格 右对齐;正数前加空格,负数前加负号;
    0 右对齐;正数前无符号,负数前加负号;如果是数字的话用0填充空白处
    (3)丶width 可选,占有宽度
    (4)丶.precision 可选,小数点后保留的位数
    (5)丶typecode 必选,可供选择的值有:
    s,获取传入对象的str方法的返回值,并将其格式化到指定位置
    r,获取传入对象的repr方法的返回值,并将其格式化到指定位置
    c,整数:将数字转换成其unicode对应的值,10进制范围为 0 <= i <= 1114111(py27则只支持0-255);字符:将字符添加到指定位置
    o,将整数转换成 八 进制表示,并将其格式化到指定位置
    x,将整数转换成十六进制表示,并将其格式化到指定位置
    d,将整数、浮点数转换成 十 进制表示,并将其格式化到指定位置
    e,将整数、浮点数转换成科学计数法,并将其格式化到指定位置(小写e)
    E,将整数、浮点数转换成科学计数法,并将其格式化到指定位置(大写E)
    f, 将整数、浮点数转换成浮点数表示,并将其格式化到指定位置(默认保留小数点后6位)
    F,同上
    g,自动调整将整数、浮点数转换成 浮点型或科学计数法表示(超过6位数用科学计数法),并将其格式化到指定位置(如果是科学计数则是e;)
    G,自动调整将整数、浮点数转换成 浮点型或科学计数法表示(超过6位数用科学计数法),并将其格式化到指定位置(如果是科学计数则是E;)
    %,当字符串中存在格式化标志时,需要用 %%表示一个百分号

注:Python中百分号格式化是不存在自动将整数转换成二进制表示的方式

1
2
3
4
5
6
print("i am %s" % "SubHyCan")
print("i am %s age %d" % ("SubHyCan", 24))
print("i am %(name)s age %(age)d" % {"name": "SubHyCan", "age": 18})
print("percent %.2f" % 99.97623)
print("i am %(pp).2f" % {"pp": 123.425556, })
print("i am %(pp).2f%%" % {"pp": 99.425556, })

format方式

[[fill]align][sign][#][0][width][,][.precision][type]
(1)丶fill 可选,空白处填充的字符
(2)丶align 可选,对齐方式(需配合width使用)
<,内容左对齐
>,内容右对齐(默认)
=,内容右对齐,将符号放置在填充字符的左侧,且只对数字类型有效。 即使:符号+填充物+数字
^,内容居中
(3)丶sign 可选,有无符号数字
+,正号加正,负号加负;
-,正号不变,负号加负;
空格 ,正号空格,负号加负;
(4)丶# 可选,对于二进制、八进制、十六进制,如果加上#,会显示 0b/0o/0x,否则不显示
(5)丶, 可选,为数字添加分隔符,如:1,000,000
(6)丶width 可选,格式化位所占宽度
(7)丶.precision 可选,小数位保留精度
(8)丶type 可选,格式化类型
传入” 字符串类型 “的参数
s,格式化字符串类型数据
空白,未指定类型,则默认是None,同s
传入“ 整数类型 ”的参数
b,将10进制整数自动转换成2进制表示然后格式化
c,将10进制整数自动转换为其对应的unicode字符
d,十进制整数
o,将10进制整数自动转换成8进制表示然后格式化;
x,将10进制整数自动转换成16进制表示然后格式化(小写x)
X,将10进制整数自动转换成16进制表示然后格式化(大写X)
传入“ 浮点型或小数类型 ”的参数
e, 转换为科学计数法(小写e)表示,然后格式化;
E, 转换为科学计数法(大写E)表示,然后格式化;
f , 转换为浮点型(默认小数点后保留6位)表示,然后格式化;
F, 转换为浮点型(默认小数点后保留6位)表示,然后格式化;
g, 自动在e和f中切换
G, 自动在E和F中切换
%,显示百分比(默认显示小数点后6位)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
print("i am {}, age {}, {}".format("seven", 24, 'SubHyCan')) 
print("i am {}, age {}, {}".format(*["seven", 24, 'SubHyCan']))
print("i am {0}, age {1}, really {0}".format("seven", 18))
print("i am {0}, age {1}, really {0}".format(*["seven", 18]))
print("i am {name}, age {age}, really {name}".format(name="seven", age=18))
print("i am {name}, age {age}, really {name}".format(**{"name": "seven", "age": 18}))
print("i am {0[0]}, age {0[1]}, really {0[2]}".format([1, 2, 3], [11, 22, 33]))
print("i am {:s}, age {:d}, money {:f}".format("seven", 18, 88888.1))
print("i am {:s}, age {:d}".format(*["seven", 18]))
print("i am {name:s}, age {age:d}".format(name="seven", age=18))
print("i am {name:s}, age {age:d}".format(**{"name": "seven", "age": 18}))
print("numbers: {:b},{:o},{:d},{:x},{:X}, {:%}".format(15, 15, 15, 15, 15, 15.87623, 2))
print("numbers: {:b},{:o},{:d},{:x},{:X}, {:%}".format(15, 15, 15, 15, 15, 15.87623, 2))
print("numbers: {0:b},{0:o},{0:d},{0:x},{0:X}, {0:%}".format(15))
print("numbers: {num:b},{num:o},{num:d},{num:x},{num:X}, {num:%}".format(num=15))

面向对象

三种编程方式为:面向过程编程,函数式编程,面向对象编程
面向对象三大特性:封装,继承,多态

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
class Foo():                               #Foo后的()可省略
def f1(self):
print(self) #self是python内部默认的参数,指向引用类的对象或实例
def f2(self,arg2):
print(self,arg)
obj = Foo() #通过类对象指针,创建一个引用类Foo的对象或实例
print(obj) #和类中print(self)的值是一样的
obj.f1()
obj.f2("shuaiguo")

### 封装
class Foo1():
def __init__(self): #封装,__init__构造方法,在遇到将类指向一个对象或实例时,会初始化执行
self.name = "lyl"
self.age = 18
def detail(self):
print (self.name,self.age)
obj1 = Foo1()
obj1.detail()
print (obj1.name,obj1.age) #直接调用obj1对象的name属性和age属性

class Foo2(Foo1):
def __init__(self, name, age): #封装,子类Foo2和父类Foo1都封装了__init__方法,则子类会覆盖父类的方法
super().__init__() #使用super函数可直接调用父类与子类相同的方法
self.xinbie = name
self.xinzuo = age
def detail(self):
print (self.xinbie,self.xinzuo)
obj1 = Foo2('男', "射手")
obj1.detail() #Python默认会将obj1传给self参数,即:obj1.detail(obj1),所以,此时方法内部的 self = obj1,即:self.name 是 lyl ;self.age 是 18
print (obj1.name,obj1.age)

游戏人生

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
class Person:
def __init__(self, na, gen, age, fig):
self.name = na
self.gender = gen
self.age = age
self.fight =fig
def grassland(self):
"""注释:草丛战斗,消耗200战斗力"""
self.fight = self.fight - 200
def practice(self):
"""注释:自我修炼,增长100战斗力"""
self.fight = self.fight + 200
def incest(self):
"""注释:多人游戏,消耗500战斗力"""
self.fight = self.fight - 500
def detail(self):
"""注释:当前对象的详细情况"""
temp = "姓名:%s ; 性别:%s ; 年龄:%s ; 战斗力:%s" % (self.name, self.gender, self.age, self.fight)
print (temp)

# ##################### 开始游戏 #####################
cang = Person('苍', '女', 18, 1000) #创建苍角色
dong = Person('木木', '男', 20, 1800) #创建木木角色
bo = Person('多多', '女', 19, 2500) #创建多多角色

cang.incest() #苍参加一次多人游戏
dong.practice()#木木自我修炼了一次
bo.grassland() #多多参加一次草丛战斗
#输出当前所有人的详细情况
cang.detail()
dong.detail()
bo.detail()

继承

父类和子类,父类也称为基类,子类也称为派生类,派生类会继承基类的对象,python的类可继承多个类,Java和C#中则只能继承一个类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class D(object):
def bar(self):
print ('D.bar')

class C(D):
def bar(self):
print ('C.bar')

class B(D):
def bar(self):
print ('B.bar')

class A(B, C): #多类继承,A有多个基类,继承优先级B优于C
def bar(self):
print ('A.bar')

a = A()
# 执行bar方法时
# 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错
# 所以,查找顺序:A --> B --> C --> D
# 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
a.bar()

多态

Pyhon不支持Java和C#这一类强类型语言中多态的写法,但是原生支持多态,其Python崇尚”鸭子类型”;python”鸭子类型”如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class F1:
pass
class S1(F1):
def show(self):
print 'S1.show'
class S2(F1):
def show(self):
print 'S2.show'
def Func(obj): #def Func(F1 obj): 伪代码实现java和C#的多态
print obj.show() # print obj.show()
s1_obj = S1()
Func(s1_obj)

s2_obj = S2()
Func(s2_obj)

反射

python中的反射功能是由以下四个内置函数提供:hasattr、getattr、setattr、delattr,该四个函数分别用于对对象内部执行:
检查是否含有某成员、获取成员、设置成员、删除成员,通过字符串的形式操作对象相关的成员。
反射是通过字符串的形式操作对象相关的成员,一切事物都是对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/env python
# -*- coding:utf-8 -*-
inp = input("请输入url(以模块名/对象的格式):")
mode,obejects = inp.split("/")
dd = __import__("lib." + mode, fromlist=True) #以字符串的方式导入模块,假设输入的模块都在lib下,模块都存在
if hasattr(dd,obejects): #判断用户输入的对象是否在模块中,如果存在,则返回设定的值或者url
ret= getattr(dd,obejects,)()
print(ret)
else:
print("404") #对象不存在,报404
print(hasattr(dd,"f1")) #False
temp = setattr(dd,"f1","lyl") #往内存中写入对象
print(hasattr(dd,"f1")) #True
delattr(dd,"f1") #在内存中删除对象
print(hasattr(dd,"f1")) #False

类成员

类成员分为三大类,分别为:
字段(普通字段,静态字段)
方法(普通方法,静态方法,类方法)
属性,也可称为特性(普通属性,也可称为普通特性);可通过@property装饰器或者静态字段方式创建

通过类来访问:静态字段,静态方法
通过对象来访问:普通字段,普通方法

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
class F1:
country = "静态字段" #静态字段,在内存中只保存一份,如果每个对象相同的字段,就使用它
def __init__(self,name):
self.name = name #普通字段
self.original_price = 100

@classmethod #定义一个类方法,此方法可通过类或者对象类访问
def f1(cls): #cls表示这个类方法属于的类F1
print("类方法")
print(cls)

@staticmethod #定义一个静态方法,此方法类似于在类中定义了一个普通函数,此方法可通过类或对象来访问
def f2():
print("静态方法")

def PT(self):
return "普通方法"

@property #在普通方法的基础上添加@property装饰器,特性其实就是将普通方法伪装成字段来访问获取
def price(self): #静态字段方式实现:如可新建三个对应函数get_price, set_price, del_price,通过PRICE = property(get_price, set_price, del_price, '价格属性描述...')来创建
print("特性")
return self.original_price

@price.setter
def price(self, value): #特性的访问特性,传参,可修改特性
self.original_price = value

@price.deleter #特性的访问特性,可删除特性
def price(self):
del self.original_price


obj = F1("普通字段")
print (obj.name) #通过对象访问普通字段
print (obj.price) #通过对象访问特性
print (obj.PT()) #通过对象访问普通方法
obj.price = 200
print (obj.price) #修改
del obj.price #删除
print (F1.country) #通过类访问静态字段

类成员修饰符

公有和私有,私有成员命名时,前两个字符是下划线。(特殊成员除外,例如:initcalldict等)
公有成员:对象可以访问;类内部可以访问;派生类中可以访问
私有成员:仅类内部可以访问;外部访问可通过公有成员曲线来访问;强制访问可通过(对象._类名__私有字段)来访问,但是不建议使用

1
2
3
4
5
6
7
8
9
10
11
12
class C:
def __init__(self):
self.name = '公有字段'
self.__foo = "私有字段"

def F1(self):
ret = self.__foo
return ret

obj = C()
print(obj.__foo) #无法访问,执行报错
print(obj.F1()) #通过F1来访问,找关系

类的特殊成员

1.doc,表示类的描述信息
2.moduleclass,表示当前操作的对象在那个模块和当前操作的对象的类是什么
3.init,构造方法,通过类创建对象时,自动触发执行
4.del,析构方法,当对象在内存中被释放时(比如内存辣鸡回收),自动触发执行
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
5.call,对象后面加括号,触发执行,即对象()或者类()(),执行类中的call方法
6.dict,类或对象中的所有成员,类的普通字段属于对象;类中的静态字段和方法等属于类
7.str,如果一个类中定义了str方法,那么在打印 对象 时,默认输出该方法的返回值
8.getitemsetitemdelitem,用于索引操作,如字典。以上分别表示获取、设置、删除数据
9.getslicesetslicedelslice,该三个方法用于分片操作,如:列表
10.iter,用于迭代器,之所以列表、字典、元组可以进行for循环,是因为类型内部定义了 iter
11.newmetaclass;obj对象是C类的一个实例,C类对象是 type类的一个实例,即:C类对象是通过type类的构造方法创建,类其实也是对象

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
class C(object):                            #object是一切类的基类
"""
这是一个类
"""
def __init__(self,sq):
self.name = 'lyl'
self.sq = sq
def __call__(self):
return "call"
def __str__(self):
return "lyl"
def __getitem__(self, key):
print ("__getitem__",key)
def __setitem__(self, key, value):
print ("__setitem__",key,value)
def __delitem__(self, key):
print ("__delitem__",key)
def __getslice__(self, i, j):
print ("__getslice__",i,j)
def __setslice__(self, i, j, sequence):
print ("__setslice__",i,j)
def __delslice__(self, i, j):
print ("__delslice__",i,j)
def __iter__(self):
return iter(self.sq)
obj = C([1,2,3,4])
print(obj.__doc__) #输出描述信息:这是一个类
print(obj.__module__)
print(obj.__class__) #输出当前对象操作的类
print(obj()) #因为定义了__call_,所以输出为:call
print(C.__dict__,obj.__dict__) #输出类中的所有成员,输出对象中的所有成员
print(obj) #因为定义了__str__,输出为:lyl,无对应则返回一个对象
result = obj['k1'] #自动触发执行 __getitem__,输出:__getitem__ k1
obj['k2'] = 'wupeiqi' #自动触发执行 __setitem__,输出:__setitem__ k2 wupeiqi
del obj['k1'] #自动触发执行 __delitem__,输出:__delitem__ k1
obj[-1:1] #自动触发执行 __getslice__,输出:__getitem__ slice(-1, 1, None)
obj[0:1] = [11,22,33,44] #自动触发执行 __setslice__,输出:__setitem__ slice(0, 1, None) [11, 22, 33, 44]
del obj[0:2] #自动触发执行 __delslice__,输出:__delitem__ slice(0, 2, None)
for i in obj:
print (i) #输出1,2,3,4,如果没有指定__iter__,则会无限循环下去

obj = iter([1,2,3,4]) #以上步骤可以看出,for循环迭代的其实是 iter([1,2,3,4]),所以执行流程可以变更为这个
for i in obj:
print (i)

类创建的两种方式:
一丶普通方法

1
2
3
class Foo(object):
def func(self):
print("nihao")

二丶特殊方式(type类的构造函数)

1
2
3
def func(self):
print("nihao")
Foo = type('Foo',(object,), {'func': func}) #type第一个参数:类名;第二个参数:当前类的基类;第三个参数:类的成员,可以为一个lamba表达式

异常处理

常用的异常:
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
IOError 输入/输出异常;基本上是无法打开文件
ImportError 无法引入模块或包;基本上是路径问题或名称错误
IndentationError 语法错误(的子类) ;代码没有正确对齐
IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError 试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C被按下
NameError 使用一个还未被赋予对象的变量
SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError 传入对象类型与要求的不符合
UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,
导致你以为正在访问它
ValueError 传入一个调用者不期望的值,即使值的类型是正确的

常用的异常处理框架:

1
2
3
4
5
6
7
8
9
10
try:
a = 1 + "lyl" #主代码块
except IndexError as e: #如果异常类型为IndexError,则执行该块,可定义多个异常处理
print(e) #异常时,执行该块,输出为异常信息
except Exception as e: #万能的异常处理,所有异常都能匹配
print(e)
else:
pass #主代码块执行完,执行该块
finally:
pass #无论异常与否,最终执行该块

主动触法异常:

1
2
3
4
try:
raise Exception('错误了。。。')
except Exception as e:
print (e) #输出为:错误了。。。

自定义异常:

1
2
3
4
5
6
7
8
9
class MyException(Exception):
def __init__(self, msg):
self.message = msg
def __str__(self):
return self.message
try:
raise MyException('我的异常')
except MyException as e:
print (e) #输出为:我的异常

单例模式

1丶单例模式,即只有一个实例
2丶静态方法+静态字段
3丶所有的实例中封装的内容相同时,用单例模式,多个实例会浪费内存
4丶单利模式存在的目的是保证当前内存中仅存在单个实例,避免内存浪费

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
from wsgiref.simple_server import make_server
# ########### 单例类定义 ###########
class DbHelper(object):
__instance = None
def __init__(self):
self.hostname = '1.1.1.1'
self.port = 3306
self.password = 'pwd'
self.username = 'root'
@staticmethod
def singleton():
if DbHelper.__instance:
return DbHelper.__instance
else:
DbHelper.__instance = DbHelper()
return DbHelper.__instance
def fetch(self):
# 连接数据库
# 拼接sql语句
# 操作
pass
def create(self):
# 连接数据库
# 拼接sql语句
# 操作
pass
def remove(self):
# 连接数据库
# 拼接sql语句
# 操作
pass
def modify(self):
# 连接数据库
# 拼接sql语句
# 操作
pass

class Handler(object):
def index(self):
obj = DbHelper.singleton() #对于Python单例模式,创建对象时不能再直接使用:obj = Foo(),而应该调用特殊的方法:obj = Foo.singleton()
print id(obj)
obj.create()
return 'index'
def news(self):
return 'news'

def RunServer(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
url = environ['PATH_INFO']
temp = url.split('/')[1]
obj = Handler()
is_exist = hasattr(obj, temp)
if is_exist:
func = getattr(obj, temp)
ret = func()
return ret
else:
return '404 not found'

if __name__ == '__main__':
httpd = make_server('', 8002, RunServer)
print "Serving HTTP on port 8001..."
httpd.serve_forever()

Socket

socket通常也称作”套接字”,用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过”套接字”向网络发出请求或者应答网络请求。
socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,对于文件用【打开】【读写】【关闭】模式来操作。socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)

socket和file的区别:
file模块是针对某个指定文件进行【打开】【读写】【关闭】
socket模块是针对 服务器端 和 客户端Socket 进行【打开】【读写】【关闭】

sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM,0)
参数一:地址簇
  socket.AF_INET IPv4(默认)
  socket.AF_INET6 IPv6
  socket.AF_UNIX 只能够用于单一的Unix系统进程间通信

参数二:类型
  socket.SOCK_STREAM  流式socket , for TCP (默认)
  socket.SOCK_DGRAM   数据报式socket , for UDP
  socket.SOCK_RAW 原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。
  socket.SOCK_RDM 是一种可靠的UDP形式,即保证交付数据报但不保证顺序。SOCK_RAM用来提供对原始协议的低级访问,在需要执行某些特殊操作时使用,如发送ICMP报文。SOCK_RAM通常仅限于高级用户或管理员运行的程序使用。
  socket.SOCK_SEQPACKET 可靠的连续数据包服务

参数三:协议
  0  (默认)与特定的地址家族相关的协议,如果是 0 ,则系统就会根据地址格式和套接类别,自动选择一个合适的协议

sk.bind(address)
  将套接字绑定到地址。address地址的格式取决于地址族。在AF_INET下,以元组(host,port)的形式表示地址。

sk.listen(backlog)
  开始监听传入连接。backlog指定在拒绝连接之前,可以挂起的最大连接数量。
backlog等于5,表示内核已经接到了连接请求,但服务器还没有调用accept进行处理的连接个数最大为5
这个值不能无限大,因为要在内核中维护连接队列

sk.setblocking(bool)
  是否阻塞(默认True),如果设置False,那么accept和recv时一旦无数据,则报错。

sk.accept()
  接受连接并返回(conn,address),其中conn是新的套接字对象,可以用来接收和发送数据。address是连接客户端的地址。
接收TCP 客户的连接(阻塞式)等待连接的到来

sk.connect(address)
  连接到address处的套接字。一般,address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。

sk.connect_ex(address)
  同上,只不过会有返回值,连接成功时返回 0 ,连接失败时候返回编码,例如:10061

sk.close()
  关闭套接字

sk.recv(bufsize[,flag])
  接受套接字的数据。数据以字符串形式返回,bufsize指定最多可以接收的数量。flag提供有关消息的其他信息,通常可以忽略。

sk.recvfrom(bufsize[.flag])
  与recv()类似,但返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。

sk.send(string[,flag])
  将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。即:可能未将指定内容全部发送。

sk.sendall(string[,flag])
  将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。
内部通过递归调用send,将所有内容发送出去。

sk.sendto(string[,flag],address)
  将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。该函数主要用于UDP协议。

sk.settimeout(timeout)
  设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如 client 连接最多等待5s )

sk.getpeername()
  返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。

sk.getsockname()
  返回套接字自己的地址。通常是一个元组(ipaddr,port)

sk.fileno()
  套接字的文件描述符

WEB服务应用,客户端为浏览器,在浏览器中输入:127.0.0.1:8081来与服务端交互,浏览器页面返回:Hello World

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import socket
def handle_request(client):
buf = client.recv(1024)
client.send(bytes("HTTP/1.1 200 OK\r\n\r\n",encoding="utf-8"))
client.send(bytes("Hello, World",encoding="utf-8"))

def main():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('localhost',8081))
sock.listen(5)

while True:
connection, address = sock.accept()
handle_request(connection)
connection.close()

if __name__ == '__main__':
main()

聊天机器人(单连接版)
服务端只能处理一个客户端连接,当有两个连接时,第二个连接处于等待状态,必须等到服务端处理完第一个连接,才能处理它
服务端:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import socket
ip_port = ('127.0.0.1',9999) #服务端用于客户端连接的ip和端口
sk = socket.socket()
sk.bind(ip_port) #开启服务端
sk.listen(5) #监听的最大连接数
while True:
print ('server waiting...')
conn,addr = sk.accept() #阻塞,直到有客户端连接,才往下执行,conn为连接的对象,addr为客户端IP和端口
conn.sendall(bytes('我是聊天机器人',encoding = "utf-8")) #发送消息给客户端
while True:
client_data = conn.recv(1024) #接收客户端的消息
if str(client_data,encoding="utf-8") == "q": #如果接收到的消息是q,即退出循环,等待下一个客户端连接
break
else:
conn.sendall(client_data + bytes("是一个大帅锅",encoding="utf-8")) #每次接收到除q外的字符串时,返回接收到的值加是一个大帅锅
conn.close() #连接关闭

客户端:

1
2
3
4
5
6
7
8
9
10
11
12
import socket
ip_port = ('127.0.0.1',9999) #连接服务端所用的IP和端口
sk = socket.socket()
sk.connect(ip_port) #客户端连接到一个服务端
while True:
server_reply = sk.recv(1024) #阻塞,接收服务端发来的消息,直到接收到才继续往下执行
print (str(server_reply,encoding="utf-8"))
inp = input("请输入内容:")
sk.sendall(bytes(inp,encoding="utf-8")) #向服务端发送输入的消息
if inp == "q": #当输入q时,客户端与服务端的连接关闭
break
sk.close() #连接关闭

IO多路复用

I/O多路复用指:通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作
Python中有一个select模块,其中提供了:select、poll、epoll三个方法,分别调用系统的 select,poll,epoll 从而实现IO多路复用

select
select最早于1983年出现在4.2BSD中,它通过一个select()系统调用来监视多个文件描述符的数组,当select()返回后,
该数组中就绪的文件描述符便会被内核修改标志位,使得进程可以获得这些文件描述符从而进行后续的读写操作。
select目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点,事实上从现在看来,这也是它所剩不多的优点之一。
select的一个缺点在于单个进程能够监视的文件描述符的数量存在最大限制,在Linux上一般为1024,不过可以通过修改宏定义甚至重新编译内核的方式提升这一限制。
另外,select()所维护的存储大量文件描述符的数据结构,随着文件描述符数量的增大,其复制的开销也线性增长。
同时,由于网络响应时间的延迟使得大量TCP连接处于非活跃状态,但调用select()会对所有socket进行一次线性扫描,所以这也浪费了一定的开销。

poll
poll在1986年诞生于System V Release 3,它和select在本质上没有多大差别,但是poll没有最大文件描述符数量的限制。
poll和select同样存在一个缺点就是,包含大量文件描述符的数组被整体复制于用户态和内核的地址空间之间,而不论这些文件描述符是否就绪,它的开销随着文件描述符数量的增加而线性增大。
另外,select()和poll()将就绪的文件描述符告诉进程后,如果进程没有对其进行IO操作,那么下次调用select()和poll()的时候将再次报告这些文件描述符,所以它们一般不会丢失就绪的消息,这种方式称为水平触发(Level Triggered)。

epoll
直到Linux2.6才出现了由内核直接支持的实现方法,那就是epoll,它几乎具备了之前所说的一切优点,被公认为Linux2.6下性能最好的多路I/O就绪通知方法。
epoll可以同时支持水平触发和边缘触发(Edge Triggered,只告诉进程哪些文件描述符刚刚变为就绪状态,它只说一遍,如果我们没有采取行动,那么它将不会再次告知,这种方式称为边缘触发),理论上边缘触发的性能要更高一些,但是代码实现相当复杂。
epoll同样只告知那些就绪的文件描述符,而且当我们调用epoll_wait()获得就绪文件描述符时,返回的不是实际的描述符,而是一个代表就绪描述符数量的值,
你只需要去epoll指定的一个数组中依次取得相应数量的文件描述符即可,这里也使用了内存映射(mmap)技术,这样便彻底省掉了这些文件描述符在系统调用时复制的开销。
另一个本质的改进在于epoll采用基于事件的就绪通知方式。在select/poll中,进程只有在调用一定的方法后,内核才对所有监视的文件描述符进行扫描,
而epoll事先通过epoll_ctl()来注册一个文件描述符,一旦基于某个文件描述符就绪时,内核会采用类似callback的回调机制,迅速激活这个文件描述符,当进程调用epoll_wait()时便得到通知。

Windows Python:
提供: select
Mac Python:
提供: select
Linux Python:
提供: select、poll、epoll

对于select方法:
句柄列表11, 句柄列表22, 句柄列表33 = select.select(句柄序列1, 句柄序列2, 句柄序列3, 超时时间)
参数: 可接受四个参数(前三个必须)
返回值:三个列表
select方法用来监视文件句柄,如果句柄发生变化,则获取该句柄。
1、当 参数1 序列中的句柄发生可读时(accetp和read),则获取发生变化的句柄并添加到 返回值1 序列中
2、当 参数2 序列中含有句柄时,则将该序列中所有的句柄添加到 返回值2 序列中
3、当 参数3 序列中的句柄发生错误时,则将该发生错误的句柄添加到 返回值3 序列中
4、当 超时时间 未设置,则select会一直阻塞,直到监听的句柄发生变化
当 超时时间 = 1时,那么如果监听的句柄均无任何变化,则select会阻塞 1 秒,之后返回三个空列表,如果监听的句柄有变化,则直接执行。

利用select实现伪同时处理多个Socket客户端请求:
服务端

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
import socket
import select
sk1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sk1.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sk1.bind(('127.0.0.1',8002))
sk1.listen(5)
sk1.setblocking(0)
inputs = [sk1,]
while True:
readable_list, writeable_list, error_list = select.select(inputs, [], inputs, 1)
for r in readable_list:
print(r)
# 当客户端第一次连接服务端时
if r == sk1:
print ('accept a connect')
request, address = r.accept()
request.setblocking(0)
inputs.append(request)
#当客户端连接上服务端之后,服务端接收数据
else:
received = r.recv(1024)
received_str = str(received,encoding="utf-8")
# 当正常接收客户端发送的数据时
if received: #如果接收到客户端的数据不为空,则给客户端返回接收到的字符串加上你好
print ('received data:',received_str )
r.sendall(received + bytes("你好",encoding="utf-8"))
# 当客户端关闭程序时
else: #如果从客户端接收到的数据为空,则移除该客户端连接
inputs.remove(r)
sk1.close()

客户端

1
2
3
4
5
6
7
8
9
10
11
12
import socket
ip_port = ('127.0.0.1',8002)
sk = socket.socket()
sk.connect(ip_port)
while True:
inp = input('please input:')
if inp == "":
break
sk.sendall(bytes(inp,encoding="utf-8"))
recived_str = str(sk.recv(1024),encoding="utf-8")
print(recived_str)
sk.close()

socketServer模块

SocketServer内部使用 IO多路复用 以及 “多线程” 和 “多进程” ,从而实现并发处理多个客户端请求的Socket服务端。
即:每个客户端请求连接到服务器时,Socket服务端都会在服务器是创建一个“线程”或者“进程” 专门负责处理当前客户端的所有请求。

ThreadingTCPServer
ThreadingTCPServer实现的Soket服务器内部会为每个client创建一个 “线程”,该线程用来和客户端进行交互。

1、ThreadingTCPServer基础
使用ThreadingTCPServer:
创建一个继承自 SocketServer.BaseRequestHandler 的类
类中必须定义一个名称为 handle 的方法
启动ThreadingTCPServer

2、ThreadingTCPServer源码剖析
内部调用流程为:
启动服务端程序
执行 TCPServer.init 方法,创建服务端Socket对象并绑定 IP 和 端口
执行 BaseServer.init 方法,将自定义的继承自SocketServer.BaseRequestHandler 的类 MyRequestHandle赋值给 self.RequestHandlerClass
执行 BaseServer.server_forever 方法,While 循环一直监听是否有客户端请求到达 …
当客户端连接到达服务器
执行 ThreadingMixIn.process_request 方法,创建一个 “线程” 用来处理请求
执行 ThreadingMixIn.process_request_thread 方法
执行 BaseServer.finish_request 方法,执行 self.RequestHandlerClass() 即:执行 自定义 MyRequestHandler 的构造方法(自动调用基类BaseRequestHandler的构造方法,在该构造方法中又会调用 MyRequestHandler的handle方法)
SocketServer的ThreadingTCPServer之所以可以同时处理请求得益于 select 和 Threading 两个东西,其实本质上就是在服务器端为每一个客户端创建一个线程,当前线程用来处理对应客户端的请求,所以,可以支持同时n个客户端链接(长连接)。

SocketServer实现服务器:
服务端可同时处理多个客户端连接请求
服务端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import socketserver
class MyServer(socketserver.BaseRequestHandler):
def handle(self):
print("新的连接开始")
# print self.request,self.client_address,self.server
conn = self.request
conn.sendall(bytes('我是聊天机器人',encoding = "utf-8"))
while True:
client_data = conn.recv(1024) #接收客户端的消息
if str(client_data,encoding="utf-8") == "q": #如果接收到的消息是q,即退出循环,等待下一个客户端连接
break
else:
conn.sendall(client_data + bytes("是一个大帅锅",encoding="utf-8")) #每次接收到除q外的字符串时,返回接收到的值加是一个大帅锅
conn.close()

if __name__ == '__main__':
server = socketserver.ThreadingTCPServer(('127.0.0.1',8009),MyServer)
server.serve_forever()

客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
import socket
ip_port = ('127.0.0.1',8009)
sk = socket.socket()
sk.connect(ip_port)
sk.settimeout(5)
while True:
data = sk.recv(1024)
print ('receive:',str(data,encoding="utf-8"))
inp = input('please input:')
sk.sendall(bytes(inp,encoding="utf-8"))
if inp == 'q':
break
sk.close()

FTP作业
服务端

1
2


客户端

1
2


Other

Nginx隐藏版本号

nginx默认显示版本号,curl -I 192.168.229.71:8888|grep Server可查看版本号,修改配置文件,在http中添加server_tokens off;语句,重新加载nginx生效

Linux耗尽cpu脚本

for i in seq 1 $(cat /proc/cpuinfo |grep "physical id" |wc -l); do dd if=/dev/zero of=/dev/null & done

Linux下日常用到的一些命令

Quick Start

命令帮助

1
2
man 命令
命令 --help

查看大文件

1
find / -type f -size +1G -print0 | xargs -0 du -h | sort -nr                           #查找所有大于1G的文件,显示大小并排序

批量修改文件后缀名

1
find ./ -name "*.log" | awk -F "." '{print $2}' | xargs -i -t mv ./{}.log ./{}.txt      #将当前目录的所有log文件修改为txt文件

找出两个目录相同的值并删除,可用awk,grep,comm命令实现

1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash
ls /lyl/openstack1 > tmp1.txt
ls /lyl/openstack2 > tmp2.txt
awk 'NR==FNR{a[$0]}NR>FNR{if($1 in a) print $0}' tmp1.txt tmp2.txt > tmp3.txt #找出两个目录相同的值
awk 'NR==FNR{a[$0]}NR>FNR{if(!($1 in a)) print $0}' tmp1.txt tmp2.txt > tmp4.txt #找出两个目录不同的值
cat tmp3.txt | while read line
do
echo $line
rm -rf /lyl/openstack2/$line
done
rm -rf tmp*.txt

查看大文件的内容

1
tail -n 100 test.log           #查看日志倒数100行的内容,文件较大是可用此命令

查看配置文件未被注释内容

1
2
3
cat /etc/cinder/cinder.conf|grep -v "^#"|grep -v "^$"
sed '/^#/d' cinder.conf
sed -i 's/^/#/' cinder.conf #注释文件所有内容

编辑文件

1
vim 文件名 +100                #打开文件并来到第100行

touch命令

1
touch 文件名                   #创建新的空文件

查看java运行的实例

1
jps

pwdx,查看程序执行路径

1
pwdx $pid

解压一个war包,例如Hudson.war

1
jar -xvf Hudson.war  #解压Hudson.war到当前目录

将一个文件夹下的所有内容添加到压缩文件

1
zip -r 文件名.zip ./*

解压zip文件到当前目录

1
unzip 文件名.zip

安装rpm包,可以用rpm或者yum

1
2
rpm -ivh rpm包    
yum install rpm包

卸载rpm包

1
2
rpm --nodeps -e rpm包
yum -y remove rpm包

nohup命令可以将程序以忽略挂起信号的方式运行起来,被运行的程序的输出信息将不会显示到终端

1
2
nohup 命令 &                   #缺省重定向输出到nohup.out
nohup 命令 > 文件.log 2>&1 & #指定输出到文件

网卡流量相关

1
2
cat /proc/net/dev #查看网卡流量
grep ens32 /proc/net/dev |awk '{print $1}' #得出网卡ens32的第1个参数数值

apache对web进行压力测试ab

1
./ab -n1000 -c100 http://192.168.229.71/mycluster/testCluster.jsp  #n为请求数,c为并发数

arpd命令是用来收集免费arp信息的一个守护进程,它将收集到的信息保存在磁盘上或者在需要时,提供给内核用户用于避免多余广播。

1
2
arpd -b /var/tmp/arpd.db       #指定数据库文件,启动arpd进程
arpd -l -b /var/tmp/arpd.db #查看结果

nstat命令和rtacct命令是一个简单的监视内核的SNMP计数器和网络接口状态的实用工具。

1
2
nstat
rtacct

suse查看版本

1
2
3
4
lsb_release -a         #查看系统版本
cat /etc/SUSE-release #查看系统版本
uname -a #查看系统信息
uname -r #查看内核版本

suse 11防火墙相关

1
2
3
SuSEfirewall2 status       #查看防火墙状态
SuSEfirewall2 satrt #开启防火墙
SuSEfirewall2 stop #关闭防火墙

ss命令用来显示处于活动状态的套接字信息。ss命令可以用来获取socket统计信息,它可以显示和netstat类似的内容。但ss的优势在于它能够显示更多更详细的有关TCP和连接状态的信息,而且比netstat更快速更高效。

1
2
3
4
5
ss -t -a  #显示tcp连接
ss -u -a #显示udp连接
ss -s #显示 Sockets 摘要
ss -l #列出所有打开的网络连接端口
ss -pl #查看进程使用的socket

ip命令用来显示或操纵Linux主机的路由、网络设备、策略路由和隧道,是Linux下较新的功能强大的网络配置工具。

1
2
3
ip -s link list     #显示更加详细的网络设备运行状态
ip route list #显示核心路由表
ip neigh list #显示邻居表

dig命令是常用的域名查询工具,可以用来测试域名系统工作是否正常。

1
dig www.baidu.com   #例如查询百度

ssh命令是openssh套件中的客户端连接工具,可以给予ssh加密协议实现安全的远程登录服务器。

1
2
ssh root@192.168.229.70               #以root用户登录服务器
ssh root@192.168.229.70 df -h #以root用户远程执行命令df -h

traceroute命令用于追踪数据包在网络上的传输时的全部路径,它默认发送的数据包大小是40字节。

1
traceroute www.baidu.com     #追踪本地到百度服务器的路由

tracepath命令用来追踪并显示报文到达目的主机所经过的路由信息,与traceroute类似。

1
tracepath www.baidu.com      #追踪本地到百度服务器的路由

route命令用来显示并设置Linux内核中的网络路由表,route命令设置的路由主要是静态路由

1
route -n          #查看当前路由

More info: route

nslookup命令是常用域名查询工具,就是查DNS信息用的命令。

1
nslookup www.baidu.com

arping命令是用于发送arp请求到一个相邻主机的工具

1
arping www.baidu.com

arp命令用于操作主机的arp缓冲区,它可以显示arp缓冲区中的所有条目、删除指定的条目或者添加静态的ip地址与MAC地址对应关系。

1
arp -v       #查询arp缓冲区中指定主机的arp条目

ifconfig命令被用于配置和显示Linux内核中网络接口的网络参数。

More info: ifconfig

ifdown命令用于禁用指定的网络接口。

1
ifdown eth0        #禁用eth0

split命令可以将一个大文件切割成很多个小文件,有时需要将文件切割成更小的片段,比如为提高可读性,生成日志等。

1
2
3
4
5
6
7
8
9
选项
-b:指定大小切割。
-C:与-b参数类似,但切割时尽量维持每行的完整性。
-d:使用数字作为后缀。
-l:以行数数大小切割。
split -b 100M test.log #分割test.log文件,每100M为一个文件,默认文件名为xaa,xab.....
split -C 100M test.log #分割test.log文件,每100M为一个文件,默认文件名为xaa,xab.....
split -d -C 100M test.log test.log #分割test.log文件,每100M为一个文件,文件名为test.log1,testlog2.......
split -d -l 100000 test.log test.log #分割test.log文件,每100000行为一个文件,文件名为test.log1,testlog2.......

tcpdump命令是一款sniffer工具,它可以打印所有经过网络接口的数据包的头信息,也可以使用-w选项将数据包保存到文件中,方便以后分析。

More info: tcpdump

ethtool命令用于获取以太网卡的配置信息,或者修改这些配置。这个命令比较复杂,功能特别多。

More info: ethtool

iptables命令是Linux上常用的防火墙软件,是netfilter项目的一部分。可以直接配置,也可以通过许多前端和图形界面配置。

More info: iptables

netstat命令用来打印Linux中网络系统的状态信息,可让你得知整个Linux系统的网络情况。

More info: netstat

ssh-keygen命令用于为“ssh”生成、管理和转换认证密钥,它支持RSA和DSA两种认证密钥。

More info: ssh-keygen

curl命令是一个利用URL规则在命令行下工作的文件传输工具。

More info: curl

mail命令是命令行的电子邮件发送和接收工具。操作的界面不像elm或pine那么容易使用,但功能非常完整。

More info: mail

lsof命令用于查看你进程开打的文件,打开文件的进程,进程打开的端口(TCP、UDP)。找回/恢复删除的文件。

1
2
lsof -n |awk '{print $2}'|sort|uniq -c |sort -nr|more   #查看所有进程打开的文件句柄数量,第一列为句柄数量(从大到小排列),第二列为进程号
lsof -p $pid | wc -l #查看进程打开的文件数

More info: lsof

wc -l命令可用于统计命令输出的行数

1
db2 list applications|wc -l          #输出数据库应用的连接数

uniq用于报告或忽略文件中的重复行,一般与sort命令结合使用。

1
uniq test.txt         #删除相邻重复出现的行

More info: uniq

sort用于排序

1
2
3
4
5
6
7
8
9
sort -k1 test.txt       #指定第一列排序
sort test.txt #排序,让文件重复的行相邻
sort test.txt | uniq #排序去重
sort -u test.txt #排序去重
sort test.txt | uniq -c #排序去重,统计重复次数
awk -F / '{print $3}' test.txt|sort|uniq -c #网址文件,查找重复出现的域名
cut -d / -f3 test.txt|sort|uniq -c
awk -F / '{print $3}' test.txt|sort -r|uniq -c #网址文件,查找重复出现的域名,倒序
cut -d / -f3 test.txt|sort -r|uniq -c

awk是一种编程语言,用于在linux/unix下对文本和数据进行处理。

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
awk 'BEGIN{ commands } pattern{ commands } END{ commands }'   #awk工作原理,BEGIN,pattern,END可省略
echo -e "A line 1\nA line 2" | awk 'BEGIN{ print "Start" } { print } END{ print "End" }'
#输出为:
Start
A line 1
A line 2
End

echo | awk '{ var1="v1"; var2="v2"; var3="v3"; print var1,var2,var3; }' #输出为:v1 v2 v3
echo | awk '{ var1="v1"; var2="v2"; var3="v3"; print var1"="var2"="var3; }' #输出为:v1=v2=v3
echo -e "line1 f2 f3\nline2 f4 f5\nline3 f6 f7" | awk '{print "Line No:"NR", No of fields:"NF, "$0="$0, "$1="$1, "$2="$2, "$3="$3} #NF表示字段数,在执行过程中对应于当前的字段数;NR 表示记录数,在执行过程中对应于当前的行号
#输出为:
Line No:1, No of fields:3 $0=line1 f2 f3 $1=line1 $2=f2 $3=f3
Line No:2, No of fields:3 $0=line2 f4 f5 $1=line2 $2=f4 $3=f5
Line No:3, No of fields:3 $0=line3 f6 f7 $1=line3 $2=f6 $3=f7

awk '{print $1}' 文件名 #输出文件每一行的第一个字段
awk '{print $1,$2}' 文件名 #输出文件每一行的第一个和第二个字段
awk 'END{ print NR }' 文件名 #统计文件的行数
echo -e "line1 f2 f3\n line2 f4 f5" | awk '{print $NF}' #使用print $NF可以打印出一行中的最后一个字段,使用$(NF-1)则是打印倒数第二个字段,其他以此类推;两行输出分别为f3和f5
echo -e "line1 f2 f3\n line2 f4 f5" | awk '{print $(NF-1)}' #两行输出分别为f2和f4
seq 5 | awk 'BEGIN{ sum=0; print "总和:" } { print $1"+"; sum+=$1 } END{ print "等于"; print sum }'
#seq 5为取数1-5,输出为:
总和:
1+
2+
3+
4+
5+
等于
15

VAR=10000
echo | awk -v VARIABLE=$VAR '{ print VARIABLE }' #借助-v选项,可以将外部值(并非来自stdin)传递给awk,输出为10000
var1="aaa"
var2="bbb"
echo | awk '{ print v1,v2 }' v1=$var1 v2=$var2 #另一种传递外部变量方法,输出为aaa bbb
awk 'BEGIN{a=1;b=2;print (a>5 && b<=2),(a>5 || b<=2);}' #逻辑判断,输出为0 1,即一假一真
awk 'BEGIN{a="100testa";if(a ~ /^100*/){print "ok";}}' #判断是否a匹配正则表达式,匹配输出ok,否则没有输出,输出为ok;~和~!分别为匹配和不匹配正则表达式
awk 'BEGIN{a=11;if(a >= 9){print "ok";}}' #判断a是否大于等于9,输出为ok
awk 'BEGIN{a="b";print a=="b"?"ok":"err";}' #?:为C条件表达式,判断a是否等于b,等于输出ok,否则输出err
awk 'BEGIN{a="b";arr[0]="b";arr[1]="c";print (a in arr);}' #in表示数组中是否存在某键值,返回值为0,假
awk 'BEGIN{a="b";arr[0]="b";arr["b"]="c";print (a in arr);}' #返回值为1,真
cat test.txt #每一行的内容分别为a,b,c,d,e
awk 'NR%2==1{next}{print NR,$0;}' test.txt #两行的输出分别为2 b,4 d
cat test.txt
内容为:
web01[192.168.2.100]
httpd ok
tomcat ok
sendmail ok
web02[192.168.2.101]
httpd ok
postfix ok
web03[192.168.2.102]
mysqld ok
httpd ok
脚本:
awk '/^web/{T=$0;next;}{print T":"$0;}' test.txt
输出为:
web01[192.168.2.100]: httpd ok
web01[192.168.2.100]: tomcat ok
web01[192.168.2.100]: sendmail ok
web02[192.168.2.101]: httpd ok
web02[192.168.2.101]: postfix ok
web03[192.168.2.102]: mysqld ok
web03[192.168.2.102]: httpd ok

echo | awk '{printf("hello word!n") > "datafile"}' #将结果输出到一个文件
awk -F: '{ print $NF }' /etc/passwd #将/etc/passwd中每一行的最后一个字段输出
awk 'BEGIN{ FS=":" } { print $NF }' /etc/passwd
awk 'BEGIN{info="it is a test";lens=split(info,tA," ");print length(tA),lens;}' #length返回字符串以及数组长度,split进行分割字符串为数组,也会返回分割得到数组长度,4 4
awk 'BEGIN{info="it is a test";split(info,tA," ");print asort(tA);}' #asort对数组进行排序,返回数组长度。4
awk 'BEGIN{info="it is a test";split(info,tA," ");for(k in tA){print k,tA[k];}}' #输出数组内容(无序)
awk 'BEGIN{info="it is a test";tlen=split(info,tA," ");for(k=1;k<=tlen;k++){print k,tA[k];}}' #输出数组内容(有序)
awk 'BEGIN{tB["a"]="a1";tB["b"]="b1";if( "c" in tB){print "ok";};for(k in tB){print k,tB[k];}}' #判断键值是否存在
awk 'BEGIN{tB["a"]="a1";tB["b"]="b1";delete tB["a"];for(k in tB){print k,tB[k];}}' #删除键值
awk 'BEGIN{OFMT="%.3f";fs=sin(1);fe=exp(10);fl=log(10);fi=int(3.1415);print fs,fe,fl,fi;}' #OFMT设置输出数据格式是保留3位小数。sin取正弦,exp取幂,log取自然对数,int取整数
awk 'BEGIN{srand();fr=int(100*rand());print fr;}' #获得随机数,rand返回0-1中的任意值
awk 'BEGIN{info="this is a test2010test!";gsub(/[0-9]+/,"!",info);print info}' #在 info中查找满足正则表达式,/[0-9]+/ 用””替换,并且替换后的值,赋值给info
awk 'BEGIN{info="this is a test2010test!";print index(info,"test")?"ok":"no found";}' #在info中查找test,找到返回ok,否则返回no found
awk 'BEGIN{info="this is a test2010test!";print substr(info,4,10);}' #从第4个字符开始,截取10个长度字符串
awk 'BEGIN{while("cat /etc/passwd"|getline){print $0;};close("/etc/passwd");}' #以close方法打开外部文件
awk 'BEGIN{while(getline < "/etc/passwd"){print $0;};close("/etc/passwd");}' #以getline方法逐行读取外部文件
awk 'BEGIN{b=system("df -h");print b;}' #以system方法调用外部应用程序,b是返回值,返回执行结果
awk 'BEGIN{a=systime();print strftime("%c",a);}' #获取系统当前的时间
awk 'BEGIN{tstamp=mktime("2001 01 01 12 12 12");print strftime("%c",tstamp);}' #建立指定时间
ps -ef|grep -v grep|grep java|awk '{print $2}'|xargs kill -9 #杀掉所有java进程
awk '{print $1}' access.log |sort|uniq -c|sort -rn|head -10 #Nginx日志访问IP统计
awk '{S[$1]++}END{for(k in S) print S[k],k}' access.log|sort -rn |head -10 #Nginx日志访问IP统计
awk '/^tcp/ {S[$NF]++}END{for(k in S) print S[k],k}' netstat.log |sort -nr|head #tcp网络连接状态排序
awk '/^tcp/ {print $NF}' netstat.log|sort|uniq -c|sort -nr|head #tcp网络连接状态排序
awk '{print $7"\t" $10}' access_log|awk '{S[$1]+=$2;S1[$1]+=1}END{for(i in S) print S[i],S1[i],i}'|sort -rn|head -10 #流量暴涨时查看文件总访问大小(前10),访问次数,路径
awk '{array_num[$7]++;array_size[$7]+=$10}END{for(x in array_num){print array_size[x],array_num[x],x}}' access_20190102.log |sort -rn -k1|head -10 #流量暴涨时查看文件总访问大小(前10),访问次数,路径

More info: awk

ln命令用来为文件创建连接,连接类型分为硬连接和符号连接两种,默认的连接类型是硬连接。如果要创建符号连接必须使用”-s”选项。

1
2
3
cd /usr/mengqc
ln /mub1/m2.c /usr/liu/a2.c #将目录/usr/mengqc/mub1下的文件m2.c链接到目录/usr/liu下的文件a2.c,在执行ln命令之前,目录/usr/liu中不存在a2.c文件。执行ln之后,在/usr/liu目录中才有a2.c这一项,表明m2.c和a2.c链接起来(注意,二者在物理上是同一文件),利用ls -l命令可以看到链接数的变化。
ln -s /usr/mengqc/mub1 /usr/liu/abc #在目录/usr/liu下建立一个符号链接文件abc,使它指向目录/usr/mengqc/mub1,执行该命令后,/usr/mengqc/mub1代表的路径将存放在名为/usr/liu/abc的文件中。

More info: ln

dd命令用于复制文件并对原文件的内容进行转换和格式化处理。

1
dd if=/dev/zero of=sun.txt bs=1M count=1          #if和of分别代表输入和输出文件,如不指定,默认为从stdin中读取输入,将stdout作为默认输出,bs 代表字节为单位的块大小,count代表被复制的块数。

stat命令用于显示文件的状态信息,stat命令的输出信息比ls命令的输出信息要更详细。

1
stat -c %s test.txt            #查看文件的大小

More info: stat

uptime命令能够打印系统总共运行了多长时间和系统的平均负载。

1
2
uptime -V    #显示uptime命令版本信息
uptime #信息显示依次为:现在时间、系统已经运行了多长时间、目前有多少登陆用户、系统在过去的1分钟、5分钟和15分钟内的平均负载。

time命令用于统计给定命令所花费的总时间。

1
time 命令    #输出的信息分别显示了该命令所花费的real时间、user时间和sys时间

at命令用于在指定时间执行命令(进入at命令行后,按ctrl+d可保存)。

More info: at

crontab命令被用来提交和管理用户的需要周期性执行的任务,与windows下的计划任务类似。

1
2
3
4
5
6
crontab -e            #编辑该用户的计时器任务
编辑的内容示例:
SHELL=/bin/bash
*/10 19-21 * * * /usr/local/workspace/jiance.sh >> /usr/local/workspace/jiance.txt
# 从晚上7点到9点每隔10分钟执行一次,并将执行结果写到文本文件
crontab -l #查看该用户的计时器任务

More info: crontab URL

ulimit命令用来限制系统用户对shell资源的访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ulimit -a 
输出如下所示:
core file size (blocks, -c) 0 #core文件的最大值为100 blocks。
data seg size (kbytes, -d) unlimited #进程的数据段可以任意大。
scheduling priority (-e) 0
file size (blocks, -f) unlimited #文件可以任意大。
pending signals (-i) 98304 #最多有98304个待处理的信号。
max locked memory (kbytes, -l) 32 #一个任务锁住的物理内存的最大值为32KB。
max memory size (kbytes, -m) unlimited #一个任务的常驻物理内存的最大值。
open files (-n) 1024 #一个任务最多可以同时打开1024的文件。
pipe size (512 bytes, -p) 8 #管道的最大空间为4096字节。
POSIX message queues (bytes, -q) 819200 #POSIX的消息队列的最大值为819200字节。
real-time priority (-r) 0
stack size (kbytes, -s) 10240 #进程的栈的最大值为10240字节。
cpu time (seconds, -t) unlimited #进程使用的CPU时间。
max user processes (-u) 98304 #当前用户同时打开的进程(包括线程)的最大个数为98304。
virtual memory (kbytes, -v) unlimited #没有限制进程的最大地址空间。
file locks (-x) unlimited #所能锁住的文件的最大个数没有限制。

More info: ulimit

sed是一种流编辑器,它是文本处理中非常中的工具,能够完美的配合正则表达式使用,功能不同凡响,全称为 stream editor可用于增删改查及过滤 取行。

参数:
-i #直接编辑文件
-r #匹配正则表达式

-n #取消默认输出

-e #允许多项编辑

i #插入
a #增加
s #替换
d #删除

p #输出匹配内容

g #全局匹配

r #从文件中读行

正则,三剑客grep,sed,awk都支持:

^w表示以w开头

w$表示以w结尾

.表示任意一个字符

*表示重复零个或多个的前一个重复字符

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
sed -nsed -i 's/hello/HELLO/' datafile                        #在文件datafile上将每一行的第一个hello替换为HELLO   
sed -i 's#hello#HELLO#' datafile
sed -i 's/hello/HELLO/g' datafile #在文件datafile上将每一行的所有hello替换为HELLO
sed -i 's#hello#HELLO#g' datafile

#以下操作都在内存中处理,标准化输出到窗口,不会更改原文件
sed '2i dandan' test.txt #在第二行前面加入dandan
sed '2a lyl' test.txt #在第二行后面加入lyl
sed '2i nishizhen\n107 banban' test.txt #加入两行
sed 'd' test.txt #删除文件所有内容
sed '1,+2d' test.txt #删除文件前3行
sed '1,3d' test.txt #删除文件前3行
sed '3d' test.txt #删除文件第三行
sed '1~2d' test.txt #删除文件奇数行,1行开始,每隔两行删除
sed '2~2d' test.txt #删除文件偶数行,2行开始,每隔两行删除
sed '/lyl/,/subhy/d' test.txt #对匹配到从lyl到subhy的行进行删除
sed '/lyl/d' test.txt #删除包含lyl的行
sed '/lyl/,10d' test.txt #删除从lyl开始的10行
sed '/lyl/,$d' test.txt #删除从lyl开始的所有行
sed '/lyl/,+1d' test.txt #删除lyl和后面的一行
sed '1,/subcan/d' test.txt #删除第一行到subcan的行

sed '2c liyunliang' test.txt #替换第二行的内容
sed '2,3c lyl\ntest' test.txt #替换2,3行的内容
sed 's/hello/HELLO/' test.txt #替换每一行的第一个字符hello
sed 's#hello#HELLO#' test.txt
sed '4s#a#A#' test.txt #精确替换,将第四行的第一个a替换为A
sed '4s#a#A#2g' test.txt #从第4行的发现的第2个开始,替换a为A
x=a
y=b
sed "s#$x#$y#" test.txt #变量替换
sed s#$x#$y# test.txt
sed 's#'$x'#'$y'#' test.txt
eval sed 's#$x#$y#' a.txt

#分组替换
echo My name is lyl,I am a boy.|sed 's#.*is \(.*\),I.*#\1#g' #替换为lyl
echo My name is lyl,I am a boy.|sed 's#^.*is \([a-z].*\),I.*#\1#g' #替换为lyl
echo My name is lyl,I am a boy.|sed -r 's#^.*is ([a-z].*),I.*#\1#g' #替换为lyl
echo My name is lyl,I am a boy.|sed -r 's#(.*) (.*),I.*#\2#g' #替换为lyl
sed -r '1,3s#(.*)#--&--#g' test.txt #&表示替换的内容

批量替换文件名
for i in {1..5};do touch test_${i}_find.jpg;done
ls *.jpg|sed -r 's#(.*)_find.*#mv & \1.jpg#g'|bash #|后加bash,表示执行输出
#开机启动项优化,关闭除了这五个的启动项
chkconfig --list|grep "3:on"|grep -vE "sshd|crond|network|rsyslog|sysstat"|awk '{print $1}'|sed -r 's#(.*)#chkconfig \1 off#g'|bash
chkconfig --list|grep "3:on"|grep -vE "sshd|crond|network|rsyslog|sysstat"|awk '{print $1}'|sed -r 's#(.*)#chkconfig \1 off#eg' #e表示执行sed模式空间里的内容

查询匹配到的内容并输出
sed -n 'p' test.txt #查询全部内容,取消默认输出
sed -n '2p' test.txt
sed -n '2,3p' test.txt
sed -n '1~2p' test.txt
sed -n '2~2p' test.txt
sed -n '/lyl/p' test.txt
sed -n '/subhy/,/lyl/p' test.txt
sed -n '/subhy,4p' test.txt
sed -n '1,/lyl/p' test.txt

sed 'w output.txt' test.txt #文件另存为output.txt
sed 's#l#Y#g w output.txt' test.txt
sed '1s#l#Y#g w output.txt' test.txt
sed '1s#l#Y#2g w output.txt' test.txt #将第1行从发现的第2个开始将l替换为Y,并另存为output.txt
sed '1s#l#Y#2g;w output.txt' test.txt #;将命令隔开
sed '1s#l#Y#2g#w output.txt' test.txt #只将替换后那一行的内容另存到文件
sed 's#lyl#NB#ig' test.txt #i,表示忽略大小写
sed 's#^#ls -lh #e' test.txt #e表示执行shell命令。在每一行的开头加上ls -lh,并执行命令
echo 101,LYL,nb | sed -r 's#(.*),(.*),(.*)#\L\2,\E\1,\U\3#g' #输出为lyl,101,NB;\L,表示变为小写,\E表示关闭功能,不会改变原来的值,\U表示变为大写
sed '=' test.txt|sed 'N;s#\n# #' #统计行数

sed '3,$d' test.txt|sed 's#10#01#g' #删除第2行以后的内容,并把10替换为01
sed -e '3,$d' -e 's#10#01#g' test.txt
sed -e '3,$d;s#10#01#g' test.txt #一般用这种命令
sed '3,$d;s#10#01#g' test.txt
sed -f test.sed test.txt #test.sed第1行内容为3,$d,第2行内容为s#10#01#g
sed -n '2,4{p;=}' test.txt #特殊符号{}
sed '$r temp.txt' test.txt #合并文件

模式空间:
n 清空当前模式空间,然后读入下一行
sed -n 'n;p' test.txt #只输出偶数行,奇数行遇到n,被清空
sed -n 'n;p' test.txt #只输出奇数行,偶数行遇到n,被清空
N 不清空当前模式空间,然后读入下一行,以\n分隔两行
sed 'N;s#\n#=#' test.txt
保持空间:

sed -n '3!p' test.txt #过滤,非第3行
sed -n '/lyl/!p' test.txt #过滤
sed -n '$=' test.txt #行统计,等同于wc -l < test.txt

More info: sed

grep 即全面搜索正则表达式并把行打印出来,是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。

More info: grep

tr命令可以对来自标准输入的字符进行替换、压缩和删除。

More info:tr

history 用于显示指定数目的指令命令

1
2
3
4
5
history -c           #清空当前历史命令

history 100 #查看最近的100条命令

!100 #显示第100条命令并执行

修改历史命令最大保存数目

历史命令是被保存在内存中的,当退出或者登录shell时,会自动保存或读取。在内存中,历史命令仅能够存储1000条历史命令,该数量是由环境变量HISTSIZE进行控制
1丶修改/etc/profile里HISTSIZE的值为想要保存的条数,保存后source /etc/profile即可生效
2丶如不生效,可重启

More: history

Centos 7

Quick Start

Firewall

查看默认防火墙状态

1
firewall-cmd --state

查看防火墙状态

1
systemctl list-unit-files|grep firewalld.service

关闭防火墙

1
systemctl stop firewalld.service

禁止防火墙开机启动

1
systemctl disable firewalld.service

查看已经开放的端口

1
firewall-cmd --list-ports

开放端口,例如80

1
firewall-cmd --zone=public --add-port=80/tcp --permanent

关闭端口,例如80

1
firewall-cmd --zone=public --remove-port=80/tcp --permanent

重新加载防火墙配置

1
firewall-cmd --reload

查看已启动的服务列表

1
systemctl list-unit-files|grep enabled

查看是否开机启动

1
systemctl is-enabled firewalld.service;echo $?

关闭SELINUX

1
2
3
4
5
getenforce               #查看
/usr/sbin/sestatus -v #查看
setenforce 1 #设置为enforcing模式
setenforce 0 #临时关闭,设置为permissive模式
vi /etc/selinux/config #永久关闭,将SELINUX=enforcing改为SELINUX=disabled,重启生效

Other

更改主机名

1
2
systemctl start NetworkManager            #启动网络管理服务
nmcli g hostname lylxuexi #更改主机名

Git

1
2
3
4
5
6
7
8
9
10
11
12
13
14
yum -y install git                                                    #安装git
git config --global user.name "SubHyCan" #配置git用户名
git config --global user.email "2442734234@qq.com" #配置邮箱
git config --global color.ui true
git init
git remote add origin https://github.com/SubHyCan/git_data.git #添加远程的代码库到本地
cd /git_data
echo "# git_data" >> README.md
git add README.md
git commit -m "first commit" #把文件提交到本地git库,first commit为提交说明
git push -u origin master #提交到远程代码库
git status #在本地的git init目录查看本地git库的状态
git log #查看日志
git reset --hard ID #根据远程库提交的ID还原数据

安装virtualbox

1丶在/etc/yum.repos.d/目录下新建virtualbox.repo并写入https://download.virtualbox.org/virtualbox/rpm/el/virtualbox.repo中的内容

1
2
3
4
5
6
7
[virtualbox]
name=Oracle Linux / RHEL / CentOS-$releasever / $basearch - VirtualBox
baseurl=http://download.virtualbox.org/virtualbox/rpm/el/$releasever/$basearch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://www.virtualbox.org/download/oracle_vbox.asc

2丶更新yum缓存,命令为yum clean allyum makecache
3丶yum install virtualbox

yum

1
2
3
yum list zabbix-* --showduplicates | sort -r               #列出可用的软件
yum install --downloadonly --downloaddir=/root zabbix-* #只下载不安装
yumdownloader openssl-1.0.2k-8.el7.x86_64 #只下载不安装

Spotlight for DB2使用

一、安装流程

二、Spotlight介绍

Spotlight on DB2 能让你迅速发现任何性能瓶颈,无论是实时还是历史查询。Spotlight 能鉴别和诊断几千种性能问题,无论是特定用户问题、集中资源SQL事务、 I/O瓶颈、锁定等待或者其它源码问题。Spotlight for DB2 能自动为每个实例建立正常活动的底线,当检测到性能瓶颈时自动发出警告。
More info: 官网链接

三、Spotlight安装 ​

1丶Spotlight安装

使用“QuestSpotlight_DB2_6.9.1.206.exe”安装包,点击下一步完成安装过程。

2丶Spotlight破解

运行“keygen.exe”生成序列号并注册软件即可使用。

四、DB2 客户端配置 ​

1丶DB2Client安装

上传并“DB2_DSClient_10.5.0.3_Win_x86-64.iso”并安装DB2客户端,用于本地编目数据库实例。

2丶编目DB2数据库 ​

(1)启动DB2 Windows客户端

打开CMD窗口,运行“DB2cmd”,进入Windows DB2命令行模式:

(2) 编目数据库

根据数据库情况,在本地对远程数据库进行挂载。
挂载命令:
节点名可自行定义,建议与数据库名一致方便查找及使用;
别名可自行定义,建议与数据库名一致方便查找及使用;
如果执行后不生效需执行db2 terminate 刷新缓存!
命令:

1
2
db2 catalog tcpip node %节点名% remote %IP% server %Port% 															
db2 catalog database %数据库名% as %别名% at node %节点名%

范例:

1
2
db2 catalog tcpip node si2db remote 192.168.229.81 server 50000 							
db2 catalog database si2db as si2db at node si2db

一些其他命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
查看编目节点: 

db2 list node directory

查看编目数据库:

db2 list db directory

卸载编目节点:

db2 uncatalog node %节点名%

卸载编目数据库:

db2 uncatalog db %别名%

挂载截图:

账号清单:

数据库名 别名 IP 账号
云平台 OMCCLOUDnue monitor
驰宏数字化 OMCDB monitor
多晶硅数字化 SI2DB monitor
锰板块数字化 MNDB monitor
钛板块数字化 TIDB monitor
永昌硅数字化 SIDB monitor
电商采购 SUNEPS monitor
生产模块 MMPM monitor
综合管理系统 GAZHDB monitor​

五、Spotlight挂载DB2数据库

启动“Spotlight”软件,点击“FILE–connect”,选择“Add new connection”:

选择监控类型为“DB2 LUW”

根据所挂载DB2数据库,在“Database Alias”中选择需监控数据库,输入数据库监控用户名/密码,监控方式“Method To Retrieve Data”可以为“Snapshot”或“Monitor”,由于数据库部分Monitor未开启,建议采用Snapshot进行监控。

六、Spotlight监控DB2数据库

通过Spotlight可对数据库性能进行监控,每个图例项点击“鼠标右键”选择“show detail”可以看到更详细的监控信息。由于收集信息非实时,可按F5刷新数据库统计信息,以下为部分主要监控参数(包含但不仅限于):

1丶表空间使用情况监控

通过“show detail”菜单可看到数据库内所有表空间现有大小及剩余空间,由于本数据库表空间均为“Auto Extent”,该监控项可仅作监控,不作为扩容依据。

2丶表锁监控(重点监控)

出现“黄色” “Pending Locks”可确认此时数据库出现表锁,点击该项目使用“show detail”菜单对表锁进行详细分析,包括表锁出现原因及所运行Sql以作详细分析。

“show detail”页面注意“Locks Held” 、 “DeadLocks”两个参数,通过点击存在以上两种情况的行,可看在下方页面中看到详细的加锁信息。

3丶缓冲池监控(重点监控)

可对现有缓冲池命中率进行监控,注意:缓冲池命中率应大于95%。

4丶数据库读写情况监控

从该数值可知目前从客户端代理直接调用数据库表空间的读写情况。

5丶Sql运行情况

通过对运行Sql占用时间进行排序,收集占用时间最长的Sql进行进一步调优。

Windows-Related

ren用于修改文件名,可批量修改

1
ren *.log *.txt         #将所有log文件改为txt文件

域名解析

1
2
3
4
5
nslookup $域名          #直接解析
nslookup #先进入域名解析环境,再输入域名来进行解析

nslookup -qt=ptr $ip #反向解析
nslookup -qt=ptr #先进入域名反解析环境,再输入ip来进行解析

Notepade+基操

1
2
3
4
5
6
7
8
9
10
11
12
13
1丶行首行尾空格替换,将下面的替换为想要的字符
行首:^\s+
行尾:\s+$
2丶行首行尾添加字符,将下面的替换为想要的字符
行首:^
行尾:$
3丶Notepade++选中多行复制(查看大日志文件特别有用)
例:30000-40000
(1)丶搜索-->行定位-->输入30000,定位到30000
(2)丶编辑-->开始/结束选择
(3)丶搜索-->行定位-->输入40000,定位到40000
(4)丶编辑-->开始/结束选择
(5)丶右键单机复制

Linux下日常安装

linux安装JDK

1丶解压缩包 tar -zxvf jdk-8u92-linux.tar.gz -C /usr/local
2丶配置java环境变量 vi /etc/profile,末行加上以下内容并保存。

1
2
3
4
export JAVA_HOME=/usr/local/jdk1.8.0_92
export CLASSPATH=.:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tools.jar
export JRE_HOME=$JAVA_HOME/jre
export PATH=$JAVA_HOME/bin:$PATH

3丶source /etc/profile,使配置生效。
4丶java -version查看安装是否成功。

linux源码安装Nginx

1丶查看gcc,gcc-c++是否安装,如果没有先安装gcc,gcc-c++.
2丶安装pcre。
tar -zxvf pcre-8.39.tar.gz -C /tmp
cd /tmp/pcre-8.39
./configure –prefix=/usr/local/pcre
make&&make install
3丶安装openssl.
tar -zxvf openssl-1.1.0-pre4.tar.gz -C /tmp
cd /tmp/openssl-1.1.0-pre4
./config –prefix=/usr/local/openssl
make&&make install
4丶安装zlib.
tar -zxvf zlib-1.2.8.tar.gz -C /tmp
cd /tmp/zlib-1.2.8
./configure –prefix=/usr/local/zlib
make&&make install
5丶安装nginx.
tar -zxvf nginx-1.11.1.tar.gz -C /tmp
cd /tmp/nginx-1.11.1
./configure –prefix=/usr/local/nginx –with-pcre=/tmp/pcre-8.39 –with-openssl=/tmp/openssl-1.1.0-pre4 –with-zlib=/tmp/zlib-1.2.8
make&&make install
cd /usr/local/nginx/sbin
./nginx
./nginx -s reload
./nginx -t

apache编译安装(安装和nginx类似)

1丶安装pcre,检测gcc依赖
2丶安装apr
3丶安装apr-util
4丶安装httpd

Kvm虚拟化

Quick Start

基本

1丶关闭防火墙
2丶进行cpu检测,命令结果大于0表示cpu支持虚拟化。如果是等于0,就需要手动勾选虚拟化引擎

1
egrep -c '(vmx|svm)' /proc/cpuinfo

Centos7.2部署Kvm

一丶环境

Vmware5.5虚拟化

Kvm主机:centos7.2虚拟机(桌面及开发工具安装)

Kvm主机ip:192.168.229.87

Esxi5.5主机支持虚拟化:

修改虚拟机所属Esxi5.5主机配置文件/etc/vmware/config,末尾新增vhv.enable = “TRUE”并保存,重新引导主机(关闭主机上的所有虚拟机电源,进入维护模式,重新引导,退出维护模式,开启虚拟机),使其支持虚拟化。

登录虚拟机,执行egrep -c ‘(vmx|svm)’ /proc/cpuinfo ,输出不为0,说明该虚拟机支持cpu虚拟化。

二丶安装软件

1丶挂载系统安装盘,进入目录/run/media/root/CentOS\ 7\ x86_64/Packages/,安装软件qume-kvm,libvirt,virt-install,bridge-utils,virt-maneger。

2丶执行lsmod | grep kvm,如下图所示,说明kvm安装成功。

三丶配置kvm

1丶systemctl start libvirtd #开启kvm服务

​ systemctl enable libvirtd #设置开机自动启动

​ systemctl status libvirtd #查看状态

2丶配置桥接网络

(1)丶先备份一份/etc/sysconfig/network-scripts文件到/root目录

(2)丶在/etc/sysconfig/network-scripts目录下创建ifcfg-br0文件,并写入如下内容

DEVICE=br0

ONBOOT=”yes”

TYPE=Bridge

BOOTPROTO=none

IPADDR=192.168.229.87

NETMASK=255.255.255.0

GATEWAY=192.168.229.1

(3) 丶修改配置文件ifcfg-ens192,改为如下内容

DEVICEens192

ONBOOT=yes

BRIDGE=br0

(4) 丶执行systemctl restart network重启网络,查看网卡信息,已有桥接bro

3丶点击应用程序-系统工具-虚拟系统管理器,即可对kvm虚拟机进行管理,配置网络时,选择桥接网络,ip地址与宿主机配置时一样,即可实现与宿主机和外部网络的通信(若只能与宿主机通信,则更改Esxi交换机安全配置,接受混杂模式,即可与外部通信)。

四丶虚拟机管理

1丶若虚机无法启动,报错为splice-client-error-quark:Error initializing USB support:Other error99,则更改虚拟机显示为VNC服务器。即可正常启动。

2丶克隆虚机时,若克隆的虚机无法启动,则删除Channel-qemu-ga(使用了其他的虚拟机配置文件),再重新新建一个,即可正常启动。

3丶相关命令:

brctl show #查看网桥信息

virt-clone -o centos7.0 -n clone7.0 -f /var/lib/libvirt/images/clone7.0.qcow2 #克隆虚机

virsh list –all #查看所有虚机

virsh start centos7.0 #启动虚机

virsh shutdown centoss7.0 #关闭虚机

virt-install –help #查看新建虚机相关