Paramiko
paramiko模块,基于SSH用于连接远程服务器并执行相关操作。
一、安装
1 pip3 install paramiko
二、使用
SSHClient
用于连接远程服务器并执行基本命令
基于用户名密码连接:
import paramiko# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname='c1.salt.com', port=22, username='wupeiqi', password='123')# 执行命令
stdin, stdout, stderr = ssh.exec_command('ls')
# 获取命令结果
result = stdout.read()# 关闭连接
ssh.close()
import paramikotransport = paramiko.Transport(('hostname', 22))
transport.connect(username='wupeiqi', password='123')ssh = paramiko.SSHClient()
ssh._transport = transportstdin, stdout, stderr = ssh.exec_command('df')
print stdout.read()transport.close()SSHClient 封装 TransportSSHClient 封装 Transport
基于私钥进行连接
import paramikoprivate_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='c1.salt.com', port=22, username='wupeiqi', key=private_key)# 执行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 获取命令结果
result = stdout.read()# 关闭连接
ssh.close()
import paramikoprivate_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')transport = paramiko.Transport(('hostname', 22))
transport.connect(username='wupeiqi', pkey=private_key)ssh = paramiko.SSHClient()
ssh._transport = transportstdin, stdout, stderr = ssh.exec_command('df')transport.close()SSHClient 封装 TransportSSHClient 封装 Transport
基于私钥字符进行连接
import paramiko
from io import StringIOkey_str = """-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAq7gLsqYArAFco02/55IgNg0r7NXOtEM3qXpb/dabJ5Uyky/8
NEHhFiQ7deHIRIuTW5Zb0kD6h6EBbVlUMBmwJrC2oSzySLU1w+ZNfH0PE6W6fans
H80whhuc/YgP+fjiO+VR/gFcqib8Rll5UfYzf5H8uuOnDeIXGCVgyHQSmt8if1+e
7hn1MVO1Lrm9Fco8ABI7dyv8/ZEwoSfh2C9rGYgA58LT1FkBRkOePbHD43xNfAYC
tfLvz6LErMnwdOW4sNMEWWAWv1fsTB35PAm5CazfKzmam9n5IQXhmUNcNvmaZtvP
c4f4g59mdsaWNtNaY96UjOfx83Om86gmdkKcnwIDAQABAoIBAQCnDBGFJuv8aA7A
ZkBLe+GN815JtOyye7lIS1n2I7En3oImoUWNaJEYwwJ8+LmjxMwDCtAkR0XwbvY+
c+nsKPEtkjb3sAu6I148RmwWsGncSRqUaJrljOypaW9dS+GO4Ujjz3/lw1lrxSUh
IqVc0E7kyRW8kP3QCaNBwArYteHreZFFp6XmtKMtXaEA3saJYILxaaXlYkoRi4k8
S2/K8aw3ZMR4tDCOfB4o47JaeiA/e185RK3A+mLn9xTDhTdZqTQpv17/YRPcgmwz
zu30fhVXQT/SuI0sO+bzCO4YGoEwoBX718AWhdLJFoFq1B7k2ZEzXTAtjEXQEWm6
01ndU/jhAasdfasdasdfasdfa3eraszxqwefasdfadasdffsFIfAsjQb4HdkmHuC
OeJrJOd+CYvdEeqJJNnF6AbHyYHIECkj0Qq1kEfLOEsqzd5nDbtkKBte6M1trbjl
HtJ2Yb8w6o/q/6Sbj7wf/cW3LIYEdeVCjScozVcQ9R83ea05J+QOAr4nAoGBAMaq
UzLJfLNWZ5Qosmir2oHStFlZpxspax/ln7DlWLW4wPB4YJalSVovF2Buo8hr8X65
lnPiE41M+G0Z7icEXiFyDBFDCtzx0x/RmaBokLathrFtI81UCx4gQPLaSVNMlvQA
539GsubSrO4LpHRNGg/weZ6EqQOXvHvkUkm2bDDJAoGATytFNxen6GtC0ZT3SRQM
WYfasdf3xbtuykmnluiofasd2sfmjnljkt7khghmghdasSDFGQfgaFoKfaawoYeH
C2XasVUsVviBn8kPSLSVBPX4JUfQmA6h8HsajeVahxN1U9e0nYJ0sYDQFUMTS2t8
RT57+WK/0ONwTWHdu+KnaJECgYEAid/ta8LQC3p82iNAZkpWlGDSD2yb/8rH8NQg
9tjEryFwrbMtfX9qn+8srx06B796U3OjifstjJQNmVI0qNlsJpQK8fPwVxRxbJS/
pMbNICrf3sUa4sZgDOFfkeuSlgACh4cVIozDXlR59Z8Y3CoiW0uObEgvMDIfenAj
98pl3ZkCgYEAj/UCSni0dwX4pnKNPm6LUgiS7QvIgM3H9piyt8aipQuzBi5LUKWw
DlQC4Zb73nHgdREtQYYXTu7p27Bl0Gizz1sW2eSgxFU8eTh+ucfVwOXKAXKU5SeI
+MbuBfUYQ4if2N/BXn47+/ecf3A4KgB37Le5SbLDddwCNxGlBzbpBa0=
-----END RSA PRIVATE KEY-----"""private_key = paramiko.RSAKey(file_obj=StringIO(key_str))
transport = paramiko.Transport(('10.0.1.40', 22))
transport.connect(username='wupeiqi', pkey=private_key)ssh = paramiko.SSHClient()
ssh._transport = transportstdin, stdout, stderr = ssh.exec_command('df')
result = stdout.read()transport.close()print(result)基于私钥字符进行连接
SFTPClient
用于连接远程服务器并执行上传下载
基于用户名密码上传下载:
import paramikotransport = paramiko.Transport(('hostname',22))
transport.connect(username='wupeiqi',password='123')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()
基于公钥上传下载
import paramikoprivate_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')transport = paramiko.Transport(('hostname', 22))
transport.connect(username='wupeiqi', 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()
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import paramiko
import uuidclass SSHConnection(object):def __init__(self, host='172.16.103.191', port=22, username='wupeiqi',pwd='123'):self.host = hostself.port = portself.username = usernameself.pwd = pwdself.__k = Nonedef create_file(self):file_name = str(uuid.uuid4())with open(file_name,'w') as f:f.write('sb')return file_namedef run(self):self.connect()self.upload('/home/wupeiqi/tttttttttttt.py')self.rename('/home/wupeiqi/tttttttttttt.py', '/home/wupeiqi/ooooooooo.py)self.close()def connect(self):transport = paramiko.Transport((self.host,self.port))transport.connect(username=self.username,password=self.pwd)self.__transport = transportdef close(self):self.__transport.close()def upload(self,target_path):# 连接,上传file_name = self.create_file()sftp = paramiko.SFTPClient.from_transport(self.__transport)# 将location.py 上传至服务器 /tmp/test.pysftp.put(file_name, target_path)def rename(self, old_path, new_path):ssh = paramiko.SSHClient()ssh._transport = self.__transport# 执行命令cmd = "mv %s %s" % (old_path, new_path,)stdin, stdout, stderr = ssh.exec_command(cmd)# 获取命令结果result = stdout.read()def cmd(self, command):ssh = paramiko.SSHClient()ssh._transport = self.__transport# 执行命令stdin, stdout, stderr = ssh.exec_command(command)# 获取命令结果result = stdout.read()return resultha = SSHConnection()
ha.run()Demodemo
1 # 对于更多限制命令,需要在系统中设置
2 /etc/sudoers
3
4 Defaults requiretty
5 Defaults:cmdb !requiretty
import paramiko
import uuidclass SSHConnection(object):def __init__(self, host='192.168.11.61', port=22, username='alex',pwd='alex3714'):self.host = hostself.port = portself.username = usernameself.pwd = pwdself.__k = Nonedef run(self):self.connect()passself.close()def connect(self):transport = paramiko.Transport((self.host,self.port))transport.connect(username=self.username,password=self.pwd)self.__transport = transportdef close(self):self.__transport.close()def cmd(self, command):ssh = paramiko.SSHClient()ssh._transport = self.__transport# 执行命令stdin, stdout, stderr = ssh.exec_command(command)# 获取命令结果result = stdout.read()return resultdef upload(self,local_path, target_path):# 连接,上传sftp = paramiko.SFTPClient.from_transport(self.__transport)# 将location.py 上传至服务器 /tmp/test.pysftp.put(local_path, target_path)ssh = SSHConnection()
ssh.connect()
r1 = ssh.cmd('df')
ssh.upload('s2.py', "/home/alex/s7.py")
ssh.close()
堡垒机
堡垒机执行流程:
- 管理员为用户在服务器上创建账号(将公钥放置服务器,或者使用用户名密码)
- 用户登陆堡垒机,输入堡垒机用户名密码,现实当前用户管理的服务器列表
- 用户选择服务器,并自动登陆
- 执行操作并同时将用户操作记录
注:配置.brashrc实现ssh登陆后自动执行脚本,如:/usr/bin/python /home/wupeiqi/menu.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-from sqlalchemy import create_engine, and_, or_, func, Table
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, DateTime
from sqlalchemy.orm import sessionmaker, relationshipBase = declarative_base() # 生成一个SqlORM 基类class Host(Base):__tablename__ = 'host'id = Column(Integer, primary_key=True, autoincrement=True)hostname = Column(String(64), unique=True, nullable=False)ip_addr = Column(String(128), unique=True, nullable=False)port = Column(Integer, default=22)class HostUser(Base):__tablename__ = 'host_user'id = Column(Integer, primary_key=True, autoincrement=True)username = Column(String(64), unique=True, nullable=False)AuthTypes = [('p', 'SSH/Password'),('r', 'SSH/KEY'),]auth_type = Column(String(16))cert = Column(String(255))host_id = Column(Integer, ForeignKey('host.id'))__table_args__ = (UniqueConstraint('host_id', 'username', name='_host_username_uc'),)class Group(Base):__tablename__ = 'group'id = Column(Integer, primary_key=True, autoincrement=True)name = Column(String(64), unique=True, nullable=False)class UserProfile(Base):__tablename__ = 'user_profile'id = Column(Integer, primary_key=True, autoincrement=True)username = Column(String(64), unique=True, nullable=False)password = Column(String(255), nullable=False)class Group2UserProfile(Base):__tablename__ = 'group_2_user_profile'id = Column(Integer, primary_key=True, autoincrement=True)user_profile_id = Column(Integer, ForeignKey('user_profile.id'))group_id = Column(Integer, ForeignKey('group.id'))__table_args__ = (UniqueConstraint('user_profile_id', 'group_id', name='ux_user_group'),)class Group2HostUser(Base):__tablename__ = 'group_2_host_user'id = Column(Integer, primary_key=True, autoincrement=True)host_user_id = Column(Integer, ForeignKey('host_user.id'))group_id = Column(Integer, ForeignKey('group.id'))__table_args__ = (UniqueConstraint('group_id', 'host_user_id', name='ux_group_host_user'),)class UserProfile2HostUser(Base):__tablename__ = 'user_profile_2_host_user'id = Column(Integer, primary_key=True, autoincrement=True)host_user_id = Column(Integer, ForeignKey('host_user.id'))user_profile_id = Column(Integer, ForeignKey('user_profile.id'))__table_args__ = (UniqueConstraint('user_profile_id', 'host_user_id', name='ux_user_host_user'),)class AuditLog(Base):__tablename__ = 'audit_log'id = Column(Integer, primary_key=True, autoincrement=True)action_choices2 = [(u'cmd', u'CMD'),(u'login', u'Login'),(u'logout', u'Logout'),]action_type = Column(String(16))cmd = Column(String(255))date = Column(DateTime)user_profile_id = Column(Integer, ForeignKey('user_profile.id'))host_user_id = Column(Integer, ForeignKey('host_user.id'))
表结构示例:
实现过程
1.前戏
import paramiko
import sys
import os
import socket
import select
import getpasstran = 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()#########
# 利用sys.stdin,肆意妄为执行操作
# 用户在终端输入内容,并将内容发送至远程服务器
# 远程服务器执行命令,并将结果返回
# 用户终端显示内容
#########chan.close()
tran.close()
肆意妄为1
import paramiko
import sys
import os
import socket
import select
import getpass
from paramiko.py3compat import utran = 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()while True:# 监视用户输入和服务器返回数据# sys.stdin 处理用户输入# chan 是之前创建的通道,用于接收服务器返回信息readable, writeable, error = select.select([chan, sys.stdin, ],[],[],1)if chan in readable:try:x = u(chan.recv(1024))if len(x) == 0:print('\r\n*** EOF\r\n')breaksys.stdout.write(x)sys.stdout.flush()except socket.timeout:passif sys.stdin in readable:inp = sys.stdin.readline()chan.sendall(inp)chan.close()
tran.close()
#!/usr/bin/env python
# -*- coding:utf-8 -*-import paramiko
import sys
import os
import socket
import select
import getpass
from paramiko.py3compat import udefault_username = getpass.getuser()
username = input('Username [%s]: ' % default_username)
if len(username) == 0:username = default_usernamehostname = input('Hostname: ')
if len(hostname) == 0:print('*** Hostname required.')sys.exit(1)tran = paramiko.Transport((hostname, 22,))
tran.start_client()default_auth = "p"
auth = input('Auth by (p)assword or (r)sa key[%s] ' % default_auth)
if len(auth) == 0:auth = default_authif auth == 'r':default_path = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa')path = input('RSA key [%s]: ' % default_path)if len(path) == 0:path = default_pathtry:key = paramiko.RSAKey.from_private_key_file(path)except paramiko.PasswordRequiredException:password = getpass.getpass('RSA key password: ')key = paramiko.RSAKey.from_private_key_file(path, password)tran.auth_publickey(username, key)
else:pw = getpass.getpass('Password for %s@%s: ' % (username, hostname))tran.auth_password(username, pw)# 打开一个通道
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))if len(x) == 0:print('\r\n*** EOF\r\n')breaksys.stdout.write(x)sys.stdout.flush()except socket.timeout:passif sys.stdin in readable:inp = sys.stdin.readline()chan.sendall(inp)chan.close()
tran.close()完整示例(一)完整示例(一)
肆意妄为2
import paramiko
import sys
import os
import socket
import select
import getpass
import termios
import tty
from paramiko.py3compat import utran = 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')breaksys.stdout.write(x)sys.stdout.flush()except socket.timeout:passif sys.stdin in r:x = sys.stdin.read(1)if len(x) == 0:breakchan.send(x)finally:# 重新设置终端属性termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)chan.close()
tran.close()
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import paramiko
import sys
import os
import socket
import getpass
import termios
import tty
import select
from paramiko.py3compat import udef interactive_shell(chan):# 获取原tty属性oldtty = termios.tcgetattr(sys.stdin)try:# 为tty设置新属性# 默认当前tty设备属性:# 输入一行回车,执行# CTRL+C 进程退出,遇到特殊字符,特殊处理。# 这是为原始模式,不认识所有特殊符号# 放置特殊字符应用在当前终端,如此设置,将所有的用户输入均发送到远程服务器tty.setraw(sys.stdin.fileno())tty.setcbreak(sys.stdin.fileno())chan.settimeout(0.0)while True:r, w, e = select.select([chan, sys.stdin], [], [])if chan in r:try:x = u(chan.recv(1024))if len(x) == 0:sys.stdout.write('\r\n*** EOF\r\n')breaksys.stdout.write(x)sys.stdout.flush()except socket.timeout:passif sys.stdin in r:x = sys.stdin.read(1)if len(x) == 0:breakchan.send(x)finally:# 重新设置终端属性termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)def run():hostname = input('请输入主机名: ')tran = paramiko.Transport((hostname, 22,))tran.start_client()username = input('请输入用户名: ')auth = input('请输入密码进行验证(p) 或 (r)sa Key进行验证?')if auth == 'r':path = input('请输入RSA key 路径: ')try:key = paramiko.RSAKey.from_private_key_file(path)except paramiko.PasswordRequiredException:password = getpass.getpass('RSA key password: ')key = paramiko.RSAKey.from_private_key_file(path, password)tran.auth_publickey(username, key)else:pw = getpass.getpass('请输入密码 %s@%s: ' % (username, hostname))tran.auth_password(username, pw)# 打开一个通道chan = tran.open_session()# 获取一个终端chan.get_pty()# 激活器chan.invoke_shell()interactive_shell(chan)chan.close()tran.close()if __name__ == '__main__':run()基于Passwd或者RSA进行登陆操作基于Passwd或者RSA进行登陆操作
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import paramiko
import sys
import os
import socket
import getpass
import termios
import tty
import select
from paramiko.py3compat import udef interactive_shell(chan):# 获取原tty属性oldtty = termios.tcgetattr(sys.stdin)try:# 为tty设置新属性# 默认当前tty设备属性:# 输入一行回车,执行# CTRL+C 进程退出,遇到特殊字符,特殊处理。# 这是为原始模式,不认识所有特殊符号# 放置特殊字符应用在当前终端,如此设置,将所有的用户输入均发送到远程服务器tty.setraw(sys.stdin.fileno())tty.setcbreak(sys.stdin.fileno())chan.settimeout(0.0)while True:r, w, e = select.select([chan, sys.stdin], [], [])if chan in r:try:x = u(chan.recv(1024))if len(x) == 0:sys.stdout.write('\r\n*** EOF\r\n')breaksys.stdout.write(x)sys.stdout.flush()except socket.timeout:passif sys.stdin in r:x = sys.stdin.read(1)if len(x) == 0:breakchan.send(x)finally:# 重新设置终端属性termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)def run():db_dict = {'c1.salt.com': {'root': {'user': 'root', 'auth': 'r', "cert": 'key路径'},'alex': {'user': 'alex', 'auth': 'p', "cert": '密码'},},'c2.salt.com': {'alex': {'user': 'alex', 'auth': 'p', "cert": '密码'},},}for row in db_dict.keys():print(row)hostname = input('请选择主机: ')tran = paramiko.Transport((hostname, 22,))tran.start_client()for item in db_dict[hostname].keys():print(item)username = input('请输入用户: ')user_dict = db_dict[hostname][username]if username['auth'] == 'r':key = paramiko.RSAKey.from_private_key_file(user_dict['cert'])tran.auth_publickey(username, key)else:pw = user_dict['cert']tran.auth_password(username, pw)# 打开一个通道chan = tran.open_session()# 获取一个终端chan.get_pty()# 激活器chan.invoke_shell()interactive_shell(chan)chan.close()tran.close()if __name__ == '__main__':run()提示用户选择主机和用户提示用户选择主机和用户
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import paramiko
import sys
import os
import socket
import getpass
import termios
import tty
import select
from paramiko.py3compat import udef interactive_shell(chan):# 获取原tty属性oldtty = termios.tcgetattr(sys.stdin)try:# 为tty设置新属性# 默认当前tty设备属性:# 输入一行回车,执行# CTRL+C 进程退出,遇到特殊字符,特殊处理。# 这是为原始模式,不认识所有特殊符号# 放置特殊字符应用在当前终端,如此设置,将所有的用户输入均发送到远程服务器tty.setraw(sys.stdin.fileno())tty.setcbreak(sys.stdin.fileno())chan.settimeout(0.0)log = open('handle.log', 'a+', encoding='utf-8')flag = Falsetemp_list = []while True:r, w, e = select.select([chan, sys.stdin], [], [])if chan in r:try:x = u(chan.recv(1024))if len(x) == 0:sys.stdout.write('\r\n*** EOF\r\n')break# 如果用户上一次点击的是tab键,则获取返回的内容写入在记录中if flag:if x.startswith('\r\n'):passelse:temp_list.append(x)flag = Falsesys.stdout.write(x)sys.stdout.flush()except socket.timeout:passif sys.stdin in r:# 读取用户在终端数据每一个字符x = sys.stdin.read(1)if len(x) == 0:break# 如果用户点击TAB键if x == '\t':flag = Trueelse:# 未点击TAB键,则将每个操作字符记录添加到列表中,以便之后写入文件temp_list.append(x)# 如果用户敲回车,则将操作记录写入文件if x == '\r':log.write(''.join(temp_list))log.flush()temp_list.clear()chan.send(x)finally:# 重新设置终端属性termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)def run():db_dict = {'c1.salt.com': {'root': {'user': 'root', 'auth': 'r', "cert": 'key路径'},'alex': {'user': 'alex', 'auth': 'p', "cert": '密码'},},'c2.salt.com': {'root': {'user': 'root', 'auth': 'r', "cert": 'key路径'},'alex': {'user': 'alex', 'auth': 'p', "cert": '密码'},},}for row in db_dict.keys():print(row)hostname = input('请选择主机: ')tran = paramiko.Transport((hostname, 22,))tran.start_client()for item in db_dict[hostname].keys():print(item)username = input('请输入用户: ')user_dict = db_dict[hostname][username]if username['auth'] == 'r':key = paramiko.RSAKey.from_private_key_file(user_dict['cert'])tran.auth_publickey(username, key)else:pw = user_dict['cert']tran.auth_password(username, pw)# 打开一个通道chan = tran.open_session()# 获取一个终端chan.get_pty()# 激活器chan.invoke_shell()interactive_shell(chan)chan.close()tran.close()if __name__ == '__main__':run()提示用户选择主机和用户(记录操作日志)提示用户选择主机和用户(记录操作日志)
更多参见:paramoko源码 https://github.com/paramiko/paramiko
武沛齐:http://www.cnblogs.com/wupeiqi/p/5699254.html
Alex堡垒机:http://www.cnblogs.com/alex3714/articles/5286889.html