系统批量运维管理器 paramiko

系统批量运维管理器 paramiko

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

1:paramiko 的安装

Linux系统部署Python3环境

bash 复制代码
#安装依赖包
yum install -y openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel libffi-devel gcc gcc-c++

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

pip国内镜像源配置

bash 复制代码
cat > /root/.config/pip/pip.conf << 'EOF'
[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
EOF

安装paramiko模块

bash 复制代码
pip install paramiko

二、paramiko 核心组件

paramiko 包含两个核心组件,分别对应不同的运维场景:

组件 作用 核心功能
SSHClient 类 封装 SSH 会话,用于远程命令执行 建立 SSH 连接、执行远程命令、设置主机密钥策略
SFTPClient 类 基于 SSH 传输协议的 SFTP 客户端 远程文件上传、下载、目录操作(创建 / 删除 / 重命名)、文件属性查询

三、paramiko 运维代码示例

(一)基础场景:单台远程执行命令(在客户端创建文件abc.txt)

bash 复制代码
import paramiko
def pwd(filename):
    with open(filename,'r') as f:
        a = f.read()
        return a
#四要素
host = '192.168.108.128'
port = 22
username = 'root'
password = pwd('password.txt')
#日志文件
paramiko.util.log_to_file('syslogin.log')
#创建一个ssh客户端对象
ssh_client = paramiko.SSHClient()
#设置主动接受未知主机密钥策略
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
#连接服务器
ssh_client.connect(hostname=host,port=port,username=username,password=password,allow_agent=False)
#执行指令,获取信息
stdin,stdout,stderr = ssh_client.exec_command('touch /abc.txt')
for line in stdout:
    print(line)
#关闭输入
stdin.close()
#关闭客户端
ssh_client.close()

(二)批量运维场景:多服务器内存信息采集与排序

bash 复制代码
#需求:巡检2台服务器,获取内存信息,把free状态的容量进行排序统计,并生成到sort.txt文件中
import paramiko
def pwd(filename):
    with open(filename) as f:
        a = f.read().strip()
        return a

hosts = ['192.168.108.128','192.168.108.162']
port = 22
username = 'root'
password = pwd('password.txt')
paramiko.util.log_to_file('log.txt')
mem_info = []
for host in hosts:
    try:
        ssh_client = paramiko.SSHClient()
        ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh_client.connect(hostname=host, port=port, username=username, password=password)
        cmd = "free -m | grep Mem | awk '{print $4}'"
        stdin, stdout, stderr = ssh_client.exec_command(cmd)
        get_info = stdout.readlines()
        if get_info:
            free_mem = int(get_info[0].strip())
            mem_info.append((host,free_mem))
            print(f'主机:{host}的空闲内存是{free_mem}')
    except Exception as e:
        print(f'主机{host}连接失败')
    ssh_client.close()
mem_info.sort(key=lambda x: x[1])
with open("sort.txt","w") as s:
    s.write('服务器IP   空闲内存\n')
    for host,free_mem in mem_info:
        s.write(f'{host}   {free_mem}\n')
print('\n排序后的结果:',mem_info)
print('结果保存在sort.txt文件中')

(三)堡垒机模式下的远程命令执行

bash 复制代码
import paramiko
import os, sys, time

blip = '192.168.108.128'
bluser = 'root'
blpasswd = '123'

hostname = '192.168.108.162'
username = 'root'
password = '123'
port = 22

passinfo = 'password: '
paramiko.util.log_to_file('python.log')

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=blip, username=bluser, password=blpasswd)

channel = ssh.invoke_shell()
channel.settimeout(30)

buff = ''
resp = ''
channel.send(' ssh ' + username + '@' + hostname + '\n')
#优化循环条件,增加时间判断防止无限循环
start_time = time.time()
while not buff.endswith(passinfo):
    try:
        # 非阻塞接收,每次只收1024字节,避免单次接收过大导致阻塞
        resp = channel.recv(1024).decode('utf-8', errors='ignore')
    except Exception as e:
        # 超时异常不直接退出,短暂等待后重试
        if 'timeout' in str(e):
            # 超过30秒再退出
            if time.time() - start_time > 30:
                print('Error info:' + str(e) + ' connection time out.')
                channel.close()
                ssh.close()
                sys.exit()
            time.sleep(0.5)
            continue
        else:
            print('Error info:' + str(e) + ' connection error.')
            channel.close()
            ssh.close()
            sys.exit()

    buff += resp
    # 清空resp,避免重复累加
    resp = ''

    if not buff.find('yes/no') == -1:
        channel.send('yes\n')
        buff = ''
        # 发送yes后等待一下,让服务器响应
        time.sleep(1)

# 发送密码后增加短暂等待
channel.send(password + '\n')
time.sleep(1)
buff = ''
# 优化提示符匹配,不只匹配#,增加$等常见提示符
start_time = time.time()
while not any(char in buff for char in ['#', '$', '%']):
    try:
        resp = channel.recv(1024).decode('utf-8', errors='ignore')
    except Exception as e:
        if 'timeout' in str(e):
            if time.time() - start_time > 30:
                print('Error info:' + str(e) + ' auth time out.')
                channel.close()
                ssh.close()
                sys.exit()
            time.sleep(0.5)
            continue
        else:
            print('Error info:' + str(e))
            channel.close()
            ssh.close()
            sys.exit()

    if not resp.find(passinfo) == -1:
        print('Error info: Authentication failed.')
        channel.close()
        ssh.close()
        sys.exit()
    buff += resp
    resp = ''

# 执行命令前清空缓冲区,执行后增加等待
channel.send('ip addr\n')
# 给命令执行留时间
time.sleep(2)
buff = ''
try:
    start_time = time.time()
    # 同时判断超时和提示符
    while buff.find('#') == -1 and time.time() - start_time < 30:
        try:
            resp = channel.recv(1024).decode('utf-8', errors='ignore')
            if resp:
                buff += resp
            else:
                time.sleep(0.5)
        except:
            time.sleep(0.5)
            continue
except Exception as e:
    print('error info:' + str(e))
print(buff)
channel.close()
ssh.close()
相关推荐
wewowilling35 分钟前
认识微服务
java·运维·微服务·springcloud
玖石书43 分钟前
Ubuntu 24.04 UFW 全命令攻略:从入门到端口开放实战
linux·运维·ubuntu
xiaoqiMikko1 小时前
Linux 实战(七):useradd、sudoers、umask、SGID、软链 —— 三台真机实测
linux·centos
weifont3 小时前
自动化抓取和上架商品:能不动手,就少动手
运维·前端·自动化
拂拉氏3 小时前
【知识讲解】 Linux之动静态库的了解
linux·运维·服务器·动静态库
Fcy6483 小时前
Linux下 五种IO模型的认识与⾮阻塞IO的实现
linux·服务器·io
Mikko74 小时前
Linux 重启后日志没了?进程被 OOM 杀了去哪看?logrotate 之后日志还往旧文件写?三台真机实测日志与性能排查
linux·运维·centos
书生执笔画浮沉4 小时前
分享一个开源小工具CAdapt
linux·c·gnu·glibc·kernel·升级·灵感
光依旧4 小时前
发版就掉请求?Spring Boot优雅停机的四步
运维·spring boot·nginx·高可用·优雅停机·mcp server
mounter6254 小时前
Linux 内核热升级(Live Update)技术详解:PCI、VFIO 与 IOMMU 子系统的演进与实战解析引言
linux·linux kernel·kernel·iommu·vfio