python使用paramiko实现ssh的功能详解
个人认为python的paramiko模块是运维人员必学模块之一,其ssh登录功能是旅行居家必备工具。
安装paramiko很简单,pipinstallparamiko就搞定了,其依赖库会被一并安装。
paramiko的官方站点在这里:http://www.paramiko.org/。有需要深入研究的可以阅读官方文档。
paramiko模块提供了ssh及sft进行远程登录服务器执行命令和上传下载文件的功能。
一、基于用户名和密码的sshclient方式登录
#建立一个sshclient对象 ssh=paramiko.SSHClient() #允许将信任的主机自动加入到host_allow列表,此方法必须放在connect方法的前面 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #调用connect方法连接服务器 ssh.connect(hostname='192.168.2.129',port=22,username='super',password='super') #执行命令 stdin,stdout,stderr=ssh.exec_command('df-hl') #结果放到stdout中,如果有错误将放到stderr中 print(stdout.read().decode()) #关闭连接 ssh.close()
二、基于用户名和密码的transport方式登录
方法1是传统的连接服务器、执行命令、关闭的一个操作,有时候需要登录上服务器执行多个操作,比如执行命令、上传/下载文件,方法1则无法实现,可以通过如下方式来操作
#实例化一个transport对象 trans=paramiko.Transport(('192.168.2.129',22)) #建立连接 trans.connect(username='super',password='super') #将sshclient的对象的transport指定为以上的trans ssh=paramiko.SSHClient() ssh._transport=trans #执行命令,和传统方法一样 stdin,stdout,stderr=ssh.exec_command('df-hl') print(stdout.read().decode()) #关闭连接 trans.close()
三、基于公钥密钥的SSHClient方式登录
#指定本地的RSA私钥文件,如果建立密钥对时设置的有密码,password为设定的密码,如无不用指定password参数 pkey=paramiko.RSAKey.from_private_key_file('/home/super/.ssh/id_rsa',password='12345') #建立连接 ssh=paramiko.SSHClient() ssh.connect(hostname='192.168.2.129', port=22, username='super', pkey=pkey) #执行命令 stdin,stdout,stderr=ssh.exec_command('df-hl') #结果放到stdout中,如果有错误将放到stderr中 print(stdout.read().decode()) #关闭连接 ssh.close()
以上需要确保被访问的服务器对应用户.ssh目录下有authorized_keys文件,也就是将服务器上生成的公钥文件保存为authorized_keys。并将私钥文件作为paramiko的登陆密钥
四、基于密钥的Transport方式登录
#指定本地的RSA私钥文件,如果建立密钥对时设置的有密码,password为设定的密码,如无不用指定password参数 pkey=paramiko.RSAKey.from_private_key_file('/home/super/.ssh/id_rsa',password='12345') #建立连接 trans=paramiko.Transport(('192.168.2.129',22)) trans.connect(username='super',pkey=pkey) #将sshclient的对象的transport指定为以上的trans ssh=paramiko.SSHClient() ssh._transport=trans #执行命令,和传统方法一样 stdin,stdout,stderr=ssh.exec_command('df-hl') print(stdout.read().decode()) #关闭连接 trans.close()
五、传文件SFTP
#实例化一个trans对象#实例化一个transport对象 trans=paramiko.Transport(('192.168.2.129',22)) #建立连接 trans.connect(username='super',password='super') #实例化一个sftp对象,指定连接的通道 sftp=paramiko.SFTPClient.from_transport(trans) #发送文件 sftp.put(localpath='/tmp/11.txt',remotepath='/tmp/22.txt') #下载文件 #sftp.get(remotepath,localpath) trans.close()
六、实现输入命令立马返回结果的功能
以上操作都是基本的连接,如果我们想实现一个类似xshell工具的功能,登录以后可以输入命令回车后就返回结果:
importparamiko importos importselect importsys #建立一个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的发送和接受信息的过程 whileTrue: readlist,writelist,errlist=select.select([channel,sys.stdin,],[],[]) #如果是用户输入命令了,sys.stdin发生变化 ifsys.stdininreadlist: #获取输入的内容 input_cmd=sys.stdin.read(1) #将命令发送给服务器 channel.sendall(input_cmd) #服务器返回了结果,channel通道接受到结果,发生变化select感知到 ifchannelinreadlist: #获取结果 result=channel.recv(1024) #断开连接后退出 iflen(result)==0: print("\r\n****EOF****\r\n") break #输出到屏幕 sys.stdout.write(result.decode()) sys.stdout.flush() #关闭通道 channel.close() #关闭链接 trans.close()
注意:在windows中,sys.stdin不是一个socket或者file-like对象,而是一个PseudoOutputFile对象,不能被select处理。所以上面的脚本不能在windows中运行,只能用于linux。
七、上例支持tab自动补全
importparamiko importos importselect importsys importtty importtermios ''' 实现一个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) whileTrue: readlist,writelist,errlist=select.select([channel,sys.stdin,],[],[]) #如果是用户输入命令了,sys.stdin发生变化 ifsys.stdininreadlist: #获取输入的内容,输入一个字符发送1个字符 input_cmd=sys.stdin.read(1) #将命令发送给服务器 channel.sendall(input_cmd) #服务器返回了结果,channel通道接受到结果,发生变化select感知到 ifchannelinreadlist: #获取结果 result=channel.recv(1024) #断开连接后退出 iflen(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()
八、SSH服务端的实现
实现SSH服务端必须继承ServerInterface,并实现里面相应的方法。具体代码如下:
importsocket importsys importthreading importparamiko host_key=paramiko.RSAKey(filename='private_key.key') classServer(paramiko.ServerInterface): def__init__(self): #执行start_server()方法首先会触发Event,如果返回成功,is_active返回True self.event=threading.Event() #当is_active返回True,进入到认证阶段 defcheck_auth_password(self,username,password): if(username=='root')and(password=='123456'): returnparamiko.AUTH_SUCCESSFUL returnparamiko.AUTH_FAILED #当认证成功,client会请求打开一个Channel defcheck_channel_request(self,kind,chanid): ifkind=='session': returnparamiko.OPEN_SUCCEEDED #命令行接收ip与port server=sys.argv[1] ssh_port=int(sys.argv[2]) #建立socket try: sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#TCPsocket sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) sock.bind((server,ssh_port)) sock.listen(100) print'[+]Listeningforconnection...' client,addr=sock.accept() exceptException,e: print'[-]Listenfailed:'+str(e) sys.exit(1) print'[+]Gotaconnection!' try: #用sock.accept()返回的socket实例化Transport bhSession=paramiko.Transport(client) #添加一个RSA密钥加密会话 bhSession.add_server_key(host_key) server=Server() try: #启动SSH服务端 bhSession.start_server(server=server) exceptparamiko.SSHException,x: print'[-]SSHnegotiationfailed' chan=bhSession.accept(20) print'[+]Authenticated!' printchan.recv(1024) chan.send("Welcometomyssh") whileTrue: try: command=raw_input("Entercommand:").strip("\n") ifcommand!='exit': chan.send(command) printchan.recv(1024)+'\n' else: chan.send('exit') print'exiting' bhSession.close() raiseException('exit') exceptKeyboardInterrupt: bhSession.close() exceptException,e: print'[-]Caughtexception:'+str(e) try: bhSession.close() except: pass sys.exit(1)
到此这篇关于python使用paramiko实现ssh的功能详解的文章就介绍到这了,更多相关pythonparamiko实现ssh内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。