如何用Python的Paramiko库实现SSH远程连接与SFTP文件传输操作
最编程
2024-02-10 10:19:34
...
paramiko是一个用于做远程控制的模块,使用该模块可以对远程服务器进行命令或文件操作,paramiko是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接。
一、安装paramiko
1.命令行使用pip3安装
由于 paramiko 模块内部依赖pycrypto,所以先下载安装pycrypto,再安装paramiko
pip3 install pycrypto
pip3 install paramiko
2.直接pycharm内安装
进入pycharm,执行‘import paramiko',发现没有paramiko,将鼠标放在paramiko上,按‘alt + enter‘,在出现的界面上选择第一个'Install package paramiko'进行安装。等待出现'Package installed successfully'表明安装成功。
二、使用
1.SSHClient
用于连接远程服务器并执行基本命令
①基于用户名密码连接:
import paramiko ##1.创建一个ssh对象 client = paramiko.SSHClient() #2.允许连接不在know_hosts文件中的主机,即之前没有连接过的主机 client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #3.连接服务器 client.connect(hostname='172.25.254.31', port=22, username='root', password='123456') #4.执行操作 stdin,stdout, stderr = client.exec_command('hostname') #5.获取命令执行的结果 result=stdout.read().decode('utf-8') print(result) #6.关闭连接 client.close()
登录失败提示报错案例:
from paramiko.ssh_exception import NoValidConnectionsError from paramiko.ssh_exception import AuthenticationException import paramiko def ssh_connect(): #1.创建一个ssh对象,并允许连接之前没有连接的主机 client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #2.连接服务器 try: client.connect(hostname=hostname, port=port, username=username, password=passwd) print('正在连接主机%s......'%(hostname)) except NoValidConnectionsError as e: ###用户不存在时的报错 print("连接失败") except AuthenticationException as t: ##密码错误的报错 print('密码错误') else: #3.执行操作 stdin,stdout, stderr = client.exec_command(cmd) #4.获取命令执行的结果 result=stdout.read().decode('utf-8') print(result) #5.关闭连接 finally: client.close()
②基于公钥密钥连接:
import paramiko # id_rsa为本地局域网密钥文件 private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa') # 创建SSH对象 client = paramiko.SSHClient() # 允许连接不在know_hosts文件中的主机 client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 连接服务器 client.connect(hostname='c1.salt.com', port=22, username='wupeiqi', key=private_key) # 执行命令 stdin, stdout, stderr = client.exec_command('df') # 获取命令结果 result = stdout.read().decode('utf-8')
# 关闭连接 ssh.close()
2.SFTPClient
用于连接远程服务器并执行上传下载
①基于用户名密码上传下载:
import paramiko transport = paramiko.Transport(('hostname',22)) transport.connect(username='root',password='123456') 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 paramiko private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa') transport = paramiko.Transport(('hostname', 22)) transport.connect(username='root', 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()
3.paramiko通过堡垒机在远程访问服务器
import paramiko import sys blip="10.254.24.100" #堡垒机地址 bluser="xxx" #堡垒机用户名 blpasswd='xxx' #堡垒机密码 hostname='10.100.255.220' #业务服务器地址 username='root' #业务服务器用户名 password='xxxx' #业务服务器密码 port=22 #堡垒机连接端口 def receive_data(match,receive_len=9999): buff='' resp='' while not buff.endswith(match): #接受到的数据末尾如果是match,结束循环 try: resp = channel.recv(receive_len) #远端接受数据 except Exception as e: print('Eroor info:%s connection time' % str(e)) channel.close() ssh.close() sys.exit() buff += resp.decode('utf-8') #resp为bytes,需转成str,才可进行字符串拼接成buff return buff def save_file(filename,mode,content): with open(filename,mode,encoding='utf-8') as f: f.write(content) if __name__ == '__main__': sum ='' paramiko.util.log_to_file('login.log') ssh=paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(hostname=blip,port=port,username=bluser,password=blpasswd) channel=ssh.invoke_shell() #创建会话,开启命令调用 channel.settimeout(20) #20秒超时 match_list=['page: ','account: ','Input account: ',"'s password: ",'# ','# '] send_list=['0\n','%s\n'%blip,'1\n','%s\n'%username,'%s\n'%password,'ifconfig\n'] for index,per_match in enumerate(match_list): channel.send(send_list[index]) buff=receive_data(per_match) sum +=buff # print(buff) print(sum) #打印整个过程的交互数据 save_file('6_3_2_operate.log','w',sum) channel.close() ssh.close()
4.paramiko通过堡垒机登录业务机上传文件
#客户端先上传文件到堡垒机,在通过堡垒机上传文件到业务服务器 import paramiko import os,sys,time blip='172.17.9.68' #堡垒机信息 bluser='root' blpasswd='xxx' hostname='172.17.9.70' #定义业务服务器信息 username='root' password='xxxx' tmpdir="/root" remotedir='/root' localpath='6_1_login.log' #本地源文件路径 tmppath=tmpdir+'/6_1_login.log' #堡垒机临时路径 remotepath=remotedir+'/6_1_login.log' #业务主机目标路径 port =22 passinfo="'s password: " paramiko.util.log_to_file('syslogin.log') t=paramiko.Transport((blip,port)) t.connect(username=bluser,password=blpasswd) sftp=paramiko.SFTPClient.from_transport(t) sftp.put(localpath=localpath,remotepath=tmppath) #上传本地文件源到堡垒机临时路径 sftp.close() ssh=paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(hostname=blip,username=bluser,password=blpasswd) channel=ssh.invoke_shell() channel.settimeout(20) buff="" resp="" print ('scp '+tmpdir+' '+username+'@'+hostname+':'+remotepath+'\n') #scp中转目录文件到目标主机 channel.send('scp '+tmppath+' '+username+'@'+hostname+':'+remotepath+'\n') while not buff.endswith(passinfo): try: resp=channel.recv(9999) except Exception as e: print('Error info:%s connection time.'%(str(e))) channel.close() ssh.close() sys.exit() buff +=resp.decode('utf-8') # print(buff) if not buff.find('yes/no') == -1: #找到yes/no字符,执行以下语句 channel.send('yes\n') buff='' channel.send(password+'\n') buff='' while not buff.endswith('# '): #buff末尾不是'# '字符,就执行以下语句 resp=channel.recv(9999) if not resp.decode('utf-8').find(passinfo) ==-1: #找到‘s password:字符就执行以下语句,说明密码错误 print ('Error info:Authentication failed.') channel.cholse() ssh.close() sys.exit() buff +=resp.decode('utf-8') print (buff) channel.close() ssh.close() 堡垒机模式下的文件上传
参考原文:https://www.cnblogs.com/python-nameless/p/6855804.html
https://www.cnblogs.com/lisenlin/p/9201781.html