目录
1. 概述
本来是不想写Paramiko的,因为我觉得之前的一篇关于Netmiko模块更适合网工,后来发现paramiko有包含SFTP功能,所以还是有必要来讲讲,毕竟我们在设备上是要经常下载配置、上传版本/升级版本用的,而且SFTP比FTP、TFTP更安全。
所以, 你也不用借助其他工具来上传、下载了,通通用 'Python' 来帮你搞定了。
SSH和SFTP都是使用一样的端口号 22。如果对数据安全传输较重视,那么SFTP替代FTP、TFTP是首选。
实验环境说明:
- 一台思科路由器,用于SSH登陆;
- 一台华为交换机,用于SFTP上传/下载;
- PyCharm Pro
2. Paramiko的基本使用
2.1 SSHClient关键参数介绍
connect()函数:
用途:用于连接远端主机,其中'hostname'为必选参数。
常用参数 hostname //远端主机,填写IP和域名都可以 port=SSH_PORT //缺省为22端口 username=None //用于登陆远端主机使用的用户名 password=None //用于登陆远端主机使用的密码 pkey=None //使用私钥用于身份认证,也叫'免密'登陆 key_filename=None //使用私钥文件名 timeout=None //tcp连接超时时间 allow_agent=True //缺省允许连接到ssh代理 look_for_keys=True //缺省在~/.ssh中搜索私钥文件,默认为True 允许 compress=False //缺省没有开启压缩
load_system_host_keys()函数:
用途:用于加载主机密钥,密钥保存"known_hosts"文件中。
filename=None //缺省会加载"~/.ssh/known_hosts"文件
set_missing_host_key_policy()函数:
用途:用于检查远端主机在本地'host keys'是否有记录并使用哪种策略。
#目前支持的三种策略: 1.AutoAddPolicy //自动添加主机名及主机密钥到本地HostKeys对象,不依赖load_system_host_key的配置。即新建立ssh连接时不需要再输入yes或no进行确认 2.WarningPolicy //用于记录一个未知的主机密钥的python警告。并接受,功能上和AutoAddPolicy类似,但是会提示是新连接 3.RejectPolicy //自动拒绝未知的主机名和密钥,依赖load_system_host_key的配置。此为默认选项
exec_command()函数:
用途:用于在远端主机执行的命令,并返回输入、输出、错误信息。
command //执行的命令 stdin, stdout, stderr //分别表示输入、输出、错误
2.2 SSHClient常用示例
2.2.1 通过用户名和密码方式登陆:
import paramiko def ssh_client(): # 创建一个实例化 ssh = paramiko.SSHClient() # 加载系统HostKeys密钥 ssh.load_system_host_keys() # 自动添加策略,保存远端主机的主机名和密钥信息,如果不添加,那么不在本地knows_hosts文件中记录的主机将无法连接,默认拒接 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #连接远端主机 ssh.connect('192.168.0.101',port=22, username='admin', password='Admin@123') #执行命令 stdin, stdout,stderr = ssh.exec_command('show ip int br') print(stdout.read().decode('utf-8')) #关闭连接 ssh.close() if __name__ == '__main__': ssh_client()
执行代码返回结果如下:
2.2.2 通过用户名和密码方式登陆 ( transport方式 )
def ssh_client(): # 创建一个实例化 ssh = paramiko.SSHClient() #transport封装 t = paramiko.Transport('192.168.0.101', 22) t.connect(username='admin', password='Admin@123') ssh._transport = t # 加载系统HostKeys密钥 ssh.load_system_host_keys() # 自动添加策略,保存远端主机的主机名和密钥信息,如果不添加,那么不在本地knows_hosts文件中记录的主机将无法连接,默认拒接 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #执行命令 stdin, stdout,stderr = ssh.exec_command('show ip int br') print(stdout.read().decode('utf-8')) #关闭连接 ssh.close() if __name__ == '__main__': ssh_client()
执行代码返回结果如下:
结果同上,输出结果一样。
2.2.3 通过用户名和密钥方式登陆
思科路由器公钥配置:
username admin privilege 15 password Admin@123 ip domain name cisco.com crypto key generate rsa modulus 1024 ip ssh version 2 ip ssh pubkey-chain username admin key-hash ssh-rsa 560DE41351E40FF6C237F9BBFF4238AC singvis@DESKTOP-IQ964AEendend line vty 0 4 exec-timeout 5 0 logging synchronous login local transport input ssh privilege level 15
python代码:
import paramiko def ssh_client(): #私钥的绝对路径 private = paramiko.RSAKey.from_private_key_file(r'C:\Users\singvis\Documents\Identity') # 创建一个实例化 ssh = paramiko.SSHClient() # 加载系统HostKeys密钥 ssh.load_system_host_keys() # 自动添加策略,保存远端主机的主机名和密钥信息,如果不添加,那么不在本地knows_hosts文件中记录的主机将无法连接,默认拒接 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #连接远端主机,此处不需要密码,为私钥文件 ssh.connect('192.168.0.101',port=22, username='admin', pkey=private) #执行命令 stdin, stdout,stderr = ssh.exec_command('show ip int br') print(stdout.read().decode('utf-8')) ssh.close() if __name__ == '__main__': ssh_client()
通过SecurityCRT采用密钥方式登陆192.168.0.101,不用输入密码,直接就登陆:
说明:密钥的生成路径:tools->creat public key ( 本次通过SecurityCRT )
2.3 SFTPClient关键参数介绍
SFTPCLient作为一个sftp的客户端对象,根据ssh传输协议的sftp会话,实现远程文件操作,如上传、下载、权限、状态。
from_transport(cls,t) //创建一个已连通的SFTP客户端通道 put(localpath, remotepath, callback=None, confirm=True) //将本地文件上传到远端主机 get(remotepath, localpath, callback=None) //从远端主机下载文件到本地 mkdir() //创建目录 remove() //删除目录 rename() //重命名目录 stat() //查看文件状态 listdir() //列出目录下的文件
2.4 SFTPClient常用示例
以华为交换机为例子说明,交换机配置如下:
rsa local-key-pair create # stelnet server enable sftp server enable # aaa local-user admin password simple Admin@123 local-user admin privilege level 15 local-user admin service-type terminal ssh # ssh authentication-type default password ssh user admin authentication-type password ssh user admin service-type all ssh user admin sftp-directory flash:/ # user-interface vty 0 4 authentication-mode aaa protocol inbound ssh
Python代码如下:
import paramiko def sftp_put(): #文件路径 local_file =r'D:\test\123.txt' remote_file ='flash:/123.txt' t = paramiko.Transport('192.168.0.200', 22) t.connect(username='admin', password='Admin@123') sftp = paramiko.SFTPClient.from_transport(t) sftp.put(local_file,remote_file) t.close() def sftp_get(): local_path = r'D:\test\vrpcfg.zip' remote_path = 'flash:/vrpcfg.zip' t = paramiko.Transport('192.168.0.200', 22) t.connect(username='admin', password='Admin@123') # sftp = paramiko.SFTPClient.from_transport(t) sftp.get(remote_path, local_path) t.close() if __name__ == '__main__': sftp_put() sftp_get()
执行代码返回结果如下:
3. 完整代码
#!/usr/bin/env python #coding:utf-8 #欢迎关注微信公众号:点滴技术 #这里有靠谱的、有价值的、共成长的,专属于网络攻城狮 import paramiko, time from paramiko.ssh_exception import NoValidConnectionsError,AuthenticationException def ssh_client(host, user, pwd, cmds, verbose=True): # 私钥文件的存放路径 # private = paramiko.RSAKey.from_private_key_file(r'C:\Users\singvis\Documents\Identity') # 创建一个实例化 ssh = paramiko.SSHClient() # 加载系统SSH密钥 ssh.load_system_host_keys() # 自动添加策略,保存服务器的主机名和密钥信息,如果不添加,那么不在本地knows_hosts文件中记录的主机将无法连接,默认拒接 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 连接设备 try: ssh.connect(hostname=host, username=user, timeout=5, compress=True, password=pwd #pkey=private, #可以采用密钥连接 ) print("正在连接主机{}.....".format(host)) except NoValidConnectionsError: print('连接出现了问题') except AuthenticationException: print('用户名或密码错误') except Exception as e: print('其他错误问题{}'.format(e)) finally: #激活交互式shell chan = ssh.invoke_shell() time.sleep(1) for cmd in cmds: chan.send(cmd.encode()) #一定要有回车'Enter'这个动作 chan.send(b'\n') time.sleep(2) r = chan.recv(40960).decode() if verbose: print(r) chan.close() ssh.close() def sftp_get(ip, user, pwd, local_file,remote_file, port=22): try: t = paramiko.Transport(ip, port) t.connect(username=user, password=pwd) sftp = paramiko.SFTPClient.from_transport(t) sftp.get(remote_file, local_file) t.close() except Exception as e: print(e) def sftp_put(ip, user, pwd, local_file, remote_file, port=22): try: t = paramiko.Transport(ip, port) t.connect(username=user, password=pwd) sftp = paramiko.SFTPClient.from_transport(t) sftp.put(local_file, remote_file) t.close() except Exception as e: print(e) if __name__ == '__main__': ''' 不要运行的,请注释掉,前面加'#'符号 ''' ip = '192.168.0.101' user= 'admin' pwd= 'Admin@123' # local_file = r'D:\test\123.txt' # remote_file = 'flash:/vrpcfg.zip' # sftp_get(ip='192.168.0.200', user=user, pwd=pwd, remote_file=remote_file, local_file=r'D:\test\vrpcfg.zip') # sftp_put(ip='192.168.0.200', user=user, pwd=pwd, local_file=local_file, remote_file='flash:/123.txt') cmds = ['terminal length 0', 'show version', 'show ip int br','show ip route'] # cmds = ['disp ip int br','disp device','disp clock'] ssh_client(ip, user, pwd, cmds)
参考信息:
如果喜欢的我的文章,欢迎关注我的公众号:点滴技术,扫码关注,不定期分享