Python paramiko 模块浅谈与SSH主要功能模拟解析
疫情还没结束,小编只能宅在家里,哪哪也去不了,今天突发奇想给大家分享一篇教程关于Pythonparamiko模块浅谈与SSH主要功能模拟解析。
大家都知道,通过SSH服务可以远程连接到Linux服务器,查看上面的日志状态,批量配置远程服务器,文件上传,文件下载等,Python的paramiko模块同样实现了这一功能。
首先我们需要安装这一模块,pycharm环境中如下操作
一,安装paramiko模块
PyCharm→Preferences→Project:项目名→ProjectInterpreter
点击箭头所指加号,在搜索框输入选中,并安装
完成后会在ProjectInterpreter中显示,如上上图
二,基于用户名和密码的sshclient方式登录
importparamiko #创建SSH对象 ssh=paramiko.SSHClient() #允许连接不在know_hosts文件中的主机 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #连接服务器 ssh.connect(hostname='192.168.199.146',port=22,username='fishman',password='9') #执行命令 stdin,stdout,stderr=ssh.exec_command('df') #获取命令结果 res,err=stdout.read(),stderr.read() result=resifreselseerr print(result.decode()) #关闭连接 ssh.close()
解析:首先导入模块,然后创建一个SSH对象,然后通过命令连接远程机器,默认端口是22,这里我连接的是192.168.199.146的机器,密码为9,然后执行df命令,获取返回的结果如下
我们可以比较一下通过SSH得到的结果
三,基于用户名和密码的transport方式登录
基于SSHClient是传统的连接服务器、执行命令、关闭的一个操作,有时候需要登录上服务器执行多个操作,比如执行命令、上传/下载文件,上面方法则无法实现,可以通过如下方式来操作
#SSHClient封装Transport importparamiko #实例化一个transport对象 transport=paramiko.Transport(('192.168.199.146',22)) #建立连接 transport.connect(username='fishman',password='9') #将sshclient的对象的transport指定为以上的transport ssh=paramiko.SSHClient() ssh._transport=transport #执行命令,和传统方法一样 stdin,stdout,stderr=ssh.exec_command('df') print(stdout.read().decode()) #关闭连接 transport.close()
四,基于公钥密钥连接
4.1SSH配置免密登陆
我们知道通过配置公钥密钥,可以实现SSH的免密登陆,比如现在连接fishman机器会提示我们输入密码,然后才能登陆
通过SSH原理与运用中介绍,我们知道,要实现免密公钥登陆,需要将我们自己机器的公钥存储在要登陆的远程主机上。登录的时候,远程主机会向用户发送一段随机字符串,用户用自己的私钥加密后,再发回来。远程主机用事先储存的公钥进行解密,如果成功,就证明用户是可信的,直接允许登录shell,不再要求密码。
首先我们生成自己的公钥通过命令ssh-keygen,这里会提示这个公钥保存的文件路径,默认即可然后回车,这里由于我本地已经有生成的公钥,所以提示是否要覆盖,我这里就不重写了,如果本地没有生成过继续回车,提示要不要对私钥设置口令(passphrase),如果担心私钥的安全,这里可以设置一个。默认也可以直接回车
得到公钥后一种方法是通过命令将公钥直接传到远程机器ssh-copy-iduser@host,如我们登陆的机器:
ssh-copy-idfishman@192.168.199.146
另一种方法是进入公钥文件去复制,进入.ssh/id_rsa.pub通过more或者cat复制公钥
~more.ssh/id_rsa.pubssh-rsaAAAAB3NzaC1yc2EAAAADAQABAAABAQCyQ2GtkbKcFAP/kX/+65e91Q8EJ+twpyqjEBzlVmZ2mxy8Zw7b/AfeV60ehloCq7p521IGJaXWbr3bky7Jljc6x7cAZsRW7mZRPFelPYa5iJ4lIshU3RwhbTYW6RyrG+InF3ognJ7bggpPmJbWFxqqpZwdkEilpnv0+8b17frSbF1xaQQh57vDjG78xr0pys2MBzylqrs1RNiTcRz86zJT7SbujYY/bpiUB78w46CmRlwzHOk8Zg0hcegqSMHjboQyhkSX0xcFv2ZLHm5Gpfba3863M+62Q1r2U+QW5Ki1f3nsGwHWQIRuHNWldUzWKYRPsKJHVvwFwkYDG3sZZMWRljf@meijiabaodeiMac.lan~cat.ssh/id_rsa.pubssh-rsaAAAAB3NzaC1yc2EAAAADAQABAAABAQCyQ2GtkbKcFAP/kX/+65e91Q8EJ+twpyqjEBzlVmZ2mxy8Zw7b/AfeV60ehloCq7p521IGJaXWbr3bky7Jljc6x7cAZsRW7mZRPFelPYa5iJ4lIshU3RwhbTYW6RyrG+InF3ognJ7bggpPmJbWFxqqpZwdkEilpnv0+8b17frSbF1xaQQh57vDjG78xr0pys2MBzylqrs1RNiTcRz86zJT7SbujYY/bpiUB78w46CmRlwzHOk8Zg0hcegqSMHjboQyhkSX0xcFv2ZLHm5Gpfba3863M+62Q1r2U+QW5Ki1f3nsGwHWQIRuHNWldUzWKYRPsKJHVvwFwkYDG3sZZMWRljf@meijiabaodeiMac.lan~
复制后,我们登陆远程机器,在目录下.ssh文件夹中发现有以下文件,其中id_rasid_ras.pub保存该机器的公钥私钥,
know_hosts:ssh会把你每个你访问过计算机的公钥(publickey)都记录在~/.ssh/known_hosts。当下次访问相同计算机时,OpenSSH会核对公钥。如果公钥不同,OpenSSH会发出警告,避免你受到DNSHijack之类的攻击。
我们需要将刚才复制的我的公钥保存到authorized_keys文件中
通过vi打开编辑然后粘贴退出保存
此时,我们退出登陆,然后重新登陆,发现就不需要输入登陆密码了,可以实现免密登陆,美滋滋。
另外我们要注意,.ssh目录的权限为700,其下文件authorized_keys和私钥的权限为600。否则会因为权限问题导致无法免密码登录
另外,将公钥拷贝到服务器的~/.ssh/authorized_keys文件中方法有如下几种:
1、将公钥通过scp拷贝到服务器上,然后追加到~/.ssh/authorized_keys文件中,这种方式比较麻烦。scp-P22~/.ssh/id_rsa.pubuser@host:~/。
2、通过ssh-copy-id命令最简单,也是第一种方法,ssh-copy-id"-p22user@host"即可,有时候user@host需要加引号,前面写-p端口号
3、可以通过cat~/.ssh/id_rsa.pub|ssh-p22user@host‘cat>>~/.ssh/authorized_keys',这个也是比较常用的方法,因为可以更改端口号。
4.2基于公钥密钥的SSHClient方式登录
进入路径查看我本地id_rsa文件路径
importparamiko private_key=paramiko.RSAKey.from_private_key_file('/Users/ljf/.ssh/id_rsa') #创建SSH对象 ssh=paramiko.SSHClient() #允许连接不在know_hosts文件中的主机 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #连接服务器 ssh.connect(hostname='192.168.199.146',port=22,username='fishman',pkey=private_key) #执行命令 stdin,stdout,stderr=ssh.exec_command('df') #获取命令结果 res,err=stdout.read(),stderr.read() result=resifreselseerr print(result.decode()) #关闭连接 ssh.close()
同理。可以用transport封装
importparamiko private_key=paramiko.RSAKey.from_private_key_file('/Users/ljf/.ssh/id_rsa') #实例化一个transport对象 transport=paramiko.Transport(('192.168.199.146',22)) #建立连接 transport.connect(username='fishman',pkey=private_key) ssh=paramiko.SSHClient() ssh._transport=transport stdin,stdout,stderr=ssh.exec_command('df') #获取命令结果 res,err=stdout.read(),stderr.read() result=resifreselseerr print(result.decode()) #关闭连接 ssh.close()
同理,可以直接根据私钥字符串连接,首先在本地获取私钥字符串
➜.sshcatid_rsa-----BEGINRSAPRIVATEKEY-----MIIEowIBAAKCAQEAskNhrZGynBQD/5F//uuXvdUPBCfrcKcqoxAc5VZmdpscvGcO2/wH3letHoZaAqu6edtSBiWl1m6925MuyZY3Ose3AGbEVu5mUTxXpT2GuYieJSLIVN0cIW02FukcqxviJxd6IJye24IKT5iW1hcaqqWcHZBIpaZ79PvG9e360mxdcWkEIee7w4xu/Ma9KcrNjAc8paq7NUTYk3Ec/OsyU+0m7o2GP26YlAe/MOOgpkZcMxzpPGYNIXHoKkjB426EMoZEl9MXBb9mSx5uRqX22t/OtzPutkNa9lPkFuSotX957BsB1kCEbhzVpXVM1imET7CiR1b8BcJGAxt7GWTFkQIDAQABAoIBAH54j7Q0yiMxkCShdc3GF8H2htDMAZ3K+9T0eYu74LYFFj4UX9Zy2KJGUex2JSX/8CzEDU2PKDkaGFjP80HR8R0i1BLU1jdWrAC2bvgszoiTBKAULU0IEg0lDlryyAQdpDVX0q2QcKQLfoU6HMmHWsP2+ut+kgv0Mb19Y4rXbDwctmx53BJ0Ykk3RaQe8FiLOAAdFzxbGIUdIwLhN8PEh9HW/wMFvJVEAgNu3oD0bONH+PZKasxqnOQlHrILSPQrNiXBOxCYr9u8cFx7hl1V0yhQHnCF+JK2se6VXQnJ1pUVtWc3kRTtwas3x7IRPdNJDbj8WT6/n6ocUm+QOgEY9gECgYEA3CtYVABizz8GsHpged/xDkOKf9gET5m1kX/awdd3m6lkoWboB5OLym6YwxWpl6Fs0XHRAih3w2434MyTxqdgZf5ixMgq00PBr7itGycokLm1KO1GFjbZ4tog3qwX6vejHsDl+TMWojxmkEjwQ1uPcQOeY96CvOafHH+kP5zmfAUCgYEAz0Ym1y07sSfiKSDEO+99r7deex8fssk/xcFI3PgD/4zwu0zGF3QIB124cbZX6Sy6ut0djzX+RQm5OGUNR1m4Qg1syeNIEF/2mV0rL7+qPGIpYIsuoeuBwedNj7qTIDx4wKtmaJcwdErEQwRJ7UOX9KEdPkKivyf4A+uT5fCsJR0CgYBE7tFF46UMLDiE8pvYLLRFegIYCuM2pPKDLpuoSzToqL2YBycokBqZc80ib1rc3a67WL5OxarRpmWaXZL7BJaa+G2mHOHDqZgv00tnj/gUcAB3Yuqps9y+OPtHnGwUphoNW+nk/wjcHLsj+6I2BKnBgZeKvzUBvdcdTh13yUEknQKBgHBkmNEbPP/+IXutwdrCLYQnyXq30Mdwqzz/ZxQzBHABK9RUeCHlkCj2X/qBJsBQudxz5ABxBbTH5gC3gvDKrMhcYT5EGSKP9rcIt09H/faKP+eS8TFp882CMCOcxwS25b+L8ZcLTIHyvOOeIrweZ/qFlsbY+UjwUmNFzcfkrmPdAoGBAJ9NWhf16aLQxUrPkUvHK9k7ONUadamBxA6NNvHMZxow81/p9VQK71o7iUdJmC/+VOvGqbA3AbtqkbjBMUWGjEeVKLxMnCZngfu9J6bnWDUaYbQz3gVY63caKFWjRXO6GtynW0Dec0Nj/q22V5J+2ZCkIvSAQ+cI04d0Ij7RdKPl-----ENDRSAPRIVATEKEY-----➜.ssh
#!/usr/bin/envpython#-*-coding:utf-8-*-#基于私钥字符串进行连接importparamikofromioimportStringIOkey_str="""-----BEGINRSAPRIVATEKEY-----MIIEowIBAAKCAQEAskNhrZGynBQD/5F//uuXvdUPBCfrcKcqoxAc5VZmdpscvGcO2/wH3letHoZaAqu6edtSBiWl1m6925MuyZY3Ose3AGbEVu5mUTxXpT2GuYieJSLIVN0cIW02FukcqxviJxd6IJye24IKT5iW1hcaqqWcHZBIpaZ79PvG9e360mxdcWkEIee7w4xu/Ma9KcrNjAc8paq7NUTYk3Ec/OsyU+0m7o2GP26YlAe/MOOgpkZcMxzpPGYNIXHoKkjB426EMoZEl9MXBb9mSx5uRqX22t/OtzPutkNa9lPkFuSotX957BsB1kCEbhzVpXVM1imET7CiR1b8BcJGAxt7GWTFkQIDAQABAoIBAH54j7Q0yiMxkCShdc3GF8H2htDMAZ3K+9T0eYu74LYFFj4UX9Zy2KJGUex2JSX/8CzEDU2PKDkaGFjP80HR8R0i1BLU1jdWrAC2bvgszoiTBKAULU0IEg0lDlryyAQdpDVX0q2QcKQLfoU6HMmHWsP2+ut+kgv0Mb19Y4rXbDwctmx53BJ0Ykk3RaQe8FiLOAAdFzxbGIUdIwLhN8PEh9HW/wMFvJVEAgNu3oD0bONH+PZKasxqnOQlHrILSPQrNiXBOxCYr9u8cFx7hl1V0yhQHnCF+JK2se6VXQnJ1pUVtWc3kRTtwas3x7IRPdNJDbj8WT6/n6ocUm+QOgEY9gECgYEA3CtYVABizz8GsHpged/xDkOKf9gET5m1kX/awdd3m6lkoWboB5OLym6YwxWpl6Fs0XHRAih3w2434MyTxqdgZf5ixMgq00PBr7itGycokLm1KO1GFjbZ4tog3qwX6vejHsDl+TMWojxmkEjwQ1uPcQOeY96CvOafHH+kP5zmfAUCgYEAz0Ym1y07sSfiKSDEO+99r7deex8fssk/xcFI3PgD/4zwu0zGF3QIB124cbZX6Sy6ut0djzX+RQm5OGUNR1m4Qg1syeNIEF/2mV0rL7+qPGIpYIsuoeuBwedNj7qTIDx4wKtmaJcwdErEQwRJ7UOX9KEdPkKivyf4A+uT5fCsJR0CgYBE7tFF46UMLDiE8pvYLLRFegIYCuM2pPKDLpuoSzToqL2YBycokBqZc80ib1rc3a67WL5OxarRpmWaXZL7BJaa+G2mHOHDqZgv00tnj/gUcAB3Yuqps9y+OPtHnGwUphoNW+nk/wjcHLsj+6I2BKnBgZeKvzUBvdcdTh13yUEknQKBgHBkmNEbPP/+IXutwdrCLYQnyXq30Mdwqzz/ZxQzBHABK9RUeCHlkCj2X/qBJsBQudxz5ABxBbTH5gC3gvDKrMhcYT5EGSKP9rcIt09H/faKP+eS8TFp882CMCOcxwS25b+L8ZcLTIHyvOOeIrweZ/qFlsbY+UjwUmNFzcfkrmPdAoGBAJ9NWhf16aLQxUrPkUvHK9k7ONUadamBxA6NNvHMZxow81/p9VQK71o7iUdJmC/+VOvGqbA3AbtqkbjBMUWGjEeVKLxMnCZngfu9J6bnWDUaYbQz3gVY63caKFWjRXO6GtynW0Dec0Nj/q22V5J+2ZCkIvSAQ+cI04d0Ij7RdKPl-----ENDRSAPRIVATEKEY-----"""private_key=paramiko.RSAKey(file_obj=StringIO(key_str))transport=paramiko.Transport(('192.168.199.146',22))transport.connect(username='fishman',pkey=private_key)ssh=paramiko.SSHClient()ssh._transport=transportstdin,stdout,stderr=ssh.exec_command('df')res,err=stdout.read(),stderr.read()result=resifreselseerrprint(result.decode())#关闭连接ssh.close()
以上得到的结果都相同
这里需要注意,如果你是Linux及OSX系统,那么自带SSH,以上操作都没问题,如果你是Windows,那么通过Xsheel也可以生成一个,通过Xsheel--》工具--》新建用户秘钥生成向导,
如果没有装Xsheel,可以将Linux的公钥copy过来,这样在这里可以读取本地存的公钥信息
通过命令sz~/.ssh/id_rsa,将公钥保存为一个txt文件,paramiko.RSAKey.from_private_key_file(公钥文件)
五,SFTPClient用于连接远程服务器并执行上传下载
我们计划将本地LocalFile.txt上传到fishman机器的test路径下remote.txt,这是该路径下原来的文件,其中remote.txt为空,没有内容,通过sftp.put('LocalFile.txt','/home/fishman/test/remote.txt')即可上传
基于用户名密码上传下载
importparamiko #实例化一个trans对象#实例化一个transport对象 transport=paramiko.Transport(('192.168.199.146',22)) #建立连接 transport.connect(username='fishman',password='9') #实例化一个sftp对象,指定连接的通道 sftp=paramiko.SFTPClient.from_transport(transport) #LocalFile.txt上传至服务器/home/fishman/test/remote.txt #sftp.put('LocalFile.txt','/home/fishman/test/remote.txt') #将LinuxFile.txt下载到本地fromlinux.txt文件中 sftp.get('/home/fishman/test/LinuxFile.txt','fromlinux.txt') transport.close()
同理,我们可以下载远程机器上test路径下的LinuxFile.txt文件到本地fromLinux.txt
基于公钥密钥上传下载
importparamiko private_key=paramiko.RSAKey.from_private_key_file('/Users/ljf/.ssh/id_rsa') transport=paramiko.Transport(('192.168.199.146',22)) transport.connect(username='fishman',password='9') sftp=paramiko.SFTPClient.from_transport(transport) #LocalFile.txt上传至服务器/home/fishman/test/remote.txt #sftp.put('LocalFile.txt','/home/fishman/test/remote.txt') #将LinuxFile.txt下载到本地fromlinux.txt文件中 sftp.get('/home/fishman/test/LinuxFile.txt','fromlinux.txt') transport.close()
5实现输入命令立马返回结果的功能以上操作都是基本的连接,如果我们想实现一个类似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()
6支持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()
到此这篇关于Pythonparamiko模块详解与SSH主要功能模拟的文章就介绍到这了,更多相关Pythonparamiko模块与SSH内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。