paramiko模块

1.模块作用

通过ssh远程连接服务器并执行想要命令 类似于Xshell

ansible批量管理机器,ansible底层用的就是paramiko模块

2.使用

1.安装

pip3 install paramiko

2.执行命令

1.用户名和密码的方式
#1.导入模块
import paramiko

#2.创建ssh对象
ssh = paramiko.SSHClient()
#3.允许链接不在know_hosts文件中主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

#4.链接服务器:地址,端口号,用户名,密码
ssh.connect(hostname='0.0.0.0',port=3306,username='root',password='123')

# 5.执行命令:
stdin, stdout, stderr = ssh.exec_command('ip a')

# 6.获取结果
res = stdout.read()  # 基于网络传输 该结果是一个bytes类型
print(res.decode('utf-8'))

# 7.断开链接
ssh.close()


2.公钥和私钥(先讲公钥保存到服务器上)
#1.导入模块
import paramiko #2. 读取本地私钥:a.txt为文件路径 private_key = paramiko.RSAKey.from_private_key_file('a.txt') # 3.创建SSH对象 ssh = paramiko.SSHClient() # 4.允许连接不在know_hosts文件中的主机 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 5.连接服务器 ssh.connect(hostname='0.0.0.0', port=22, username='root', pkey=private_key) # 6.执行命令 stdin, stdout, stderr = ssh.exec_command('ls /') # 7.获取命令结果 result = stdout.read() print(result.decode('utf-8')) # 8.关闭连接 ssh.close()

3.上传和下载文件

1.#用户名密码方式
import paramiko

#2.ip端口 用户名和密码
transport = paramiko.Transport(('172.16.219.168', 22))
transport.connect(username='root', password='jason123')

sftp = paramiko.SFTPClient.from_transport(transport)

# 3.上传文件:本地文件,上传后位置路径
sftp.put("a.txt", '/data/tmp.txt')  # 注意上传文件到远程某个文件下 文件必须存在

#4.下载文件:服务器文件,本地路径
sftp.get('/data/tmp.txt', 'hahahha.txt')  # 将远程文件下载到本地并重新命令
#5.关闭链接
transport.close() 2.# 公钥私钥方式 import paramiko #1.链接 private_key = paramiko.RSAKey.from_private_key_file('a.txt') transport = paramiko.Transport(('172.16.219.168', 22)) transport.connect(username='root', pkey=private_key) sftp = paramiko.SFTPClient.from_transport(transport) # 2.将location.py 上传至服务器 /tmp/test.py sftp.put('/tmp/location.py', '/tmp/test.py') # 3.将remove_path 下载到本地 local_path sftp.get('remove_path', 'local_path') transport.close()

4.封装总结

秘钥和用户名密码的区别在于链接时参数的不同而已:
1.密码
ssh.connect(hostname='0.0.0.0',port=3306,username='root',password='123')
2.秘钥
ssh.connect(hostname='0.0.0.0', port=22, username='root', pkey=private_key)
文件上传下载同理
transport.connect(username='root', password='123')
transport.connect(username='root', pkey=private_key)

疑问点:如果我想链接服务器执行多条命令并且还想上传下载文件,那么你所能看到的一般做法都是执行一次命令创建一次链接

我们要实现在一个链接上即可以执行命令又可以上传下载文件

我们封装成一个类,类的内部有一系列的方法,并且这些方法都可以在同一个链接下执行多次

# 1.基于用户名密码使用封装
import paramiko

class SSHProxy(object):
    def __init__(self, hostname, port, username, password):
        self.hostname = hostname
        self.port = port
        self.username = username
        self.password = password
        self.transport = None

    def open(self):  # 给对象赋值一个上传下载文件对象连接
        self.transport = paramiko.Transport((self.hostname, self.port))
        self.transport.connect(username=self.username, password=self.password)

    def command(self, cmd):  # 正常执行命令的连接  至此对象内容就既有执行命令的连接又有上传下载链接
        ssh = paramiko.SSHClient()
        ssh._transport = self.transport

        stdin, stdout, stderr = ssh.exec_command(cmd)
        result = stdout.read()
        return result

    def upload(self, local_path, remote_path):
        sftp = paramiko.SFTPClient.from_transport(self.transport)
        sftp.put(local_path, remote_path)
        sftp.close()

    def close(self):
        self.transport.close()

    def __enter__(self):
        print('with开始')
        self.open()
        return self  # 该方法返回什么 with ... as 后面就拿到什么

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('with结束')
        self.close()


if __name__ == '__main__':
#1. with上下文管理使用(推荐) obj = SSHProxy(hostname='172.16.219.168',port=22,username='root',password='jason123') with obj as ssh: # 默认不支持 对象执行with会自动触发内部的__enter__方法 print('with内部代码')
# with上下文执行完毕之后 会自动触发__exit__方法

#2.使用方式2:

#2.尝试基于用户名密码秘钥封装

mport paramiko

class SSHProxy(object):
    def __init__(self, hostname, port, username, password,pkey):
        self.hostname = hostname
        self.port = port
        self.username = username
        self.password = password
        self.pkey = pkey
        self.transport = None

    def open(self):  # 给对象赋值一个上传下载文件对象连接
        self.transport = paramiko.Transport((self.hostname, self.port))
        self.transport.connect(username=self.username, password=self.password,pkey=self.pkey)

    def command(self, cmd):  # 正常执行命令的连接  至此对象内容就既有执行命令的连接又有上传下载链接
        ssh = paramiko.SSHClient()
        ssh._transport = self.transport

        stdin, stdout, stderr = ssh.exec_command(cmd)
        result = stdout.read()
        return result

    def upload(self, local_path, remote_path):
        sftp = paramiko.SFTPClient.from_transport(self.transport)
        sftp.put(local_path, remote_path)
        sftp.close()
    def down(self,remote_path,local_path):
        sftp = paramiko.SFTPClient.from_transport(self.transport)
        sftp.get(remote_path,local_path)
        sftp.close()

    def close(self):
        self.transport.close()

    def __enter__(self):
        print('with开始')
        self.open()
        return self  # 该方法返回什么 with ... as 后面就拿到什么

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('with结束')
        self.close()

 

posted @ 2020-06-23 17:36  心慌得初夏  阅读(188)  评论(0编辑  收藏  举报
levels of contents