Python+requests之通过跳板机(ssh通道)操作MySQL

公司内部通常会限制MySQL的登录访问的IP地址,如此情况下我们就需要通过ssh登录指定的服务器(跳板机)才能访问远程MySQL,程序本身不能直接连接MySQL,在写一些自动化脚本时会很麻烦, Python可通过paramikosshtunnel模块建立ssh通道在访问MySQL

思路

1.  通过密钥或密码登录(ssh)指定跳板机

2.  绑定本地地址与跳板机相通的端口

3. 登录MySQL数据库

4. 执行SQL

5. 登出数据库和服务器

实现

(一)服务器登录方法

#!/usr/bin/python3
# coding=utf-8
# Author: 文


import paramiko
from sshtunnel import SSHTunnelForwarder


class Jump_Server():
    def login_server(self, address, address_port, username, remote_address, remote_address_port, **kw):
        """
        :param address:       跳扳机的IP地址
        :param address_port:  跳扳机的端口号
        :param username:      跳板机的SSH登录账号
        :param remote_address:      远程服务器的IP地址
        :param remote_address_port: 远程服务器的端口号
        :param kw: 参数ssh_pkey(客户端私钥路径)参数key_password(客户端开机密码) 参数ssh_password(客户端密码)
        :return:  返回服务器操作指针
        """
        try:
            # 通过密钥调用connect函数建立Linux连接
            if "ssh_pkey" in kw.keys():
                server = SSHTunnelForwarder(
                    # 跳板机ip与ssh登录端口号
                    ssh_address_or_host=(address, address_port),
                    # 跳板机登录账号
                    ssh_username=username,
                    # PC(客户端)的私钥路径
                    ssh_pkey=paramiko.RSAKey.from_private_key_file(kw["ssh_pkey"]),
                    # PC(客户端)的密码
                    ssh_private_key_password=kw["key_password"],
                    # 远程MYSQL服务器的绑定的IP和端口号
                    remote_bind_address=(remote_address, remote_address_port)
                )
            # 通过密码调用connect函数建立Linux连接
            elif "password" in kw.keys():
                server = SSHTunnelForwarder(
                    ssh_address_or_host=(address, address_port),
                    ssh_username=username,
                    ssh_password=kw["password"],
                    remote_bind_address=(remote_address, remote_address_port),
                    # 绑定本地地址(默认127.0.0.1和端口号)及与跳板机相通的端口
                    local_bind_address=('127.0.0.1', 22),
                )
            else:
                print("登录信息与方法错误,抛出异常 - ValueError")
                raise ValueError
            server.start()
            print("账号【%s】登录【%s】服务器启动服务器【%s】的MySQL服务" % (username, address, remote_address))
            return server
        except Exception as e:
            print("发生未知错误: %s" % e)
            raise

    def logout_server(self, server_pointer):
        """
        :param server_pointer: 服务器操作指针
        :return:
        """
        try:
            server_pointer.close()
            print("登出服务器成功")
        except Exception as e:
            print("发生未知错误: %s" % e)
            raise

(二)数据库登录方法

#!/usr/bin/python3
# coding=utf-8
# Author: 文


import pymysql
from operate_server import Jump_Server


def connect_db(sql, host=None, db=None):
    """
    :param sql: mysql语句
    :param host: 服务器登录信息
    :param db: 数据库登录信息
    :return:
    """
    if "ssh_pkey" in host.keys():
        server = Jump_Server().login_server(
            address=host["address"],
            address_port=host["address_port"],
            username=host["username"],
            remote_address=host["remote_address"],
            remote_address_port=host["remote_address_port"],
            ssh_pkey=host["ssh_pkey"],
            key_password=["key_password"]
        )
    # 密码登录服务器
    elif "password" in host.keys():
        server = Jump_Server().login_server(
            address=host["address"],
            address_port=host["address_port"],
            username=host["username"],
            password=host["password"],
            remote_address=host["remote_address"],
            remote_address_port=host["remote_address_port"],
            local_bind_address=('127.0.0.1', 22),
        )
    else:
        print("登录方法错误,传参密钥登录或密码登录, 抛出异常 - ValueError")
        raise ValueError

    # 登录数据库
    db = pymysql.connect(
        host=db["address"],            # mysql地址
        port=server.local_bind_port,    # 跳板机绑定的端口号
        user=db["user"],               # mysql账号
        passwd=db["password"],         # mysql密码
        db=db["db"],                   # 数据库名
        charset='utf8'
    )
    version = db.server_version
    print("账号【{0}】登录【{1}】端口【{2}】数据库【{3}】成功, 数据库version: {4}".format(
        dbs["user"], dbs["address"], host["remote_address_port"], dbs["db"], version))
    # 使用cursor()方法获取mysql操作游标
    cursor = db.cursor()
    print("开始执行sql语句: {0}".format(sql))
    try:
        if sql[0:6].lower() == "select":
            cursor.execute(sql)             # 执行select语句
            results = cursor.fetchall()     # 获取查询结果
            print("获得select查询结果:{0}".format(results))
        elif sql[0:6].lower() == "update":
            try:
                cursor.execute(sql)         # 执行update语句
                db.commit()                 # 提交到数据库执行
                print("update语句执行通过, {0}条记录被修改".format(cursor.rowcount))
            except Exception:
                db.rollback()               # 数据操作失败, 回滚
                print("数据更新失败, 数据回滚成功")
                raise
        elif sql[0:6].lower() == "delete":
            cursor.execute(sql)             # 执行delete语句
            db.commit()                     # 提交到数据库执行
            print("delete语句执行通过, {0}条记录被删除".format(cursor.rowcount))
        elif sql[0:6].lower() == "insert":
            cursor.execute(sql)             # 执行insert语句
            db.commit()                     # 提交到数据库执行
            print("insert语句执行通过, 成功插入{0}条记录".format(cursor.rowcount))
        else:
            print("sql语句类型识别失败, 请校验sql语句, 抛出异常-ValueError")
            raise ValueError
    except Exception as e:
        print("发生预料之外的错误: %s" % e)
        raise
    finally:
        cursor.close()
        print("关闭mysql光标对象")
        db.close()
        print("登出mysql数据库")
        Jump_Server().logout_server(server_pointer=server)

(三)执行方式

#!/usr/bin/python3
# coding=utf-8
# Author: 文


if __name__ == "__main__":
    hosts1 = {"address": "跳板机IP", "address_port": "跳板机登录端口", "username": "跳板机登录账号",
              "remote_address": "mysql服务器IP", "remote_address_port": "数据库端口号",
              "ssh_pkey": "私钥路径", "key_password": "私钥密码"}

    hosts2 = {"address": "跳板机IP", "address_port": "跳板机登录端口", "username": "跳板机登录账号",
              "remote_address": "mysql服务器IP", "remote_address_port": "数据库端口号", 
              "password": "数据库密码"}

    dbs = {"address": "数据库IP", "user": "数据库账号", "password": "数据库密码", "db": "数据库名"}
    sql = "select * from blog where id > 116 and id < 115;"
    # 通过密钥登录跳板机
    connect_db(sql=sql, host=hosts1, db=dbs)
    # 通过密码登录跳板机
    connect_db(sql=sql, host=hosts2, db=dbs)

 

你可能感兴趣的:(Requests接口自动化)