python的paramiko模块向Windows和Linux服务器发送远程命令

一、 python使用paramiko进行系统间通信遇到的坑
二、python的paramiko模块同时向Windows和Linux服务器发送远程命令(传输文件)

上一篇使用ssh进行通信踩坑结束后,本篇来写个demo验证一下。

1. paramiko介绍

1、首先先介绍下paramiko模块,paramiko是基于python编写的使用ssh协议的模块,跟xshell和xftp功能类似,支持加密与认证,可以上传下载和访问服务器的文件。
2、paramiko 主要包含SSHClient和SFTPClient两个组件,有使用密码和使用密钥免密码这两种登陆方式。
3、以下实例我们采用使用密码方式,判断连接服务器的系统类型,并上传文件。

2. SSHClient连接服务器

ssh服务会话的表示,通常用来执行命令,主要有connect、exec_command、load_system_host_keys和set_missing_host_key_policy方法。
connect:建立SSH远程连接并校验;
exec_command:执行指令并返回结果;
代码如下:
hostname(主机ip),port(端口22), username(主机用户名), password(用户密码)
可自行传参

def ssh_client_con(hostname, port, username, password):
    try:
        # 基于SSHClient是传统的连接服务器/执行命令/关闭的一个操作
        ssh_client = paramiko.SSHClient()
        # 远程主机没有本地主机密钥时的方式。
        ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy)
        # 连接服务器
        ssh_client.connect(hostname=hostname, port=port, username=username, password=password)
        return ssh_client
    except Exception as error:
        return error

3. 使用exec_command判断系统类型

1、Windows上使用ver命令判断,如图:
在这里插入图片描述

2、Linux上使用lsb_release命令判断
Ubuntu系统如图所示:
python的paramiko模块向Windows和Linux服务器发送远程命令_第1张图片
CentOS系统如图所示:
python的paramiko模块向Windows和Linux服务器发送远程命令_第2张图片

如果没有这个命令的话,需要安装一下,参考centos下安装lsb_release命令
3、使用exec_command向服务端发送命令并返回结果
代码如下:
hostname(主机ip),port(端口22), username(主机用户名), password(用户密码)

def _system_type(hostname, port, username, password):
    # Linux判断命令
    shell_command = "lsb_release -a"
    # Windows判断命令
    win_cmd = "ver"
    ssh_client = ssh_client_con(hostname, port, username, password)
    # 先执行Linux的lsb_release命令
    std_in, std_out, stderr = ssh_client.exec_command(shell_command)
    # 打印输出信息,判断输出信息列表是否为空
    value = std_out.readlines()
    # 如果不为空则执行
    if value:
        for mess in value:
            dis_id = mess.strip().split('\t')
            if dis_id[0] == "Distributor ID:":
                if dis_id[-1] == "Ubuntu":
                    return dis_id[-1]
                elif dis_id[-1] == "CentOS":
                    return dis_id[-1]
                else:
                    return False
    else:
    	# 如果为空,执行windows的ver命令
        std_in, std_out, stderr = ssh_client.exec_command(win_cmd)
        # 输出信息时bytes类型,且中文显示乱码,所以需要转换一下
        # '\r'表示将光标的位置回退到本行的开头位置,'\n'是换行,利用replace()方法将'\r'替换为空字符串'',在使用strip删除换行符
        a = std_out.read().decode('gbk').replace('\r', '').strip('\n')
        # 得到:Microsoft Windows [版本 10.0.14393],使用split进行截取并获取Windows字符串
        return a.split(' ')[1]

4. SFTPClient传输文件

SFTPClient是SFTP客户端对象,实现远程文件操作,主要有from_transport、put、get、stat、remove、rename、listdir等方法。
Transport:从已通过验证的传输对象建立连接。
put:上传本地文件到服务器上。
get:从服务器下载文件到本地。
stat、remove、rename、listdir:获取文件信息、删除文件、重命名文件或获取指定目录中的列表。
代码如下:
hostname(主机ip),port(端口22), username(主机用户名), password(用户密码), local_path(本地文件路径), server_path(服务端路径)
可自行传参

def sftp_client_con(hostname, port, username, password, local_path, server_path, timeout=10):
    # 需要登录上服务器执行多个操作,如上传/下载文件
    try:
        t = paramiko.Transport(hostname, port)
        t.banner_timeout = timeout
        t.connect(username=username, password=password)
        # 创建sftp实例
        sftp = paramiko.SFTPClient.from_transport(t)
        sftp.put(local_path, server_path)
        t.close()
        return True
    except Exception as error:
        return error

5. 根据系统类型传输文件

代码如下:
hostname(主机ip),port(端口22), username(主机用户名), password(用户密码), file_name(安装包存在目录包括exe, deb,rpm等文件,可使用os.listdir读取并存放到列表里)
可自行传参

def ssh_tran_file(hostname, port, username, password, file_name):
	# 判断系统类型
	system_type = _system_type(hostname, port, username, password)
    if system_type == "Windows":
        for fi in file_name:
            if fi.endswith('.exe'):
                name = os.path.basename(fi)
                server_path = "C:/Users/" + username + "/Desktop/" + name
                sftp_client_con(hostname, port, username, password, fi, server_path)
    elif system_type == "Ubuntu":
        for fi in file_name:
            if fi.endswith('.deb'):
                name = os.path.basename(fi)
                server_path = "/home/" + username + "/Desktop/" + name
                sftp_client_con(hostname, port, username, password, fi, server_path)
    elif system_type == "CentOS":
        server_path_list = []
        for fi in file_name:
            if fi.endswith('.rpm'):
                name = os.path.basename(fi)
                server_path = "/home/" + username + "/Desktop/" + name
                sftp_client_con(hostname, port, username, password, fi, server_path)
    else:
        print("不明确的系统类型")

6. 使用exec_command操作Linux sudo命令

场景描述:比如在Ubuntu上安装deb文件,需要使用sudo权限。
解决方法:使用sudo命令则需要输入密码,采用std_in.write()方式
代码如下:

#使用管道sudo -S
shell_command = "sudo -S dpkg -i " + p
ssh_client = ssh_client_con(hostname, port, username, password)
    # 先执行Linux的lsb_release命令
std_in, std_out, stderr = ssh_client.exec_command(shell_command)
# 执行输入命令,输入sudo命令的密码,会自动执行
std_in.write(password + '\n')

你可能感兴趣的:(linux,windows,ssh,python)