1、paramiko模块介绍
paramiko模块提供了基于ssh连接,进行远程登录服务器执行命令和上传下载文件的功能。这是一个第三方的软件包,使用之前需要安装。
2、paramiko的使用方法
(1)基于用户名和密码的sshclient方式登陆
#!/usr/bin/env python#coding:utf8import 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.129port=2323user=rootpwd=123.comtimeout=1.1#封装ssh类#!/usr/bin/env python#coding:utf8import configparser,paramikoclass 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:utf8import 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:utf8import 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 paramikoimport osimport selectimport sys# 建立一个sockettrans = 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 paramikoimport osimport selectimport sysimport ttyimport termios'''实现一个xshell登录系统的效果,登录到系统就不断输入命令同时返回结果支持自动补全,直接调用服务器终端'''# 建立一个sockettrans = 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()