• Python使用开源库psutil库监控Linux


    Psutil库是一个开源且跨平台的库,其提供了便利的函数来获取操作系统的信息,如CPU,内存,磁盘,网络等信息。

    安装方式:pip install psutil.

    下面介绍一下相关的监控函数,具体操作的环境在ipython中,安装:yum install ipython

    1、CPU

    cpu相关的功能函数

    1)cpu_count默认返回逻辑cpu的个数,也可以指定logical=false获取物理cpu的个数。

    In [1]: import psutil
    
    In [2]: psutil.cpu_count()
    
    Out[2]: 2
    
    In [4]: psutil.cpu_count(logical=False)
    
    Out[4]: 2

    2)cpu_percent返回cpu的利用率,可以通过interval参数阻塞式地获取interval时间范围内的cpu利用率,否则,获取上一次调用cpu_percent这段时间以来的cpu利用率。可以使用percent参数指定获取每个cpu的利用率,默认获取整体的cpu利用率。

    In [5]: psutil.cpu_percent()
    
    Out[5]: 0.1
    
    In [7]: psutil.cpu_percent(percpu=True)
    
    Out[7]: [0.1, 0.0]

    3)cpu_times以命名元组的形式返回cpu的时间花费,也可以通过percpu参数指定获取每个cpu的统计时间。

    In [8]: psutil.cpu_times()
    
    Out[8]: scputimes(user=23.62, nice=0.0, system=38.07, idle=17458.43, iowait=16.43, irq=0.0, softirq=0.24, steal=0.0, guest=0.0, guest_nice=0.0)

    4)cpu_times_percent与cpu_times类似,但是返回的是耗费时间的比例。

    In [9]: psutil.cpu_times_percent()
    
    Out[9]: scputimes(user=0.0, nice=0.0, system=0.1, idle=99.9, iowait=0.0, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0)

    5)cpu_stats以命令元组的形式返回cpu的统计信息,包括上下文切换、中断、软中断和系统调用的次数。

    In [10]: psutil.cpu_stats()
    
    Out[10]: scpustats(ctx_switches=1070599, interrupts=639997, soft_interrupts=620611, syscalls=0)

    2、内存

    与内存相关的功能函数

    1)virtual_memory以命名元组的形式返回内存使用情况,包括总内存、可用内存、内存利用率、buffercached等。

    In [11]: psutil.virtual_memory()
    
    Out[11]: svmem(total=1907970048, available=1509765120, percent=20.9, used=240463872, free=1449373696, active=199106560, inactive=139300864, buffers=2125824, cached=216006656, shared=10063872, slab=54452224)
    
    In [12]: psutil.virtual_memory().total
    
    Out[12]: 1907970048

    #将字节转换成人类可读的函数

    def bytes2human(n):
    
            symbols = ('K','M','G','T','P','E','Z','Y')
    
            prefix = {}
    
            for i,s in enumerate(symbols):
    
                prefix[s] = 1 << (i + 1) *10
    
            for s in reversed(symbols):
    
                if n >= prefix[s]:
    
                    value = float(n) / prefix[s]
    
                    return '%.1f%s' % (value,s)
    
            return "%sB" % n
    In [14]:  bytes2human(psutil.virtual_memory().total)
    
    Out[14]: '1.8G'

    2)swap_memory以命名元组的形式返回swap memory的使用情况。

    In [15]: psutil.swap_memory()
    
    Out[15]: sswap(total=2147479552, used=0, free=2147479552, percent=0.0, sin=0, sout=0)

    3、磁盘

    与磁盘相关的功能函数

    1)disk_partitions返回所有已经挂的磁盘,以命名元组的形式返回。命名元组包含磁盘名称、挂载点、文件系统类型等信息。

    In [16]: psutil.disk_partitions()
    
    Out[16]:
    
    [sdiskpart(device='/dev/sda3' mountpoint='/', fstype='xfs', opts='rw,relatime,attr2,inode64,noquota'),
    
     sdiskpart(device='/dev/sda1', mountpoint='/boot', fstype='xfs', opts='rw,relatime,attr2,inode64,noquota')] 
    
    def get_disk_via_mountpoint(mountpoint):
    
            disk = [item for item in psutil.disk_partitions() if item.mountpoint == mountpoint]
    
            return disk[0].device
    
    In [18]: get_disk_via_mountpoint('/')
    
    Out[18]: '/dev/sda3'
    
    In [19]: get_disk_via_mountpoint('/boot')
    
    Out[19]: '/dev/sda1'

    2)disk_usage获取磁盘的使用情况,包括磁盘的容量、磁盘的空间利用率。

    In [21]: psutil.disk_usage('/')
    
    Out[21]: sdiskusage(total=18242076672, used=6832975872, free=11409100800, percent=37.5)
    
    In [22]: bytes2human(psutil.disk_usage('/').total)
    
    Out[22]: '17.0G'

    3)disk_io_counters以命名元组的形式返回磁盘io统计信息,包括读的次数,写的次数,读字节数,写字节数。

    In [23]: psutil.disk_io_counters()
    
    Out[23]: sdiskio(read_count=8407, write_count=2567, read_bytes=195427840, write_bytes=54457856, read_time=38577, write_time=34691, read_merged_count=2, write_merged_count=613, busy_time=24421)

    4、网络

    与网络相关的功能函数

    1)net_io_counter返回当前系统中网络io统计信息是监控系统中最需要关注的网络信息。net_io_counter函数以命名元组的形式返回了每块网卡的网络io统计信息,包括收发字节数,收发包的数量,出错情况与删包情况。

    In [24]: psutil.net_io_counters()
    
    Out[24]: snetio(bytes_sent=658478, bytes_recv=290760, packets_sent=3387, packets_recv=2735, errin=0, errout=0, dropin=0, dropout=0) 
    
    In [25]: psutil.net_io_counters(pernic=True)
    
    Out[25]:
    
    {'ens33': snetio(bytes_sent=385132, bytes_recv=293910, packets_sent=1740, packets_recv=2765, errin=0, errout=0, dropin=0, dropout=0),
    
     'ens37': snetio(bytes_sent=275804, bytes_recv=0, packets_sent=1662, packets_recv=0, errin=0, errout=0, dropin=0, dropout=0),
    
     'lo': snetio(bytes_sent=0, bytes_recv=0, packets_sent=0, packets_recv=0, errin=0, errout=0, dropin=0, dropout=0)}

    2)net_connections以列表的形式返回第个网络网接详细信息。可以行使查看网络连连状态。统计连接个数以及处于特定状态的网络连接个数。

    In [26]: psutil.net_connections()
    
    Out[26]:
    
    [sconn(fd=1, family=2, type=2, laddr=addr(ip='127.0.0.1', port=323), raddr=(), status='NONE', pid=6155),
    
     sconn(fd=22, family=10, type=1, laddr=addr(ip='::', port=3306), raddr=(), status='LISTEN', pid=7054),
    
     sconn(fd=3, family=2, type=1, laddr=addr(ip='0.0.0.0', port=22), raddr=(), status='LISTEN', pid=6550),
    
     sconn(fd=4, family=10, type=1, laddr=addr(ip='::', port=22), raddr=(), status='LISTEN', pid=6550),
    
     sconn(fd=2, family=10, type=2, laddr=addr(ip='::1', port=323), raddr=(), status='NONE', pid=6155),
    
     sconn(fd=3, family=2, type=1, laddr=addr(ip='10.0.0.171', port=22), raddr=addr(ip='10.0.0.1', port=20590), status='ESTABLISHED', pid=6705),
    
     sconn(fd=13, family=2, type=1, laddr=addr(ip='127.0.0.1', port=25), raddr=(), status='LISTEN', pid=7832),
    
     sconn(fd=14, family=10, type=1, laddr=addr(ip='::1', port=25), raddr=(), status='LISTEN', pid=7832),
    
     sconn(fd=7, family=2, type=2, laddr=addr(ip='0.0.0.0', port=68), raddr=(), status='NONE', pid=17166),
    
     sconn(fd=3, family=2, type=1, laddr=addr(ip='10.0.0.171', port=22), raddr=addr(ip='10.0.0.1', port=20696), status='ESTABLISHED', pid=15983)]

    3)net_if_addrs以字典的形式返回网卡的配置信息,包括ip地址、子网掩码、MAC地址和广播地址。

    In [27]: psutil.net_if_addrs()
    
    Out[27]:
    
    {'ens33': [snicaddr(family=2, address='10.0.0.171', netmask='255.255.255.0', broadcast='10.0.0.255', ptp=None),
    
      snicaddr(family=10, address='fe80::479e:194c:b6bb:9553%ens33', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None),
    
      snicaddr(family=17, address='00:0c:29:a2:07:95', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)],
    
     'ens37': [snicaddr(family=17, address='00:0c:29:a2:07:9f', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)],
    
     'lo': [snicaddr(family=2, address='127.0.0.1', netmask='255.0.0.0', broadcast=None, ptp=None),
    
      snicaddr(family=10, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None, ptp=None),
    
      snicaddr(family=17, address='00:00:00:00:00:00', netmask=None, broadcast=None, ptp=None)]}

    4)net_if_stats返回网卡的详细信息,包括是否启动、通信类型、传输速度与mtu。

    In [29]: psutil.net_if_stats()
    
    Out[29]:
    
    {'ens33': snicstats(isup=True, duplex=2, speed=1000, mtu=1500),
    
     'ens37': snicstats(isup=True, duplex=2, speed=1000, mtu=1500),
    
     'lo': snicstats(isup=True, duplex=0, speed=0, mtu=65536)}

    5、其他

    1)users以命名元组的方式返回当前登录用户的信息,包括用户名,登录时间,终端与主机的信息。

    In [30]: psutil.users()
    
    Out[30]:
    
    [suser(name='root', terminal='tty1', host='', started=1591761024.0, pid=6176),
    
     suser(name='root', terminal='pts/0', host='10.0.0.1', started=1591761024.0, pid=6884),
    
     suser(name='root', terminal='pts/1', host='10.0.0.1', started=1591761152.0, pid=15985)]

    2)boot_time以时间戳的形式返回系统的启动时间

    In [31]: psutil.boot_time()
    
    Out[31]: 1591760992.0
    
     datetime.datetime.fromtimestamp(psutil.boot_time()).strftime("%Y-%M-%D %H:%M:%S")
    
    Out[33]: '2020-49-06/10/20 11:49:52'

    6、一个案例:使用psutil实现监控程序

    在程序中,使用psutil收集了cpu的信息,开机时间,内存信息,磁盘信息,网络信息等。

    monitor.py具体内容如下:

    #!/usr/bin/python
    # -*- coding: UTF-8 -*-
    from __future__ import unicode_literals
    import os
    import socket
    from datetime import datetime
    
    import jinja2
    import yagmail
    import psutil
    
    
    EMAIL_USER = 'mick_bing@126.com'        #发送邮箱帐号
    EMAIL_PASSWORD = '***********'     #发送邮箱登录码或授权码
    RECIPIENTS = ['eeexu123@163.com','eee@sohu.com']       #接收邮件的帐号
    
    
    #将获取到的监控信息写入monitor.html中
    def render(tpl_path, **kwargs):
        path, filename = os.path.split(tpl_path)
        return jinja2.Environment(
            loader=jinja2.FileSystemLoader(path or './')
        ).get_template(filename).render(**kwargs)
    
    #将获取的信息转化为人类可读
    def bytes2human(n):
        symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
        prefix = {}
        for i, s in enumerate(symbols):
            prefix[s] = 1 << (i + 1) * 10
        for s in reversed(symbols):
            if n >= prefix[s]:
                value = float(n) / prefix[s]
                return '%.1f%s' % (value, s)
        return "%sB" % n
    
    #获取CPU的信息
    def get_cpu_info():
        cpu_count = psutil.cpu_count()  #CPU的逻辑个数
        cpu_percent = psutil.cpu_percent(interval=1)    #CPU的利用率
        return dict(cpu_count=cpu_count, cpu_percent=cpu_percent)
    
    #获取内存的信息
    def get_memory_info():
        virtual_mem = psutil.virtual_memory()
    
        mem_total = bytes2human(virtual_mem.total)  #内存总量  
        mem_percent = virtual_mem.percent   #内存的利用率
        mem_free = bytes2human(virtual_mem.free + virtual_mem.buffers + virtual_mem.cached) #内存的可使用空间
        mem_used = bytes2human(virtual_mem.total * virtual_mem.percent) #内存的已使用空间
    
        return dict(mem_total=mem_total, mem_percent=mem_percent,
                    mem_free=mem_free, mem_used=mem_used)
    
    #获取磁盘的信息
    def get_disk_info():
        disk_usage = psutil.disk_usage('/')
    
        disk_total = bytes2human(disk_usage.total)  #磁盘的总量
        disk_percent = disk_usage.percent   #磁盘的利用率
        disk_free = bytes2human(disk_usage.free)    #磁盘可用空间
        disk_used = bytes2human(disk_usage.used)    #磁盘已用空间
    
        return dict(disk_total=disk_total, disk_percent=disk_percent,
                    disk_free=disk_free, disk_used=disk_used)
    
    #获取网络信息
    def get_net_info():
        net_info = psutil.net_io_counters()  
        net_sent = net_info.bytes_sent         #网络发送字节数
        net_recv = net_info.bytes_recv         #网络接收字节数
        packet_sent = net_info.packets_sent     #网络发送数据包
        packet_recv = net_info.packets_recv     #网络接收数据包
    
        return dict(net_sent=net_sent,net_recv=net_recv,packet_sent=packet_sent,packet_recv=packet_recv)
    
    #获取系统开机时间
    def get_boot_info():
        boot_time = datetime.fromtimestamp(psutil.boot_time()).strftime("%Y-%m-%d %H:%M:%S")    #获取开机的时间戳,并将时间戳转化年月日
        return dict(boot_time=boot_time)
    
    #获取信息更新
    def collect_monitor_data():
        data = {}
        data.update(get_boot_info())
        data.update(get_cpu_info())
        data.update(get_memory_info())
        data.update(get_disk_info())
        data.update(get_net_info())
        return data
    
    
    def main():
    
        hostname = socket.gethostname() #获取系统主机的时间
        data = collect_monitor_data()
        data.update(dict(hostname=hostname))
    
        content = render('monitor.html', **data)
        print content
    
        with yagmail.SMTP(user=EMAIL_USER, password=EMAIL_PASSWORD,
                          host='smtp.126.com') as yag:
            for recipient in RECIPIENTS:
                yag.send(recipient, "监控信息".encode('utf-8'), content.encode('utf-8'))
    
    
    if __name__ == '__main__':
        main()

    我们将所有收集的监控数据保存在一个字典中,并以解引用的方式传递给render函数。render函数的作用非常简单,在默认的情况下根据模板的名称在当前目录下查找模板,然后使用jinja2进行模板渲染。模板渲染以后,就得到一个HTML形式的字符串。在此例中,模板形式如下:

    <html>
        <head><title>监控信息</title>
        <body>
            <table border="1">
                <tr><td>服务器名称</td><td>{{hostname}}</td></tr>
                <tr><td>开机时间</td><td>{{boot_time}}</td></tr>
    
                <tr><td>CPU个数</td><td>{{cpu_count}}</td></tr>
                <tr><td>CPU利用率</td><td>{{cpu_percent}}%</td></tr>
    
                <tr><td>内存总量</td><td>{{mem_total}}</td></tr>
                <tr><td>内存利用率</td><td>{{mem_percent}}%</td></tr>
                <tr><td>内存已用空间</td><td>{{mem_used}}</td></tr>
                <tr><td>内存可用空间</td><td>{{mem_free}}</td></tr>
    
                <tr><td>磁盘空间总量</td><td>{{disk_total}}</td></tr>
                <tr><td>磁盘空间利用率</td><td>{{disk_percent}}%</td></tr>
                <tr><td>磁盘已用空间</td><td>{{disk_used}}</td></tr>
                <tr><td>磁盘可用空间</td><td>{{disk_free}}</td></tr>
    
                <tr><td>网络发送数据包</td><td>{{packet_sent}}</td></tr>
                <tr><td>网络接收数据包</td><td>{{packet_recv}}</td></tr>
            </table>
        </body>
    </html>         

    运行程序所得如下:

  • 相关阅读:
    WPF分页控件
    Anroid图标尺寸
    linux常用快捷键
    securecrt中vim行号下划线问题及SecureCRT里root没有高亮的设置,修改linux终端命令行颜色
    ANT-普通替换和正则替换
    js实现IOS上删除app时颤抖动画j函数
    php语法错误导致服务器错误(500)解决
    Linux 常用命令大全2
    Linux 命令行快捷键
    backbone源代码注释(部分)
  • 原文地址:https://www.cnblogs.com/eeexu123/p/13092738.html
Copyright © 2020-2023  润新知