python3之paramiko模块
1、paramiko模块介绍
paramiko模块提供了基于ssh连接,进行远程登录服务器执行命令和上传下载文件的功能。这是一个第三方的软件包,使用之前需要安装。
2、paramiko的使用方法
(1)基于用户名和密码的sshclient方式登陆
#!/usr/bin/env python #coding:utf8 import paramiko #创建sshclient对象 ssh = paramiko.SSHClient() #允许将信任的主机自动加入到host_allow 列表,此方法必须放在connect方法的前面 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #调用connect方法连接服务器 ssh.connect(hostname='172.16.32.129',port=2323,username='root',password='123.com') while True: input_command = input('>>>:') if input_command == 'quit': break #执行命令,输出结果在stdout中,如果是错误则放在stderr中 stdin,stdout,stderr = ssh.exec_command(input_command) result = stdout.read() #read方法读取输出结果 if len(result) == 0: #判断如果输出结果长度等于0表示为错误输出 print(stderr.read()) else: print(str(result,'utf-8')) ssh.close()
封装方法,隐藏属性:
#config.ini文件 [ssh] host=172.16.32.129 port=2323 user=root pwd=123.com timeout=1.1 #封装ssh类 #!/usr/bin/env python #coding:utf8 import configparser,paramiko class parmikoclient(object): def __init__(self,ini_file): self.config=configparser.ConfigParser() self.config.read(ini_file) self.host = self.config.get('ssh','host') self.port = self.config.get('ssh', 'port') self.user = self.config.get('ssh', 'user') self.pwd = self.config.get('ssh', 'pwd') self.timeout = self.config.get('ssh', 'timeout') self.client=paramiko.SSHClient() self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) self.client.connect(hostname=self.host,port=self.port,username=self.user,password=self.pwd,timeout=float(self.timeout)) def run_ssh(self,cmd_command): # 执行命令,输出结果在stdout中,如果是错误则放在stderr中 stdin,stdout,stderr = self.client.exec_command(cmd_command) result = stdout.read() # read方法读取输出结果 if len(result) == 0: # 判断如果输出结果长度等于0表示为错误输出 print(stderr.read().decode()) else: print(str(result, 'utf-8')) def close(self): self.client.close() if __name__ == '__main__': client_cmd = parmikoclient('config.ini') while True: cmd_input=input('>>>:') client_cmd.run_ssh(cmd_input) if cmd_input == 'quit': client_cmd.close()
通过transport方式登录:
#!/usr/bin/env python #coding:utf8 import paramiko #实例化一个transport对象 transport = paramiko.Transport(('172.16.32.129',2323)) #建立连接 transport.connect(username='root',password='123') #建立ssh对象 ssh = paramiko.SSHClient() #绑定transport到ssh对象 ssh._transport=transport #执行命令 stdin,stdout,stderr=ssh.exec_command('df') #打印输出 print(stdout.read().decode()) #关闭连接 transport.close()
(2)基于密钥的sshclient方式登陆
#!/usr/bin/env python #coding:utf8 #必须先将公钥文件传输到服务器的~/.ssh/authorized_keys中 import paramiko # 指定本地的RSA私钥文件,如果建立密钥对时设置的有密码,password为设定的密码,如无不用指定password参数 pkey = paramiko.RSAKey.from_private_key_file('id_rsa_1024') #建立连接 ssh = paramiko.SSHClient() #允许将信任的主机自动加入到known_hosts列表 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(hostname='172.16.32.129',port=2323,username='root',pkey=pkey) #指定密钥连接 #执行命令 stdin,stdout,stderr=ssh.exec_command('free -m') print(stdout.read().decode()) ssh.close()
以上需要确保被访问的服务器对应用户.ssh目录下有authorized_keys文件,也就是将服务器上生成的公钥文件保存为authorized_keys。并将私钥文件作为paramiko的登陆密钥
transport封装密钥登陆:
#!/usr/bin/env python #coding:utf8 #必须先将公钥文件传输到服务器的~/.ssh/authorized_keys中 import paramiko # 指定本地的RSA私钥文件,如果建立密钥对时设置的有密码,password为设定的密码,如无不用指定password参数 pkey = paramiko.RSAKey.from_private_key_file('id_rsa_1024') #创建transport对象绑定主机和端口,指定用户和密钥连接 transport = paramiko.Transport(('172.16.32.129',2323)) transport.connect(username='root',pkey=pkey) ssh = paramiko.SSHClient() ssh._transport = transport #类属性赋值 #允许将信任的主机自动加入到known_hosts列表 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #执行命令 stdin,stdout,stderr=ssh.exec_command('free -m') print(stdout.read().decode()) ssh.close()
(3)SFTP文件传输
#!/usr/bin/env python #coding:utf8 import paramiko #实例化transport对象,并建立连接 transport = paramiko.Transport(('172.16.32.129',2323)) transport.connect(username='root',password='123.com') #实例化sftp对象,指定连接对象 sftp = paramiko.SFTPClient.from_transport(transport) #上传文件 sftp.put(localpath='id_rsa_1024',remotepath='/root/idrsa1024.txt') #下载文件 sftp.get(remotepath='/root/idrsa1024.txt',localpath='idrsa1024_back.txt') #关闭连接 transport.close()
实现一个类似xshell工具的功能,登录以后可以输入命令回车后就返回结果:
import paramiko import os import select import sys # 建立一个socket trans = paramiko.Transport(('192.168.2.129', 22)) # 启动一个客户端 trans.start_client() # 如果使用rsa密钥登录的话 ''' default_key_file = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa') prikey = paramiko.RSAKey.from_private_key_file(default_key_file) trans.auth_publickey(username='super', key=prikey) ''' # 如果使用用户名和密码登录 trans.auth_password(username='super', password='super') # 打开一个通道 channel = trans.open_session() # 获取终端 channel.get_pty() # 激活终端,这样就可以登录到终端了,就和我们用类似于xshell登录系统一样 channel.invoke_shell() # 下面就可以执行你所有的操作,用select实现 # 对输入终端sys.stdin和 通道进行监控, # 当用户在终端输入命令后,将命令交给channel通道,这个时候sys.stdin就发生变化,select就可以感知 # channel的发送命令、获取结果过程其实就是一个socket的发送和接受信息的过程 while True: readlist, writelist, errlist = select.select([channel, sys.stdin,], [], []) # 如果是用户输入命令了,sys.stdin发生变化 if sys.stdin in readlist: # 获取输入的内容 input_cmd = sys.stdin.read(1) # 将命令发送给服务器 channel.sendall(input_cmd) # 服务器返回了结果,channel通道接受到结果,发生变化 select感知到 if channel in readlist: # 获取结果 result = channel.recv(1024) # 断开连接后退出 if len(result) == 0: print("\r\n**** EOF **** \r\n") break # 输出到屏幕 sys.stdout.write(result.decode()) sys.stdout.flush() # 关闭通道 channel.close() # 关闭链接 trans.close()
支持tab自动补全
import paramiko import os import select import sys import tty import termios ''' 实现一个xshell登录系统的效果,登录到系统就不断输入命令同时返回结果 支持自动补全,直接调用服务器终端 ''' # 建立一个socket trans = paramiko.Transport(('192.168.2.129', 22)) # 启动一个客户端 trans.start_client() # 如果使用rsa密钥登录的话 ''' default_key_file = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa') prikey = paramiko.RSAKey.from_private_key_file(default_key_file) trans.auth_publickey(username='super', key=prikey) ''' # 如果使用用户名和密码登录 trans.auth_password(username='super', password='super') # 打开一个通道 channel = trans.open_session() # 获取终端 channel.get_pty() # 激活终端,这样就可以登录到终端了,就和我们用类似于xshell登录系统一样 channel.invoke_shell() # 获取原操作终端属性 oldtty = termios.tcgetattr(sys.stdin) try: # 将现在的操作终端属性设置为服务器上的原生终端属性,可以支持tab了 tty.setraw(sys.stdin) channel.settimeout(0) while True: readlist, writelist, errlist = select.select([channel, sys.stdin,], [], []) # 如果是用户输入命令了,sys.stdin发生变化 if sys.stdin in readlist: # 获取输入的内容,输入一个字符发送1个字符 input_cmd = sys.stdin.read(1) # 将命令发送给服务器 channel.sendall(input_cmd) # 服务器返回了结果,channel通道接受到结果,发生变化 select感知到 if channel in readlist: # 获取结果 result = channel.recv(1024) # 断开连接后退出 if len(result) == 0: print("\r\n**** EOF **** \r\n") break # 输出到屏幕 sys.stdout.write(result.decode()) sys.stdout.flush() finally: # 执行完后将现在的终端属性恢复为原操作终端属性 termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty) # 关闭通道 channel.close() # 关闭链接 trans.close()