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 paramikotransport = 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.mp4sftp.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 paramikoprivate_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.pysftp.put(r'E:\test\a.mp4', '/tmp/b.mp4')# 将remove_path 下载到本地 local_path# sftp.get('remove_path', 'local_path')transport.close()
基于transport用户名和密码连接并执行命令
import paramikotransport = paramiko.Transport(('192.168.33.35', 22))transport.connect(username='root', password='xxx')ssh = paramiko.SSHClient()ssh._transport = transportstdin, stdout, stderr = ssh.exec_command('df')print(stdout.read().decode())transport.close()
总结:
1、执行命令既可以用SSHClient,也可以用transport
2、当上传文件或下载文件的时候,只能用transport
基于类的模式封装了命令和上传及下载功能
import paramikoclass 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 paramikoimport sysimport socketimport selectfrom paramiko.py3compat import utran = 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 paramikoimport sysimport socketimport selectimport termiosimport ttyfrom paramiko.py3compat import utran = 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