(1)基于用户名和密码的连接

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import paramiko
 
# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname='123.123.123.123', port=22, username='user', password='passwd')
# 执行命令
stdin, stdout, stderr = ssh.exec_command('ls')
# 获取命令结果
result = stdout.read()
# 关闭连接
ssh.close()

SSHClient 封装 Transport

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import paramiko
 
transport = paramiko.Transport(('hostname', 22))
transport.connect(username='user', password='passwd')
 
ssh = paramiko.SSHClient()
ssh._transport = transport
 
stdin, stdout, stderr = ssh.exec_command('df')
print(stdout.read())
 
transport.close()

(2)基于公钥秘钥连接

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import paramiko
 
private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname='123.123.123, port=22, username='user', key=private_key)
# 执行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 获取命令结果
result = stdout.read()
# 关闭连接
ssh.close()

SSHClient 封装Transport

1
2
3
4
5
6
7
8
9
import paramiko
 
private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
transport = paramiko.Transport(('hostname', 22))
transport.connect(username='user', pkey=private_key)
ssh = paramiko.SSHClient()
ssh._transport = transport
stdin, stdout, stderr = ssh.exec_command('df')
transport.close()

(3)基于用户名密码上传下载

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import paramiko
 
transport = paramiko.Transport(('hostname',22))
transport.connect(username='user',password='passwd')
 
sftp = paramiko.SFTPClient.from_transport(transport)
# 将location.py 上传至服务器 /tmp/test.py
sftp.put('/tmp/location.py', '/tmp/test.py')
# 将remove_path 下载到本地 local_path
sftp.get('remove_path', 'local_path')
 
transport.close()

(4)基于公钥秘钥上传下载

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import paramiko
 
private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
 
transport = paramiko.Transport(('hostname', 22))
transport.connect(username='GSuser', pkey=private_key )
 
sftp = paramiko.SFTPClient.from_transport(transport)
# 将location.py 上传至服务器 /tmp/test.py
sftp.put('/tmp/location.py', '/tmp/test.py')
# 将remove_path 下载到本地 local_path
sftp.get('remove_path', 'local_path')
 
transport.close()

(5)Demo: 实现远程命令执行和文件上传

demo1:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import paramiko
 
class SSHConnection(object):
 
    def __init__(self, host='192.168.12.68', port=22, username='locojoy',pwd='123321QQ!'):
        self.host = host
        self.port = port
        self.username = username
        self.pwd = pwd
        self.__k = None
 
    def run(self):
        self.connect()  # 连接远程服务器
        self.upload('db.py','/tmp/1.py')  # 将本地的db.py文件上传到远端服务器的/tmp/目录下并改名为1.py
        self.cmd('df')  # 执行df 命令
        self.close()    # 关闭连接
 
    def connect(self):
        transport = paramiko.Transport((self.host, self.port))
        transport.connect(username=self.username, password=self.pwd)
        self.__transport = transport
 
    def close(self):
        self.__transport.close()
 
    def upload(self,local_path,target_path):
        sftp = paramiko.SFTPClient.from_transport(self.__transport)
        sftp.put(local_path,target_path)
 
    def cmd(self, command):
        ssh = paramiko.SSHClient()
        ssh._transport = self.__transport
        # 执行命令
        stdin, stdout, stderr = ssh.exec_command(command)
        # 获取命令结果
        result = stdout.read()
        print(result)
        return result
 
obj = SSHConnection()
obj.run()

demo2:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import paramiko
import os
 
class ParamikoHelper():
 
    def __init__(self,remote_ip, remote_ssh_port, private_key_file, ssh_username ):
        self.remote_ip = remote_ip
        self.remote_ssh_port = remote_ssh_port
        self.ssh_username = ssh_username
        self.private_key = paramiko.RSAKey.from_private_key_file(private_key_file) # 实例化一个私钥对象
 
    def connect_ssh(self):
        try:
            self.ssh = paramiko.SSHClient()
            self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            self.ssh.connect(hostname=self.remote_ip, port=self.remote_ssh_port, username=self.ssh_username,
                             pkey=self.private_key)
        except Exception as e:
            print(e)
        return self.ssh
 
    def close_ssh(self):
        try:
            self.ssh.close()
        except Exception as e:
            print(e)
 
    def exec_shell(self, shell):
        ssh = self.connect_ssh()
        try:
            stdin, stdout, stderr = ssh.exec_command(shell)
            return stdin, stdout, stderr
        except Exception as e:
            print(e)
 
    def sftp_put_file(self, file, local_dir, remote_dir):
        try:
            t = paramiko.Transport((self.remote_ip, self.remote_ssh_port))
            t.connect(username=self.ssh_username, pkey=self.private_key)
            sftp = paramiko.SFTPClient.from_transport(t)
            sftp.put(os.path.join(local_dir, file), remote_dir)
            t.close()
        except Exception:
            print("connect error!")
 
    def sftp_get_file(self, file, local_dir, remote_dir):
        try:
            t = paramiko.Transport((self.remote_ip, self.remote_ssh_port))
            t.connect(username=self.ssh_username, pkey=self.private_key)
            sftp = paramiko.SFTPClient.from_transport(t)
            sftp.get(remote_dir, os.path.join(local_dir, file))
            t.close()
        except Exception:
            print("connect error!")
 
 
def main():
    remote_ip = '192.168.196.134'
    remote_ssh_port = 22
    ssh_username = 'root'
    private_key_file = 'performance_rsa_4096' # RSA私钥
    ph = ParamikoHelper(remote_ip=remote_ip,remote_ssh_port=remote_ssh_port,private_key_file=private_key_file,ssh_username=ssh_username)
 
    # 远程执行ssh命令
    shell = "df -h | grep dev"
    stdin, stdout, stderr = ph.exec_shell(shell)
    for line in stdout.readlines():
        print(line)
    ph.close_ssh()
 
    # 上传文件file4.txt到远程服务器上
    file = 'file4.txt'
    remote_dir = '/root/test_log/' + file
    local_dir = os.getcwd()
    ph.sftp_put_file(file=file, local_dir=local_dir, remote_dir=remote_dir)
 
    # 下载文件file3.txt
    file = 'file3.txt'
    remote_dir = '/root/test_log/' + file
    local_dir = os.getcwd()
    ph.sftp_get_file(file=file, local_dir=local_dir, remote_dir=remote_dir)
 
if __name__ == '__main__':
    main()

(6)paramiko在堡垒机中的应用

(1)简单实例:远程连接一台主机,操作命令,linux版本,输入终端为回车则发送命令。不支持tab补全功能。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import paramiko, sys, os, socket, select, getpass
from paramiko.py3compat import u   # 在python3中是这样使用的,如果在Python2中则注释这行
 
# 这个程序依赖于终端,只能在Liunx下运行,windows用其他的方式
 
tran = paramiko.Transport(('192.168.12.68', 22,))
tran.start_client()
tran.auth_password('locojoy', '123321QQ!')
 
# 打开一个通道
chan = tran.open_session()
# 获取一个终端
chan.get_pty()
# 激活器
chan.invoke_shell()
 
# 原始的方法利用终端进行收发消息
# 利用sys.stdin,肆意妄为执行操作
# 用户在终端输入内容,并将内容发送至远程服务器
# 远程服务器执行命令,并将结果返回
# 用户终端显示内容
 
while True:
    # 监视用户输入和服务器返回数据
    # sys.stdin 处理用户输入
    # chan 是之前创建的通道,用于接收服务器返回信息
    # 通过select监听终端(输入输出),一旦变化,就将拿到的数据发送给服务器
    # 通过监听socket句柄,如果有变化表示服务器要给我发消息
    readable, writeable, error = select.select([chan, sys.stdin, ],[],[],1)
    # 通过select.select 监听chan(打开的通道(和远程服务器连接的状态)), sys.stdin(输入),一旦变化就写入readable
    # 当chan变化时,加入到readable,远程服务器发送内容过来
    if chan in readable:
        try:
            x = u(chan.recv(1024))  # Python3用这个
            # x = chan.recv(1024)  Python2使用这个
            if len(x) == 0:
                print('\r\n*** EOF\r\n')
                break
            sys.stdout.write(x)   # 写入缓冲区
            sys.stdout.flush()    # 刷新,将缓冲区内容显示出来
        except socket.timeout:
            pass
    # 当sys.stdin 放入readable中时,将获取到的内容发送到远程服务器
    if sys.stdin in readable:
        inp = sys.stdin.readline()
        chan.sendall(inp)
 
chan.close()
tran.close()

(2)每按一个键就发送记录,并支持tab自动补全

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import paramiko, sys, os, socket, select, getpass, termios, tty
from paramiko.py3compat import u
 
tran = paramiko.Transport(('10.211.55.4', 22,))
tran.start_client()
tran.auth_password('wupeiqi', '123')
# 打开一个通道
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()

Reference

1、 https://www.cnblogs.com/meng-wei-zhi/p/8258674.html
2、 https://blog.csdn.net/u012887259/article/details/102425930

打赏

微信 微信 支付宝 支付宝
万分感谢