第1章 系统基础信息模块详解
1.1 系统性能信息模块 psutil
- 解决VMWare在Windows10的安装问题: 安装VC Redistributable 2017
- 解决虚拟机的上网问题:修改VMWare 的网络设置
- 解决PuTTY连接不上虚拟机的问题:修改VMnet8的IPv4地址
- 在Centos7安装pip 参考
- 在Centos7安装psutil模块 参考
#1、以root身份登陆CentOS依次 执行以下命令:
wget https://pypi.python.org/packages/source/p/psutil/psutil-2.1.3.tar.gz --no-check-certificate
tar zxvf psutil-2.1.3.tar.gz
cd psutil-2.1.3/
python setup.py install
#2、在执行以上命令最后的安装命令时,遇到以下问题
psutil/_psutil_linux.c:12:20: fatal error: Python.h: No such file or directory
这样的错误提示,表示缺少Python-dev的依赖环境,直接安装Python-devel即可
yum -y install python-devel*
安装完后,再执行 python setup.py install 即可
安装完成提示:
Installed /usr/lib64/python2.7/site-packages/psutil-2.1.3-py2.7-linux-x86_64.egg
Processing dependencies for psutil==2.1.3
Finished processing dependencies for psutil==2.1.3
1.1.1 获取系统性能信息
(1) CPU信息
>>> import psutil
/usr/lib64/python2.7/site-packages/psutil-2.1.3-py2.7-linux-x86_64.egg/_psutil_linux.py:3: UserWarning: Module _psutil_linux was already imported from /usr/lib64/python2.7/site-packages/psutil-2.1.3-py2.7-linux-x86_64.egg/_psutil_linux.pyc, but /tmp/psutil-2.1.3 is being added to sys.path
>>> psutil.cpu_times()
scputimes(user=46.0, nice=0.27, system=87.6, idle=10040.74, iowait=52.76, irq=0.0, softirq=9.79, steal=0.0, guest=0.0, guest_nice=0.0)
>>> psutil.cpu_times().user
46.03
>>> psutil.cpu_count()
2
>>> psutil.cpu_count(logical=False)
2
>>>
(2)内存信息
>>> mem = psutil.virtual_memory()
>>> mem
svmem(total=1907970048L, available=1505476608L, percent=21.1, used=915431424L, free=992538624L, active=423669760, inactive=202493952, buffers=2134016L, cached=510803968)
>>> mem.total
1907970048L
>>> mem.free
992538624L
>>> psutil.swap_memory()
sswap(total=2147479552L, used=0L, free=2147479552L, percent=0.0, sin=0, sout=0)
>>>
(3)磁盘信息
>>> psutil.disk_partitions()
[sdiskpart(device='/dev/sda3', mountpoint='/', fstype='xfs', opts='rw,seclabel,relatime,attr2,inode64,noquota'), sdiskpart(device='/dev/sda1', mountpoint='/boot', fstype='xfs', opts='rw,seclabel,relatime,attr2,inode64,noquota')]
>>> psutil.disk_usage('/')
sdiskusage(total=19001245696, used=4522000384, free=14479245312, percent=23.8)
>>> psutil.disk_io_counters()
sdiskio(read_count=14186, write_count=8265, read_bytes=432613888, write_bytes=230467072, read_time=225143, write_time=59109)
>>> psutil.disk_io_counters(perdisk=True)
{'sr0': sdiskio(read_count=18, write_count=0, read_bytes=1052672, write_bytes=0, read_time=761, write_time=0), 'sda2': sdiskio(read_count=54, write_count=0, read_bytes=2527232, write_bytes=0, read_time=335, write_time=0), 'sda3': sdiskio(read_count=12123, write_count=6178, read_bytes=404980224, write_bytes=217040384, read_time=219281, write_time=58635), 'sda1': sdiskio(read_count=1991, write_count=2089, read_bytes=24053760, write_bytes=13428224, read_time=4766, write_time=476)}
>>>
(4)网络信息
>>> psutil.net_io_counters()
snetio(bytes_sent=1227849, bytes_recv=34910887, packets_sent=12412, packets_recv=29882, errin=0, errout=0, dropin=0, dropout=0)
>>> psutil.net_io_counters(pernic=True)
{'lo': snetio(bytes_sent=14274, bytes_recv=14274, packets_sent=144, packets_recv=144, errin=0, errout=0, dropin=0, dropout=0), 'ens33': snetio(bytes_sent=1216087, bytes_recv=34904091, packets_sent=12290, packets_recv=29824, errin=0, errout=0, dropin=0, dropout=0), 'virbr0-nic': snetio(bytes_sent=0, bytes_recv=0, packets_sent=0, packets_recv=0, errin=0, errout=0, dropin=0, dropout=0), 'virbr0': snetio(bytes_sent=0, bytes_recv=0, packets_sent=0, packets_recv=0, errin=0, errout=0, dropin=0, dropout=0)}
>>>
(5)其他系统信息
>>> psutil.users()
[suser(name='root', terminal='tty1', host='', started=1597921920.0), suser(name='root', terminal='pts/0', host='192.168.135.1', started=1597933824.0), suser(name='chenjo', terminal='pts/1', host='192.168.135.1', started=1597923712.0)]
>>> import datetime
>>> psutil.boot_time()
1597925932.0
>>> datetime.datetime.fromtimestamp(psutil.boot_time()).strftime("%Y-%m-%d %H:%M:%S")
'2020-08-20 20:18:52'
>>>
1.1.2 系统进程管理方法
(1)进程信息
>>> import psutil
>>> psutil.pids()
[1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 36, 37, 38, 39, 47, 48, 49, 50, 51, 53, 66, 97, 638, 649, 655, 664, 666, 805, 810, 1678, 1683, 1824, 1828, 2876, 2877, 2887, 2890, 2893, 2894, 2895, 2896, 2897, 2898, 2899, 2900, 2973, 2998, 3010, 4696, 4923, 4931, 4937, 4939, 4944, 4945, 4947, 4951, 4956, 4962, 4965, 4966, 6128, 6129, 6134, 6136, 6138, 6160, 6164, 6166, 6171, 6172, 6174, 6175, 6179, 6180, 6181, 6187, 6188, 6204, 6207, 6208, 6209, 6210, 6212, 6215, 6218, 6255, 6256, 6273, 6327, 6813, 6815, 6816, 6822, 6824, 6861, 6862, 6865, 7069, 7071, 7794, 7799, 16233, 16975, 17196, 17200, 17201, 17352, 17356, 17396, 17397, 17466, 17470, 17553, 17557, 17645, 18143, 18460, 18483, 18524, 18637, 18639, 18643, 18730, 18766, 18767]
>>> p = psutil.Process(17557)
>>> p.name
<bound method Process.name of <psutil.Process(pid=17557, name='python') at 139991911690768>>
>>> p.exe()
'/usr/bin/python2.7;5f3e6c2d'
>>> p.cwd()
'/tmp'
>>> p.status()
'stopped'
>>> p.create_time()
1597928634.08
>>> p.uids()
puids(real=0, effective=0, saved=0)
>>> p.gids()
pgids(real=0, effective=0, saved=0)
>>> p.cpu_times()
pcputimes(user=0.01, system=0.0)
>>> p.cpu_affinity()
[0, 1]
>>> p.memory_percent()
0.27350031021032045
>>> p.memory_info()
pmem(rss=5218304, vms=133287936)
>>> p.io_counters()
pio(read_count=118, write_count=9, read_bytes=0, write_bytes=0)
>>> p.connections()
[]
>>> p.num_threads()
1
>>>
(2)popen类的使用
import psutil
from subprocess import PIPE
p = psutil.Popen(["/usr/bin/python", "-c", "print('hello')"], stdout=PIPE)
p.name()
p.username()
p.cpu_times()
p.communicate()
#p.cpu_times()
[root@ansible mycode]# python
Python 2.7.5 (default, Apr 2 2020, 13:16:51)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-39)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import psutil
>>> from subprocess import PIPE
>>> p = psutil.Popen(["/usr/bin/python", "-c", "print('hello')"], stdout=PIPE)
>>> p.name()
'python'
>>> p.username()
'root'
>>> p.cpu_times()
pcputimes(user=0.01, system=0.0)
>>> p.communicate()
('hello
', None)
>>>
参考提示
- 1.1.1节示例参考https://github.com/giampaolo/psutil
- 1.1.1节模块说明参考官网http://psutil.readthedocs.org/en/latest
1.2 实用的IP地址处理模块IPy
- Centos7上安装ipy 参考
>>> from IPy import IP
>>> IP('10.0.0.0/8').version()
4
>>> IP('::1').version()
6
>>>
>>> ip = IP('192.168.0.0/16')
>>> print ip.len()
65536
>>> for x in ip:
... print(x)
...
192.168.0.0
192.168.0.1
192.168.0.2
192.168.0.3
...
>>> print(IP('192.168.1.0').make_net('255.255.255.0'))
192.168.1.0/24
>>> print(IP('192.168.1.0/255.255.255.0', make_net=True))
192.168.1.0/24
>>> print(IP('192.168.1.0-192.168.1.255', make_net=True))
192.168.1.0/24
>>>
wantprefixlen 的取值及含义:
- wantprefixlen = 0,无返回,如192.168.1.0。
- wantprefixlen = 1,prefix格式,如192.168.1.0/24。
- wantprefixlen = 2,decimalnetmask格式,如192.168.1.0/255.255.255.0。
- wantprefixlen = 3,lastIP格式,如192.168.1.0-192.168.1.255。
>>> IP('192.168.1.0/24').strNormal(0)
'192.168.1.0'
>>> IP('192.168.1.0/24').strNormal(1)
'192.168.1.0/24'
>>> IP('192.168.1.0/24').strNormal(2)
'192.168.1.0/255.255.255.0'
>>> IP('192.168.1.0/24').strNormal(3)
'192.168.1.0-192.168.1.255'
>>>
1.2.2. 多网络计算方法详解
比较大小,是否包含
>>> from IPy import IP
>>> IP('10.0.0.0/24') < IP('12.0.0.0/24')
True
>>> '192.168.1.100' in IP('192.168.1.0/24')
True
>>> IP('192.168.1.0/24') in IP('192.168.0.0/16')
True
>>>
是否重叠
>>> IP('192.168.0.0/23').overlaps('192.168.1.0/24')
1
>>> IP('192.168.1.0/24').overlaps('192.168.2.0')
0
>>>
示例 根据输入的IP或子网返回网络、掩码、广播、方向解析、子网数、IP类型等信息
[root@ansible ops_automation]# ./ch01_ipy
Please input an IP or net-range: 192.168.1.0/24
net: 192.168.1.0
netmask: 255.255.255.0
broadcast: 192.168.1.255
reverse address: 1.168.192.in-addr.arpa.
number of subnets: 256
hexadecimal: 0xc0a80100
binary ip: 11000000101010000000000100000000
iptype: PRIVATE
[root@ansible ops_automation]# ./ch01_ipy
Please input an IP or net-range: 192.168.1.20
reverse address: 20.1.168.192.in-addr.arpa.
hexadecimal: 0xc0a80114
binary ip: 11000000101010000000000100010100
iptype: PRIVATE
参考文献
- https://github.com/haypo/python-ipy/
- https://github.com/yorkoliu/pyauto/
- http://blog.philippklaus.de/2012/12/ip-address-analysis-using-python/
- http://www.sourcecodebrowser.com/ipy/0.62/class_i_py_1_1_i_pint.html
1.3 DNS处理模块dnspython
安装
# wget http://www.dnspython.org/kits/1.9.4/dnspython-1.9.4.tar.gz
# tar -zxvf dnspython-1.9.4.tar.gz
# cd dnspython-1.9.4
# python setup.py install
1.3.1 模块域名解析方法详解
query方法的定义如下:
query(self, qname, rdtype=1, rdclass=1, tcp=False, source=None, raise_on_no_answer=True, source_port=0)
qname参数是待查询的域名,rdtype参数是资源的类型,常用的有以下几种:
- A记录,将主机名转换成IP地址
- MX记录,邮件交换记录,定义邮件服务器的域名
- CNAME记录,指别名记录,实现域名间的映射
- NS记录,标记区域的域名服务器及授权子区域。
- PTR记录,反向解析,与A记录相反,将IP转换成主机名。
- SOA记录,SOA标记,一个起始授权区的定义
rdclass参数用于指定网络类型,可选值有IN、CH与HS,其中IN为默认。
tcp参数用于指定是否启用TCP协议,默认为False。
source与source_port参数指定查询源地址与端口,默认值为查询设备IP地址与0。
raise_on_no_answer参数用于指定当查询无应答时是否触发异常。
1.3.2 常见解析类型示例说明
(1)A记录
若dnspython模块报错 AttributeError: 'CNAME' object has no attribute 'address',可参考
#!/usr/bin/env python
import dns.resolver
domain = raw_input('Please input a domain: ')
A = dns.resolver.query(domain, 'A')
for i in A.response.answer:
for j in i.items:
if j.rdtype == 1:
print(j.address)
(2)MX记录
#!/usr/bin/env python
import dns.resolver
domain = raw_input('Please input a domain: ')
MX = dns.resolver.query(domain, 'MX')
for i in MX:
print 'MX preference = ', i.preference, 'mail exchanger = ', i.exchange
以163.com域名为例:
[root@ansible ch01]# ./dnspython_ex2.py
Please input a domain: 163.com
MX preference = 10 mail exchanger = 163mx03.mxmail.netease.com.
MX preference = 10 mail exchanger = 163mx02.mxmail.netease.com.
MX preference = 10 mail exchanger = 163mx01.mxmail.netease.com.
MX preference = 50 mail exchanger = 163mx00.mxmail.netease.com.
(3)NS记录
#!/usr/bin/env python
import dns.resolver
domain = raw_input('Please input a domain: ')
ns = dns.resolver.query(domain, 'NS')
for i in ns.response.answer:
for j in i.items:
print j.to_text()
只限输入一级域名,如baidu.com。如果输入二级或多级域名,如www.baidu.com,则是错误的。
[root@ansible ch01]# ./dnspython_ex3.py
Please input a domain: baidu.com
ns3.baidu.com.
ns4.baidu.com.
dns.baidu.com.
ns2.baidu.com.
ns7.baidu.com.
(4)CNAME记录
#!/usr/bin/env python
import dns.resolver
domain = raw_input('Please input a domain: ')
cname = dns.resolver.query(domain, 'CNAME')
for i in cname.response.answer:
for j in i.items:
print j.to_text()
结果将返回cname后的目标域名。
[root@ansible ch01]# ./dnspython_ex4.py
Please input a domain: www.baidu.com
www.a.shifen.com.
1.3.3 实践:DNS域名轮询业务监控
(1)步骤
- 实现域名的解析,获取域名的所有的A记录,解析IP列表。
- 对IP列表进行HTTP级别的探测。
(2)代码实现
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import dns.resolver
import os
import httplib
iplist = [] # 定义域名IP列表变量
appdomain = "www.baidu.com" # 定义业务域名
def get_iplist(domain=""): # 域名解析函数,解析成功IP将被追加到iplist
try:
A = dns.resolver.query(domain, 'A')
except Exception, e:
print "dns resolver error: " + str(e)
return
for i in A.response.answer:
for j in i.items:
if j.rdtype == 1:
iplist.append(j.address)
return True
def checkip(ip):
checkurl = ip + ":80"
getcontent=""
httplib.socket.setdefaulttimeout(5)
conn = httplib.HTTPConnection(checkurl)
try:
conn.request("GET", "/", headers = {"Host": appdomain})
r = conn.getresponse()
getcontent = r.read(15)
finally:
if getcontent == "<!DOCTYPE html>": # 监控URL页的内容一般是事先定义好的,比如 HTTP 200 等
print ip + " [OK]"
else:
print ip + " [Error]" # 此处可放告警程序,可以是邮件、短信通知
if __name__ == "__main__":
if get_iplist(appdomain) and len(iplist) > 0:
for ip in iplist:
checkip(ip)
else:
print "dns resolver error."
我们可以将此脚本放到crontab中定时运行,再结合告警程序,这样一个基于域名轮询的业务监控已经完成。运行结果如下:
[root@ansible ch01]# ./dnspython_ex5.py
14.215.177.39 [OK]
14.215.177.38 [OK]