系统批量运维管理器 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()
相关推荐
习惯就好zz1 天前
在 Ubuntu 18.04 旧系统上部署新版 GitHub Actions Runner 的终极方案
linux·ubuntu·github·cicd·action
杨云龙UP1 天前
Linux LVM 在线扩容标准操作流程_20260102
linux·运维·服务器·centos·ux
微凉的衣柜1 天前
Windows Server 使用 Nginx 反向代理实现域名访问内网 Gradio 应用
运维·windows·nginx
warton881 天前
ubuntu24.04 安装mysql8.0.36
linux·运维·mysql
CS创新实验室1 天前
《计算机网络》深入学:虚电路
服务器·计算机网络·php·虚电路
运维有小邓@1 天前
如何实现基于角色的访问控制?
运维·网络
范纹杉想快点毕业1 天前
嵌入式通信核心架构:从状态机、环形队列到多协议融合
linux·运维·c语言·算法·设计模式
小龙1 天前
【Git 报错解决】SSH 公钥认证失败(`Permission denied (publickey)`)
运维·git·ssh
白驹过隙^^1 天前
VitrualBox及ubuntu系统安装
linux·运维·ubuntu