Python 运维实战:psutil 监控系统资源 + paramiko 远程管理服务器

一、psutil模块

psutil模块作用:协助我们完成 CPU使用率 、 内存 、磁盘信息、网络等等相关数据的采集!

1、模块介绍

psutil 是一个跨平台的 Python 库,用于检索系统的运行信息,包括 CPU 使用情况、内存状态、磁盘信息、网络统计、进程信息等,非常适合运维和系统监控应用。下面是 psutil 的一些常见用法和应用示例。

2、安装 psutil

前置操作:

第一步:启动VMware中的node1服务器(192.168.88.101)

第二步:在PyCharm中创建一个新项目,所有配置保持默认,不需要调整

第三步:在项目中,找到File菜单->Settings设置->Project关键词菜单->Python Interpreter解析器

选择On SSH:配置远程解析器

填入Linux服务器信息:

确认指纹,单击OK,然后输入Linux服务器的密码,如下图所示:

设置系统解析器:

在Linux服务器的/root目录创建一个day04Project文件夹

powershell 复制代码
mkdir -p /root/day04Project

然后更改解析器信息(注意:必须选择系统解析器):

如果选择虚拟的话,里面可以使用的包只有几种需要去下载其他包后才能使用,而选择系统默认的解释器里面则大多数包都是有的

更改源码上传位注意更改源码上传位置::

进入到Linux服务器,可以通过以下命令安装 psutil

powershell 复制代码
dnf install python3-pip -y
pip install psutil -i https://pypi.tuna.tsinghua.edu.cn/simple

注:
pip install 软件包名称,安装软件
-i 指定镜像源,说白了就是从哪里下载软件
https://pypi.tuna.tsinghua.edu.cn/simple清华镜像源

3、官方文档

官方地址:https://github.com/giampaolo/psutil

4、获取CPU使用情况

获取CPU使用率

python 复制代码
import psutil

# 获取 CPU 总使用率,1 秒间隔
cpu_usage = psutil.cpu_percent(interval=1)
print("CPU usage:", cpu_usage, "%")

常见运行报错解决方案:

获取每个核心的 CPU 使用率

第一个核心使用率,第二个核心使用率,第三个核心使用率,第四个核心使用

python 复制代码
import psutil

# 获取每个核心的CPU使用率
for i in range(psutil.cpu_count()):
    print("CPU usage of core", i, ":", psutil.cpu_percent(interval=1, percpu=True)[i], "%")

5、获取内存使用情况

字节Bytes => /1024 KB千字节 => /1024 MB兆字节 => /1024 GB

python 复制代码
import psutil

# 获取物理内存信息
memory_info = psutil.virtual_memory()
print("Total memory:", memory_info.total // (1024 ** 2), "MB")
print("Used memory:", memory_info.used // (1024 ** 2), "MB")
print("Memory usage:", memory_info.percent, "%")

获取交换内存信息

powershell 复制代码
import psutil

# 获取交换内存信息
swap_info = psutil.swap_memory()
print("Total swap:", swap_info.total // (1024 ** 2), "MB")
print("Used swap:", swap_info.used // (1024 ** 2), "MB")
print("Swap usage:", swap_info.percent, "%")

6、获取磁盘使用情况

powershell 复制代码
import psutil

# 获取磁盘分区
partitions = psutil.disk_partitions()   # disk_partitions() 获取磁盘的所有分区
for partition in partitions:
    print(f"Device: {partition.device}, Mountpoint: {partition.mountpoint}, Filesystem: {partition.fstype}")

# 获取指定分区的使用情况
disk_usage = psutil.disk_usage('/')
print("Total disk space:", disk_usage.total // (1024 ** 3), "GB")
print("Used disk space:", disk_usage.used // (1024 ** 3), "GB")
print("Disk usage:", disk_usage.percent, "%")

获取磁盘IO:

I:Input

O:Output

磁盘IO指的是系统对磁盘设备进行数据读写的过程,主要包括:

  • 读取操作:从磁盘中读取数据到内存。

  • 写入操作:将数据从内存写入到磁盘。

磁盘IO性能通常受磁盘硬件、文件系统类型、RAID配置和磁盘缓存的影响。

常见指标:

  • IOPS(Input/Output Operations Per Second):每秒处理的IO操作数量。

  • 吞吐量:磁盘每秒处理的数据量(如MB/s或GB/s)。

  • 比如:一块SSD的读写速度标称为 3.5 GB/s,表示它每秒可以读取或写入3.5GB的数据。

计算磁盘的IOPS:

python 复制代码
import psutil
import time

# 第一次采样
disk_io_1 = psutil.disk_io_counters()
time.sleep(1)  # 等待1秒
# 第二次采样
disk_io_2 = psutil.disk_io_counters()

# 计算吞吐量 (MB/s)
read_bytes_diff = disk_io_2.read_bytes - disk_io_1.read_bytes
write_bytes_diff = disk_io_2.write_bytes - disk_io_1.write_bytes
read_mb_s = read_bytes_diff / (1024 * 1024)  # 转换为MB/s
write_mb_s = write_bytes_diff / (1024 * 1024)  # 转换为MB/s

# 计算IOPS
read_iops = disk_io_2.read_count - disk_io_1.read_count
write_iops = disk_io_2.write_count - disk_io_1.write_count

print(f"读取吞吐量: {read_mb_s:.2f} MB/s")
print(f"写入吞吐量: {write_mb_s:.2f} MB/s")
print(f"读取IOPS: {read_iops}")
print(f"写入IOPS: {write_iops}")

---------------------------------------------------------------------------
psutil.disk_io_counters() 返回一个对象,包含以下关键属性(指标): 
read_bytes:从磁盘读取的总字节数。
write_bytes:写入磁盘的总字节数。
read_count:读取操作的次数(可用于计算IOPS)。
write_count:写入操作的次数。

运行结果:

powershell 复制代码
读取吞吐量: 15.75 MB/s
写入吞吐量: 8.20 MB/s
读取IOPS: 1200
写入IOPS: 600

理论值参考:

吞吐量:HDD(顺序读写约100-200 MB/s),SATA SSD(500-550 MB/s)或NVMe SSD(3-7 GB/s)

IOPS:HDD(100-200 IOPS),SATA SSD(1万-10万IOPS)或NVMe SSD(10万-100万IOPS)

7、获取网络信息

获取网络I/O统计

网络IO指的是系统通过网络接口进行数据收发的过程,主要包括:

  • 接收操作:从网络中接收数据包。

  • 发送操作:通过网络发送数据包。

  • 带宽:单位时间内网络传输的数据量(如Mbps或Gbps)。

  • 延迟:网络数据包从源到目标的时间。

  • 吞吐量:实际传输的数据量,通常小于带宽上限。


普及一个概念:千兆带宽1Gb/s(注意这里b是小写的!!!)

Gb/s:表示 Gigabit per second(千兆比特每秒),1 Gb = 10亿比特(10^9 bits)。

GB/s:表示 Gigabyte per second(吉字节每秒),1 GB = 10亿字节(10^9 Bytes)。

关键区别:1 Byte(字节) = 8 bits(比特),所以 1 GB/s = 8 Gb/s。

所以千兆带宽的理论传输速度约为125MB/s,百兆带宽理论传输速度约为12.5MB/s

python 复制代码
import psutil

# 获取网络流量统计
net_io = psutil.net_io_counters()
print("Bytes sent:", net_io.bytes_sent)
print("Bytes received:", net_io.bytes_recv)

-----------------------------------------------
psutil.net_io_counters() 返回一个命名元组,包含系统所有网络接口(如Wi-Fi、以太网)的累计网络IO统计数据
主要指标: 
bytes_sent:系统发送的总字节数(上传流量)。
bytes_recv:系统接收的总字节数(下载流量)。
其他指标包括: 
packets_sent:发送的数据包数。
packets_recv:接收的数据包数。
errin/errout:接收/发送的错误数。
dropin/dropout:接收/发送丢弃的数据包数。

获取网络IO吞吐量:

powershell 复制代码
import psutil
import time

# 第一次采样
net_io_1 = psutil.net_io_counters()
time.sleep(1)  # 等待1秒
# 第二次采样
net_io_2 = psutil.net_io_counters()

# 计算吞吐量 (MB/s)
bytes_sent_diff = net_io_2.bytes_sent - net_io_1.bytes_sent
bytes_recv_diff = net_io_2.bytes_recv - net_io_1.bytes_recv
send_mb_s = bytes_sent_diff / (1024 * 1024)  # 转换为MB/s
recv_mb_s = bytes_recv_diff / (1024 * 1024)  # 转换为MB/s

print(f"发送吞吐量: {send_mb_s:.2f} MB/s")
print(f"接收吞吐量: {recv_mb_s:.2f} MB/s")

获取网路接口(网卡,如lo网卡、ens33/ens160/eth0)地址信息

powershell 复制代码
import psutil

net_if_addrs = psutil.net_if_addrs()
for interface_name, interface_addresses in net_if_addrs.items():
    print(f"接口名称: {interface_name}")
    print(f"接口地址: {interface_addresses[0].address}")

小结:

网络信息采集通常采集两个方面:(网络IO,使用net_io_counters)与 (网卡信息,使用net_if_addrs)

8、psutil运维场景:获取cpu使用率

监控CPU使用率,超过80%(阈值)就发给邮件给运维,前置知识点:https://docs.python.org/3.9/library/smtplib.html

powershell 复制代码
import psutil
import smtplib
from email.mime.text import MIMEText
from email.header import Header

# 设置邮箱地址和授权码
from_addr = '你的邮箱'
to_addr = '目标邮箱'
auth_code = '你的邮箱授权码'  # 早期版本都是使用的是邮箱密码,有安全隐患,现在使用的都是授权码(不能登录邮箱,只能用于邮件发送)

# 获取 CPU 使用率
cpu_percent = psutil.cpu_percent()

# 判断 CPU 使用率是否超过阈值
if cpu_percent > 80:
    # 构造邮件内容
    subject = '警报:高 CPU 使用率'
    message = 'CPU 使用率超过 80%:当前使用率为 {}%'.format(cpu_percent)

    # 使用 MIMEText 创建邮件对象,指定编码为 UTF-8,plain:代表纯文本
    msg = MIMEText(message, 'plain', 'utf-8')
    msg['Subject'] = Header(subject, 'utf-8')
    msg['From'] = from_addr  # 用于显示的发件人
    msg['To'] = to_addr      # 用于显示的收件人

    # 建立 SMTP 连接
    server = smtplib.SMTP('smtp.163.com')
    server.login(from_addr, auth_code)

    # 发送邮件
    server.sendmail(from_addr, to_addr, msg.as_string())
    server.quit()

测试:在linux端下载一个压力测试工具 yun install stress-ng -y;接着输入命令进行测试stress-ng --cpu n --timeout 60s

n表示虚拟机机子的CPU核心数n可以是4或者6...,60秒,表示把CPU压力满的时间为60s,60s之后就恢复正常了

小结:

整个案例一共使用了3个模块:检查系统CPU信息(psutil)、发送邮件(email)

另外特别注意:邮件发送时,使用的密码并不是邮件密码,而是邮件授权码!!!

二、paramiko模块

目标:paramiko主要用于实现(远程登录)、(文件上传)与(下载功能)

1、模块介绍

paramiko模块支持以加密和认证的方式连接远程服务器。可以实现远程文件的上传,下载或通过ssh远程执行命令。

Linux上写shell脚本远程ssh操作处理密码有两种方法:

  • ssh-keygen实现免密操作,这样远程连接不用输入密码 ssh 192.168.88.102 touch /tmp/123

  • expect自动应答处理密码

powershell 复制代码
#!/bin/bash

# 删除 .ssh/known_hosts 中的旧记录,以便每次登录都需要确认
sed -i /^192.168.88.102/d /root/.ssh/known_hosts

# 使用 expect 自动化 SSH 登录
expect <<EOF
    spawn ssh 192.168.88.102        # 执行 SSH 登录
    expect "(yes/no)?"                       # 等待出现 yes/no 确认提示
    send "yes\n"                                  # 发送 yes 确认
    expect "password:"                    # 等待输入密码提示
    send "123\n"                                 # 输入密码
    expect "]"                                        # 等待登录成功提示符
    send "touch /tmp/123\n"        # 登录成功后执行命令
    send "exit\n"                                 # 退出 SSH

expect eof
EOF

2、安装paramiko

powershell 复制代码
pip install paramiko -i https://pypi.tuna.tsinghua.edu.cn/simple

3、使用paramiko实现远程登录

python 复制代码
import paramiko

# 创建sshclient对象
ssh = paramiko.SSHClient()  # 创建一个客户端连接实例
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy)  # 加了这一句,如果第一次ssh连接要你输入yes,也不用输入了
ssh.connect(hostname="192.168.88.102", port=22, username="root", password="123456")  # 指定连接的ip,port,username,password

stdin,stdout,stderr = ssh.exec_command("touch /tmp/file.txt")   # 执行一个命令,有标准输入,输出和错误输出

# 标准输入可以忽略
cor_res = stdout.read()  # 标准输出赋值
err_res = stderr.read()  # 错误输出赋值

print(cor_res.decode())        # 网络传输是二进制需要decode(我们没有讨论socket编程,所以你就直接这样做)
print(err_res.decode())        # 不管正确的还是错误的输出,都打印出来

ssh.close() # 关闭此连接实例

paramiko 中,ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 用于指定在首次连接到一个新主机时的处理策略。

作用

自动接受未知主机:在首次连接到一个新的主机(即 known_hosts 文件中没有记录的主机)时,通常会提示确认连接,要求输入 yesno

避免手动确认:使用 AutoAddPolicy 后,paramiko 会自动将未知主机的主机密钥添加到 known_hosts 文件中,而不提示用户手动确认。

把以上内容封装为函数

python 复制代码
# 1. 导入模块
import paramiko

# 2. 封装函数
def ssh_exec(hostname, password, cmd, port=22, username='root'):
    # 创建SSHClient对象
    ssh = paramiko.SSHClient()
    # 允许连接不在know_hosts文件中的主机
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    # 连接服务器
    ssh.connect(hostname=hostname, port=port, username=username, password=password)
    # 执行命令,获取返回结果 => 标准输入 + 标准输出1 + 标准错误2
    stdin, stdout, stderr = ssh.exec_command(cmd)
    # 返回最终的结果
    print(stdout.read().decode())
    print(stderr.read().decode())
    # 关闭SSH连接
    ssh.close()

# 3. 调用函数
# ssh_exec('192.168.88.102', '123456', 'ls /')
while True:
    cmd = input('[root@node2 ~]# ')
    ssh_exec('192.168.88.102', '123456', cmd)

4、使用paramiko免密远程登录操作

node1服务器生成秘钥,发送公钥给node2服务器,然后才能使用paramiko实现免密登录!

powershell 复制代码
# ssh-keygen
# ssh-copy-id root@192.168.88.102
powershell 复制代码
import paramiko

ssh = paramiko.SSHClient()                        # 创建一个客户端连接实例
private_key = paramiko.RSAKey.from_private_key_file("/root/.ssh/id_rsa")        # 提前先做好ssh等效性(也就是免密登陆)
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy)  # 加了这一句,如果第一次ssh连接要你输入yes,也不用输入了
ssh.connect(hostname="192.168.88.102",port=22,username="root",pkey=private_key)        # 把password=123456换成pkey=private_key
stdin,stdout,stderr = ssh.exec_command("touch /tmp/paramiko.txt")
cor_res = stdout.read()
err_res = stderr.read()

print(cor_res.decode())
print(err_res.decode())

ssh.close()

5、使用paramiko实现文件上传下载

基于账号密码操作

powershell 复制代码
import paramiko
# 创建传输连接
trans = paramiko.Transport(("192.168.88.102",22))  # 参数比较特殊,要求必须是一个元组类型
# 使用账号密码连接node2服务器
trans.connect(username="root",password="123456")
# 创建sftp对象实现文件的上传与下载
sftp = paramiko.SFTPClient.from_transport(trans)
# 下载文件
sftp.get("/etc/fstab","/tmp/fstab1") # 把对方机器的/etc/fstab下载到本地为/tmp/fstab(注意不能只写/tmp,必须要命名)
# 上传文件
sftp.put("/etc/inittab","/tmp/inittab1") # 本地的上传,也一样要命令
# 关闭连接
trans.close()

基于免密操作

node1:

powershell 复制代码
# ssh-keygen
# ssh-copy-id root 192.168.88.102

编写执行代码

powershell 复制代码
import paramiko
# 创建传输连接
trans = paramiko.Transport(("192.168.88.102",22))
# 使用私钥进行登录验证
private_key = paramiko.RSAKey.from_private_key_file("/root/.ssh/id_rsa")
trans.connect(username="root",pkey=private_key) # 提前使用ssh-keygen做好免密登录
# 创建sftp对象
sftp = paramiko.SFTPClient.from_transport(trans)
# 实现文件的上传与下载
sftp.get("/etc/fstab","/tmp/fstab2")
sftp.put("/etc/inittab","/tmp/inittab2") 

trans.close()

小结:

paramiko作用?实现(远程登录)、((上传)、(下载)、执行远程命令(模拟MobaXterm软件)等功能

paramiko既支持密码登录,还支持(免密)登录?

相关推荐
几度热忱2 小时前
【uv包管理工具】常用命令记录
python·uv
weixin_568996062 小时前
处理大体积DBF文件导入卡顿怎么办_性能优化与分批操作
jvm·数据库·python
xcbrand2 小时前
工业制造品牌全案公司哪家专业
大数据·人工智能·python·制造
m0_640309302 小时前
如何处理SQL查询中的逻辑重叠:AND OR嵌套优先级
jvm·数据库·python
qq_432703662 小时前
如何快速定位SQL表中的特定行:ROWID与唯一键的应用
jvm·数据库·python
m0_377618232 小时前
mysql如何配置插件以提升查询性能_安装启用memcached插件
jvm·数据库·python
djjdjdjdjjdj2 小时前
SQL高效实现两表数据对比_利用FULL OUTER JOIN查找差异
jvm·数据库·python
qq_424098562 小时前
html标签怎么表示用户输入_kbd标签键盘快捷键标注【介绍】
jvm·数据库·python
qq_372154232 小时前
PHP 中使用 GnuPG 实现 PGP 加密与解密的完整实践指南
jvm·数据库·python