之前做过的一点东西,取出一部分,做个回顾。
这个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输入,就没必要进行下面操作了。。
就说这么多,还有什么好的优化方式可以留言评论。。。