Python实现Linux下SSh的无密码登录

之前做过的一点东西,取出一部分,做个回顾。

这个SSH的无密码登录只是其中一个基础的配置,因为不能都手动进行ssh无密码登录配置,所以想用Python写个脚本节约时间。可惜没想到自己造轮子,问题很多啊,当时也请教过其他人,但是我不想引入第三方库,于是自己找找资料,最后也解决了。

问题:SSH无密码登录需要进行什么配置?我看过一些介绍,说是首先生成私钥和公钥,比喻成钥匙和锁头,你要做的就是把钥匙踹自己兜里,把锁头发给其他机器,只要不换锁,想进入其他机器,直接套出钥匙开锁就OK了,直白点,其实就是调用ssh-keygen操作,当然密码设置为空,然后第二步是ssh-copy-id -i /root/.ssh/id_rsa.pub root@ip操作,一个是生成一个是分发,可以这么理解,太深入的原理,我也记不太清,有兴趣的自己查资料,大概原理是通过第二步的操作是把这个id_rsa.pub的内容写到了指定的机器,也是.ssh目录下authorized_keys里面,也就是说这个文件里面可以放很多不同的锁头,这样可以SSH登录无需输入密码了。。。

看起来很简单,过程也不复杂,就是两步,第一keygen,第二copy。。但是要写成代码,还是费了我不少脑细胞,因为没经验,就是凭着一腔热血,从零开始写。。

分析:keygen操作,在判定id_rsa文件不存在时,就是三次回车,第一次是让你指定生成的文件存储位置,回车就是默认指定在.ssh下,后面两次回车就是空密码的设置,因为ssh一开始就带了id_rsa文件,所以为了少交互一次,我们在执行keygen之前,执行一次rm操作,删除id_rsa;第二步是,copy操作,这个操作就要考虑是首次与指定ip的机器进行copy还是非首次,因为首次执行copy,会让你回答yes/no,仅仅多了这个提示而已,剩下的就是输入root登录密码

相关选择:第一步的keygen的rm操作,因为没有交互,所以用subprocess.call调用rm操作即可,keygen需要三次回车,所以pexpect.spawn(),然后用sendline('')重复三次就ok;第二步的copy,因为交互情况分两种,所以选用pexpect.spawn(),和expect来捕捉关键字,根据关键字提示不同,执行不同的操作,好了,贴代码

(PS:这个代码没有进行优化,写的很烂)

import subprocess
import os
import pexpect
import time
import sys
def ssh_set(slavehost,passwd):
        cmd1 = ['ssh-keygen']
        cmd = ['rm -rf /root/.ssh/id*']
        subprocess.call(''.join(cmd),shell=True)#delete the old id* of .ssh/
        print '######rm -rf /root/.ssh/id*#####'
        #ssh-keygen
        child = pexpect.spawn(''.join(cmd1))
        child.sendline('')
        time.sleep(0.1)
        child.sendline('')
        time.sleep(0.1)
        child.sendline('')
        time.sleep(0.1)
        print '###############ssh-keygen'
        #ssh-copy-id id_rsa.pub
        #passwd='123456'
        cmd2 = ['/usr/bin/ssh-copy-id -i /root/.ssh/id_rsa.pub root@']
        cmd2.append(slavehost)
        child = pexpect.spawn(''.join(cmd2))
        try:
                ret = child.expect(['password:','continue connecting (yes/no)?'],timeout=5)
                if ret == 0:
                        print ret
                        child.sendline(passwd)
                        print child.read()
                else:
                        print ret
                        child.sendline('yes')
                        child.expect('password:')
                        child.sendline(passwd)
                        print child.read()
                print '###############ssh-copyid  id_rsa.pub'
        except pexpect.EOF:
                print "EOF"
                child.close()
		sys.exit(0)
        except pexpect.TIMEOUT:
                print 'TIMEOUT'
                child.close()
		sys.exit(0)

这部分代码修改过,应该能用,因为原来的except信息的处理是调用另一个日志系统,在这里我给修改了,最后抛出异常打印错误信息,正常退出。当然这部分代码还只是个雏形,能跑而已,既不能看,也不能实际用,也就是说代码需要进一步优化下。。。

优化的代码我就不贴了,但是优化的几个点可以说下:1.subprocess.call的调用,要判断下返回值时候正确。2.keygen和copy操作的执行,有个顺序才行,也就是说keygen必须执行完了,才能copy,就是说进程等待完成了,再copy。3.可以进一步对参数中的slavehost进行下格式判断,因为不符合语法的ip输入,就没必要进行下面操作了。。

就说这么多,还有什么好的优化方式可以留言评论。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值