1930251516

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

paramiko

该模块基于SSH用于连接远程服务器:

安装:

pip3 install paramiko

SSHClient

基于用户名密码连接并执行命令:

import paramiko

# 创建SSH对象
ssh = paramiko.SSHClient() # 实例化

# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

# 连接服务器
ssh.connect(hostname='192.168.1.3', port=22, username='root', password='xxx')

# 执行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 获取命令结果
res, err = stdout.read(), stderr.read()
result = res if res else err
print(result.decode())
# 关闭连接 ssh.close()

 基于用户名密码上传下载:

import paramiko

transport = paramiko.Transport(("192.168.33.3", 22))
transport.connect(username='root', password='xxx') # 进行连接

sftp = paramiko.SFTPClient.from_transport(transport)
# 将E:\test\a.mp4'上传至服务器 /tmp/a.mp4
sftp.put(r'E:\test\a.mp4', '/tmp/a.mp4')
# 将remove_path 下载到本地 local_path
# sftp.get('remove_path', 'local_path')

transport.close()

基于公钥密钥连接:

就是利用公钥和私钥进行验证,这里我们假设有2台机器(A/B)首先在A机器需要生成一个密钥对(公钥/私钥),然后把公钥传到B机器上,那么A访问B的时候,就可以不使用密码验证了

基于公钥连接并执行命令:

import paramiko

# 私钥路径
private_key = paramiko.RSAKey.from_private_key_file('id_rsa')

# 创建SSH对象
ssh = paramiko.SSHClient()

# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

# 连接服务器
ssh.connect(hostname='192.168.33.3', port=22, username='test', pkey=private_key)

# 执行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 获取命令结果
result = stdout.read()
print(result.decode())
# 关闭连接
ssh.close()

 基于密钥上传下载:

import paramiko

private_key = paramiko.RSAKey.from_private_key_file('id_rsa')

transport = paramiko.Transport(('192.168.33.34', 22))
transport.connect(username='test', pkey=private_key)

sftp = paramiko.SFTPClient.from_transport(transport)
# 将location.py 上传至服务器 /tmp/test.py
sftp.put(r'E:\test\a.mp4', '/tmp/b.mp4')
# 将remove_path 下载到本地 local_path
# sftp.get('remove_path', 'local_path')

transport.close()

基于transport用户名和密码连接并执行命令

import paramiko

transport = paramiko.Transport(('192.168.33.35', 22))
transport.connect(username='root', password='xxx')

ssh = paramiko.SSHClient()
ssh._transport = transport

stdin, stdout, stderr = ssh.exec_command('df')
print(stdout.read().decode())

transport.close()

总结:

1、执行命令既可以用SSHClient,也可以用transport

2、当上传文件或下载文件的时候,只能用transport

基于类的模式封装了命令和上传及下载功能

import paramiko


class SSH:
    def __init__(self, host, port, user, pwd):
        self.host = host
        self.port = port
        self.user = user
        self.pwd = pwd
        self.transport = None

    def connect(self):
        self.transport = paramiko.Transport((self.host, self.port))
        self.transport.connect(username=self.user, password=self.pwd)  # 进行连接

    def cmd(self, cmd):
        ssh = paramiko.SSHClient()
        ssh._transport = self.transport
        stdin, stdout, stderr = ssh.exec_command(cmd)
        return stdout.read()

    def download(self, server_path, local_path):
        sftp = paramiko.SFTPClient.from_transport(self.transport)
        sftp.get(server_path, local_path)

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

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


obj = SSH('192.168.33.35', 22, 'root', 'xxx')
obj.connect()
a = obj.cmd('ls')
print(a.decode())
b = obj.cmd('df')
print(b.decode())
obj.close()

第三种连接方式:保持会话

前面我们介绍了用户名密码和使用transport方式,下面介绍来介绍第三种方式:保持会话,从方法主要适合开发堡垒机环境。

paramiko模块保持会话连接(一):

不适用于windows环境,需要在linux环境运行。

import paramiko
import sys
import socket
import select
from paramiko.py3compat import u

tran = paramiko.Transport(('192.168.33.35', 22,))
tran.start_client()
tran.auth_password('root', 'redhat')

# 打开一个通道
chan = tran.open_session()
# 获取一个终端
chan.get_pty()
# 激活器
chan.invoke_shell()

while True:
    # 监视用户输入和服务器返回数据
    # sys.stdin 处理用户输入
    # chan 是之前创建的通道,用于接收服务器返回信息
    readable, writeable, error = select.select([chan, sys.stdin, ], [], [], 1)
    if chan in readable:
        try:
            x = u(chan.recv(1024))  # u代表paramiko的兼容模式,在py3中需要
            if len(x) == 0:
                print('\r\n*** EOF\r\n')
                break
            sys.stdout.write(x)
            sys.stdout.flush()
        except socket.timeout:
            pass
    if sys.stdin in readable:
        inp = sys.stdin.readline()  # readline表示读一整行
        chan.sendall(inp)

chan.close()
tran.close()

paramiko模块保持会话连接(二):

import paramiko
import sys
import socket
import select
import termios
import tty
from paramiko.py3compat import u

tran = paramiko.Transport(('192.168.33.35', 22,))
tran.start_client()
tran.auth_password('root', 'redhat')

# 打开一个通道
chan = tran.open_session()
# 获取一个终端
chan.get_pty()
# 激活器
chan.invoke_shell()

# 获取原tty属性
oldtty = termios.tcgetattr(sys.stdin)
try:
    # 为tty设置新属性
    # 默认当前tty设备属性:
    #   输入一行回车,执行
    #   CTRL+C 进程退出,遇到特殊字符,特殊处理。

    # 这是为原始模式,不认识所有特殊符号
    # 放置特殊字符应用在当前终端,如此设置,将所有的用户输入均发送到远程服务器
    tty.setraw(sys.stdin.fileno())
    chan.settimeout(0.0)

    while True:
        # 监视 用户输入 和 远程服务器返回数据(socket)
        # 阻塞,直到句柄可读
        r, w, e = select.select([chan, sys.stdin], [], [], 1)
        if chan in r:
            try:
                x = u(chan.recv(1024))
                if len(x) == 0:
                    print('\r\n*** EOF\r\n')
                    break
                sys.stdout.write(x)
                sys.stdout.flush()
            except socket.timeout:
                pass
        if sys.stdin in r:
            x = sys.stdin.read(1)
            if len(x) == 0:
                break
            chan.send(x)

finally:
    # 重新设置终端属性
    termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)

chan.close()
tran.close()

更多参见:paramoko源码 https://github.com/paramiko/paramiko

posted on 2017-02-10 19:31  1930251516  阅读(434)  评论(0编辑  收藏  举报