Python 自动化运维学习笔记

1. 在 Linux 系统上安装 Python

  1. 从模板机克隆一台 CentOS 8 虚拟机
  2. 点击下载 Python3 软件包,并将其上传至虚拟机
  3. 在 Linux 系统上部署 Python3 环境并安装
bash 复制代码
# 安装编译环境
yum install -y openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel libffi-devel gcc gcc-c++ make

# 解压缩软件包
tar zxvf Python-3.13.2.tgz
cd Python-3.13.2/

# 配置编译参数
./configure --prefix=/usr/local/python3

# 编译并安装
make && make install

# 创建系统软链接
ln -s /usr/local/python3/bin/python3 /usr/bin/python3
ln -s /usr/local/python3/bin/pip3 /usr/bin/pip

# 验证结果
python3 --version
  1. 配置 pip 国内镜像源
bash 复制代码
# 创建并编辑配置文件
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple/
vim /root/.config/pip/pip.conf

[global]
timeout=40
index-url=http://mirrors.aliyun.com/pypi/simple/
extra-index-url=
    https://pypi.tuna.tsinghua.edu.cn/simple/
    http://pypi.douban.com/simple/
    http://pypi.mirrors.ustc.edu.cn/simple/
[install]
trusted-host=
    pypi.tuna.tsinghua.edu.cn
    mirrors.aliyun.com
    pypi.douban.com
    pypi.mirrors.ustc.edu.cn

# 更新 pip 版本至最新
/usr/local/python3/bin/python3.13 -m pip install --upgrade pip

# 验证结果
pip list

2. 系统信息模块

2.1 psutil

psutil 是一个跨平台库,能够轻松实现获取系统运行的进程和系统利用率,如 CPU、内存、磁盘、网络等。它主要应用于系统监控、分析、限制系统资源以及进程管理

例如:获取系统当前物理内存总大小以及已使用大小,使用 Shell 获取的命令如下:

bash 复制代码
# 获取内存使用情况的命令与结果如下:
[root@localhost ~ 14:47:51]# free -m
              total        used        free      shared  buff/cache   available
Mem:           3633         296        1697          16        1639        3076
Swap:          4019           0        4019

# 将物理内存 Mem 行过滤出来的代码如下:
[root@localhost ~ 14:48:29]# free -m | grep Mem
Mem:           3633         296        1697          16        1639        3076

# 将 Mem 列的第二个数据(总容量)提取出来的命令如下:
[root@localhost ~ 14:49:57]# free -m | grep Mem | awk '{ print $2 }'
3633

# 将 Mem 列的第三个数据(已使用容量)提取出来的命令如下:
[root@localhost ~ 14:50:45]# free -m | grep Mem | awk '{ print $3 }'
297

使用 Python 获取的代码如下:

!NOTE

使用 psutil 工具前,需要先运行 pip install psutil 进行安装

CentOS 系统中执行 Python 命令前,应当先在控制台运行 Python3 进入到 Python 命令行

py 复制代码
import psutil
mem = psutil.virtual_memory()
print("Total Mem: ",mem.total)
print("Used Mem: ",mem.used)

2.2 获取性能信息

2.2.1 获取 CPU 信息

使用以下参数可以获取 CPU 的指定信息:

参数 获取的信息
psutil.cpu_times().user 获取 CPU 的用户使用时间比
psutil.cpu_times().system 获取 CPU 的系统使用时间比
psutil.cpu_count() 获取 CPU 的逻辑核心数
psutil.cpu_count(logical=False) 获取 CPU 的物理核心数

示例:

py 复制代码
import psutil
print("User time: ", psutil.cpu_times().user, "%")
print("System time: ", psutil.cpu_times().system, "%")
print("Physical Cores: ", psutil.cpu_count(logical=False))
print("Logical Threads: ", psutil.cpu_count())

输出结果示例:

bash 复制代码
User time:  89.05 %
System time:  95.1 %
Physical Cores:  4
Logical Threads:  4

2.2.2 获取内存信息

Linux 系统的内存利用率信息涉及 total(内存总数)、used(已使用的内存数)、free(空闲内存数)、bufers(缓冲使用数)、cache(缓存使用数)、swap(交换分区使用数)等,分别使用 psutil.virtual_memory()psutil.swap_memory() 方法获取这些信息

使用以下参数可以获取内存的指定信息:

| 参数 | 子参数 | 获取的信息 |

|-|-|

| psutil.virutal_memory() | mem | 内存完整信息 |

| | total | 内存总空间,单位:Byte |

| | free | 内存空余空间,单位:Byte |

| psutil.swap_memory() | mem | swap 完整信息 |

| | total | swap 总空间,单位:Byte |

| | free | swap 空余空间,单位:Byte |

示例:

py 复制代码
import psutil
mem = psutil.virtual_memory()
print('mem_total: ',mem.total)
print('mem_free: ',mem.free)

输出内容如下:

bash 复制代码
mem_total:  3810177024
mem_free:  1764446208

2.2.3 获取磁盘信息

在系统的所有磁盘信息中,我们更加关注磁盘的利用率及 I/O 信息

磁盘利用率使用 psutil.disk_usage 方法获取

磁盘 I/O 信息使用使用 psutil.diskiocounters() 获取,主要包括:

  • read_count: 读 I/O 数
  • write_count: 写 I/O 数
  • read_bytes: I/O 读字节数
  • write_bytes: I/O 写字节数
  • read time: 磁盘读时间
  • write_time: 磁盘写时间

示例:

py 复制代码
import psutil
print('磁盘完整信息:',psutil.disk_partitions())
print('/分区参数使用情况:',psutil.disk_usage('/'))
print('硬盘总的IO个数、读写信息:',psutil.disk_io_counters())
print('每块硬盘IO个数、读写信息:',psutil.disk_io_counters(perdisk=True))

2.2.4 获取网络信息

系统的网络信息与磁盘 I/O 类似,使用 psutil.net_io_counters() 方法获取,涉及几个关键点,包括:

  • bytes_sent(发送字节数)
  • bytes_recv(接收字节数)
  • packets_sent(发送数据包数)
  • packets_recv(接收数据包数)

示例:

py 复制代码
import psutil
print('网络总 I/O 信息:',psutil.net_io_counters())
print('每个网络接口的 I/O 信息:',psutil.net_io_counters(pernic=True))

2.2.5 获取其他系统信息

psutil 模块还支持获取用户登录、开机时间等信息

示例:

py 复制代码
import psutil,datetime
print('当前登录系统用户信息:',psutil.users())
# 时间戳是以 1970 年 1 月 1 日开始经过的秒数,可以用整数 or 字符串格式表示
print('开机时间,以时间戳格式返回:',psutil.boot_time())
print('开机时间格式:',datetime.datetime.fromtimestamp(psutil.boot_time()).strftime('%Y-%m-%d %H:%M:%S'))

2.3 进程管理

获得当前系统的进程信息,可以让运维人员得知应用程序的运行状态,包括进程的启动时间、查看或设置 CPU 亲和度、内存使用率、I/O 信息、socket 连接、线程数等,这些信息可以呈现出指定进程是否存活、资源利用情况,为开发人员的代码优化、问题定位提供很好的数据参考

示例:

py 复制代码
import psutil
# 列出所有进程 PID
print(psutil.pids())
# 实例化一个 process 对象,参数为进程 PID
p = psutil.Process(2000)
# 进程名称
print('进程名称:',p.name())
# 进程 bin 路径
print('进程bin路径:',p.exe())
# 进程工作目录绝对路径
print('进程工作目录绝对路径:',p.cwd()) # Linux 使用
# 进程状态
print('进程状态:',p.status())
# 进程创建时间,时间戳
print('进程创建时间戳:',p.create_time())
# 进程 UID 信息
print('进程UID信息:',p.uids()) # Linux 使用
# 进程 GID 信息
print('进程GID信息:',p.gids()) # Linux 使用
# 进程 CPU 时间信息,包括 user,system 两个 CPU 时间
print('进程CPU时间:',p.cpu_times())
# get 进程 CPU 亲和度,如果要设置进程 CPU 亲和度,将 CPU 号作为参数即可
print('CPU亲和度:',p.cpu_affinity()) # Linux使用
# 进程内存利用率
print('进程内存利用率:',p.memory_percent())
# 进程内存 rss,vms 信息
print('进程 rss,vms 信息:',p.memory_info())
# 进程 I/O 信息,包括读写 I/O 数及字节数
print('进程 I/O 信息:',p.io_counters())
# 进程开启的线程数
print('进程开启的线程数:',p.num_threads())

2.4 popen 类的使用

Popen 类是 subprocess 模块中的一个类,用于在 python 中创建和管理子进程

案例:使用 Popen 类列出当前目录下的文件并打印输出和错误信息

py 复制代码
import subprocess
# 创建 Popen 对象,使用 subprocess.Popen 创建一个子进程对象。可以指定命令、参数、输入输出重定向等
process = subprocess.Popen(['ls', '-l'], stdout=subprocess.PIPE, 
stderr=subprocess.PIPE)
# 与进程交互,可以通过 communicate() 方法与进程交互,获取输出和错误信息。
output, error = process.communicate()
if output:
    print("Output:\n", output.decode('utf-8'))
if error:
    print("Error:\n", error.decode('utf-8'))

3. IP 地址处理模块 IPy

IP地址规划是网络设计中非常重要的一个环节,规划的好坏会直接影响路由协议算法的效率,包括网络性能、可扩展性等方面,在这个过程当中,免不了要计算大量的地址,包括网段、网络掩码、广播地址、子网数、IP 类型等

Python 提供了一个强大的第三方模块 IPy 模块可以很好地辅助我们高效完成 IP 的规划工作

使用该模块前,需要运行 pip install ipy 进行安装

3.1 IP 地址基本处理

IPy 模块包含 IP 类,使用它可以方便处理绝大部分格式为 IPv6 及 IPv4 的网络和地址

3.1.1 IP 协议区分

通过 version 方法就可以区分出 IPv4 与 IPv6 协议

示例:

py 复制代码
from IPy import IP

ip4 = IP('172.16.31.10').version()
ip6 = IP('::1').version()

print(ip4)
print(ip6)

输出结果如下:

bash 复制代码
4
6

3.1.2 获取网段 IP 清单

使用 len() 函数可以获取网段中有多少个 IP 地址,通过循环可以输出网段中的所有 IP 地址

示例:

py 复制代码
from IPy import IP

ip = IP('172.16.31.0/30')
print("IP Numbers: ",ip.len())

print("IP list: ")
for x in ip:
    print(x)

输出结果如下:

bash 复制代码
IP Numbers:  4
IP list
172.16.31.0
172.16.31.1
172.16.31.2
172.16.31.3

4. 系统批量运维管理器 paramiko

paramiko 是基于 Python 实现的 SSH2 远程安全连接,支持认证及密钥方式。可以实现远程命令执行、文件传输、中间 SSH 代理等功能,相对于 Pexpect,封装的层次更高,更贴近 SSH 协议的功能

使用 pip install paramiko 安装 paramiko

4.1 paramiko 核心组件

paramiko 模块包含两个核心组件,一个为 SSHClient 类,另一个为 SFTPClient

4.2 SSHClient 类

SSHClient 类是 SSH 服务会话的高级表示,该类封装了传输(transport)、通道(channel) 及 SFTPClient 的校验、建立的方法,通常用于执行远程命令

4.2.1 connection()

connect 方法实现了远程 SSH 连接并校验,常用参数如下:

参数名 参数值类型 用途
hostname String 连接的目标主机地址
port int 连接目标主机的端口,默认为 22
username String 校验的用户名(默认为当前的本地用户名)
password String 密码用于身份校验或解锁私钥
pkey pkey 私钥方式用于身份验证
key_filename String 或 list(String) 用于私钥的身份验证
timeout float 一个可选的超时时间(以秒为单位)的 TCP 连接
allow_agent bool 设置为 False 时用于禁用连接到 SSH 代理
look_for_keys bool 设置为 False 时用来禁用在~/.ssh 中搜索私钥文件
compress bool 设置为 True 时打开压缩

4.2.2 exec_command()

远程命令执行方法,该命令的输入与输出流为标准输人(stdin)、输出(stdout)、错误(stderr)的 Python 文件对象,语法如下:

py 复制代码
exec_command(self, COMMAND, bufsize=SIZE)
# COMMAND: 命令内容,String 类型
# SIZE: 文件缓冲区大小,默认为 -1,即不限制

4.2.3 set_missing_host_key_policy()

设置连接的远程主机没有本地主机密钥或 HostKeys 对象时的策略,仅限用于 SSHClient 类,目前支持三种,分别是

  • AutoAddPolicy:自动添加主机名及主机密钥到本地 HostKeys 对象,并将其保存
  • RejectPolicy(默认):自动拒绝未知的主机名和密钥
  • WarningPolicy:用于记录一个未知的主机密钥的 Python 警告,并接受它,功能上与 AutoAddPolicy 相似,但未知主机会有告警

示例:

py 复制代码
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

案例

巡检 2 台服务器,获取内存信息,把 free 状态的容量进行排序统计,并生成到 sort.txt 文件中

!NOTE

要做什么:

  1. 连接服务器
  2. 执行命令
  3. 将获取的信息进行排序
  4. 存放到文件

!TIP

  • 获取内存 free 状态容量的命令:free -m | grep Mem | awk '{print $4}'
py 复制代码
import paramiko as pk

# 1. 编写远程连接函数
def get_info(host, port, user, pwd):
    ssh_client = pk.SSHClient()
    ssh_client.set_missing_host_key_policy(pk.AutoAddPolicy())
    # 执行连接目标服务器
    ssh_client.connect(hostname=host,   # 主机名 / 主机 IP
                    port=port,          # 端口号
                    username=user,      # 账户名
                    password=pwd,       # 密码
                    allow_agent=False)
    # 执行远程命令
    stdin, stdout, stderr = ssh_client.exec_command("free -m | grep Mem | awk '{print $4}'")

# 2. 巡检
hosts = ['192.168.100.138','192.168.100.140'] # 主机 IP
infos = []

for ip in hosts:
    mem,err = get_info(ip, 22, 'root', '123123') # 账户,密码
    for line in mem:
        infos.append(int(line))

# 3. 排序
infos.sort(reverse=True)

# 4. 存入文件
new_list = []
for i in infos:
    new_list.append(str(i)+'\n')

with open('a.txt', 'w', encoding='utf-8') as f:
    f.writelines(new_list)
print("Done!")

4.3 SFTPClient 类

SFTPClient 作为一个 SFTP 客户端对象,根据 SSH 传输协议的 sftp 会话,实现远程文件操作,比如文件上传、下载、权限、状态等操作

4.3.1 from_transport()

from_transport() 用来基于一个已经建立的 Transport(传输通道)创建 SFTP 客户端实例

语法如下:

py 复制代码
from_transport(TRANSPORT)

示例:

py 复制代码
import paramiko

# 建立 Transport 通道
transport = paramiko.Transport(("10.1.8.10", 22)) # 连接到 10.1.8.10:22
transport.connect(username="root", password="123")

# 基于 transport 创建 SFTP 客户端
sftp = paramiko.SFTPClient.from_transport(transport)

print("SFTP 连接成功!")
sftp.close()
transport.close()

正常连接后输出结果如下:

bash 复制代码
SFTP 连接成功!

4.3.2 put()

put() 方法用于将本地文件上传至远程服务器,语法如下:

py 复制代码
put(本地路径, 远程服务器路径)

4.3.3 get()

get() 方法用于将远程服务器的文件下载到本地,语法如下:

py 复制代码
get(远程服务器路径, 本地路径)

4.3.4 其他方法

方法名及语法 用途
mkdir(路径, 权限) 创建目录
remove(路径) 删除目录
rename(原文件名, 新文件名) 重命名文件

5. 实战

5.1 堡垒机模式下的远程命令执行

堡垒机环境在一定程度上提升了运营安全级别,但同时也提高了日常运营成本,作为管理的中转设备,任何针对业务服务器的管理请求都会经过此节点,比如SSH协议,首先运维人员在办公电脑通过SSH协议登录堡垒机,再通过堡垒机SSH跳转到所有的业务服务器进行维护操作

py 复制代码
import paramiko as pk
import os, sys, time

# 堡垒机信息
bastion_ip = "10.1.8.11"
bastion_username = "root"
bastion_password = "123"

# 业务服务器信息
server_ip = "10.1.8.10"
server_username = "root"
server_password = "123"

port = 22

# 1. 登录堡垒机
passinfo = "\'s password: " # 设定关键字
pk.util.log_to_file("syslogin.log")

# 2. SSH 登录堡垒机
ssh = pk.SSHClient()
ssh.set_missing_host_key_policy(pk.AutoAddPolicy())
ssh.connect(hostname=bastion_ip, username=bastion_username, password=bastion_password, port=port)

# 3. 调用命令
channel = ssh.invoke_shell()
channel.settimeout(300)

buff = " "
resp = " "

channel.send('ssh ' + server_username + '@' + server_ip + '\n')
while not buff.endswith(passinfo):
    try:
        resp = channel.recv(1024).decode('utf-8')
    except Exception as err:
        print('Error info: ' + str(err) + 'connection time.')
        channel.close()
        ssh.close()
        sys.exit()

    buff = buff + resp
    if not buff.find('yes/no') == -1:
        channel.send('yes\n')
        buff = ''

channel.send(server_password + '\n')
buff = ''
while not buff.endswith('# '):
    resp = channel.recv(1024).decode('utf-8')
    if not resp.find(passinfo) == -1:
        print('Error info: Authentication failed.')
        channel.close()
        ssh.close()
        sys.exit()
    buff = buff + resp

channel.send('ifconfig\n')
buff = ''
try:
    while buff.find('# ') == -1:
        resp = channel.recv(1024).decode('utf-8')
        buff = buff + resp
except Exception as err:
    print('Error info: ' + str(err))

print(buff)
channel.close()
ssh.close()

5.2 实现堡垒机模式下的远程文件上传

实现堡垒机模式下的文件上传,原理是通过 paramiko 的 SFTPCIient 将文件从办公设备上传至堡垒机指定的临时目录,如 /tmp,再通过 SSHClient 的 invoke_shell 方法开启 ssh 会话,执行 scp 命令,将 /tmp 下的指定文件复制到目标业务服务器上

py 复制代码
import paramiko as pk
import os, sys, time

# 堡垒机信息
bastion_ip = "10.1.8.11"
bastion_username = "root"
bastion_password = "123"

# 业务服务器信息
server_ip = "10.1.8.10"
server_username = "root"
server_password = "123"

# ===== 路径信息 =====
tmpdir = "/tmp" # 临时目录
target_dir = "/data" # 目标目录
localpath = "E:\\pytest\\1.txt"     # 本地文件路径
tmppath = tmpdir + "/1.txt"         # 堡垒机临时文件路径
targetpath = target_dir + "/1.txt"  # 服务器文件路径

port = 22

# 1. 登录堡垒机
passinfo = "\'s password: " # 设定关键字
pk.util.log_to_file("syslogin.log")

t = pk.Transport(bastion_ip, port)
t.connect(username=bastion_username, password=bastion_password)

print("===== [ Bastion login ]: OK =====")

# 2. 将本地文件传送到堡垒主机
sftp = pk.SFTPClient.from_transport(t)
sftp.put(localpath, tmppath)
sftp.close()

print("===== [ Send file to Bastion ]: OK =====")

# 3. SSH 远程登录堡垒主机
ssh = pk.SSHClient()
ssh.set_missing_host_key_policy(pk.AutoAddPolicy())
ssh.connect(hostname=bastion_ip, port=port, username=bastion_username, password=bastion_password)
channel = ssh.invoke_shell() # 开启命令调用
channel.settimeout(300)

print("===== [ SSH to Bastion ]: OK =====")

# 4. 使用 scp 中转文件到服务器
buff = ''
resp = ''

print("===== [ Sending file to Server ] =====")
print("Command: " + "scp " + tmppath + " " + server_username + "@" + server_ip + ":" + targetpath)

channel.send("scp " + tmppath + " " + server_username + "@" + server_ip + ":" + targetpath + "\n")
while not buff.endswith(passinfo):
    try:
        resp = channel.recv(1024).decode('utf-8')
    except Exception as e:
        print("Error info: " + str(e) + "connection time.")
        channel.close()
        ssh.close()
        sys.exit()

    buff = buff + resp
    if not buff.find("yes/no") == -1:
        channel.send("yes\n")
        buff = ''

channel.send(server_password + "\n")
buff = ''
while not buff.endswith('# '):
    resp = channel.recv(1024).decode('utf-8')
    if not resp.find(passinfo) == -1:
        print("Error info: Authentication failed!")
        channel.close()
        ssh.close()
        sys.exit()
    buff = buff + resp

print(buff)
channel.close()
ssh.close()
相关推荐
Acrelhuang34 分钟前
直击新能源电能质量痛点:安科瑞 APView500 在线监测装置应用方案
大数据·运维·开发语言·人工智能·物联网
一条咸鱼¥¥¥37 分钟前
【运维经验】服务器设置磁盘阵列
运维·服务器
CNRio38 分钟前
第二章-镜像深度解析:Docker的‘千层蛋糕‘魔法
运维·docker·容器
hweiyu0043 分钟前
Linux 命令:fdisk
linux·运维·服务器
牙牙要健康44 分钟前
【open3d】示例:自动计算点人脸点云模型面部朝向算法
人工智能·python·算法
lalala_lulu44 分钟前
Lambda表达式是什么
开发语言·python
r***86981 小时前
Python中的简单爬虫
爬虫·python·信息可视化
atregret1 小时前
OSError: [WinError 1114] 动态链接库(DLL)初始化例程失败。Error loading ... c10.dll
人工智能·python
宠..1 小时前
创建文本框控件
linux·运维·服务器·开发语言·qt