Python实现ssh免密码登录+自定义命令操作服务器

如何实现免密码登录服务器

源代码
如果打不开请直接访问https://github.com/buzheng1949/Athena/tree/master/FreeServer

首先介绍脚本背景,我司查看服务器的时候,需要经过登录堡垒机,输入查看的服务器的IP地址,输入命令对服务器进行操作的流程,为此学习了Python之后,鼓捣了一个Python版本的免密码登录服务器的脚本

一、需求分析

  • 登录堡垒机
  • 登录服务器
  • 输入命令

二、方案选择

首先我们考虑的是Linux下是可以用expect进行ssh交互的,强大如Python当然也有这个能力,于是我们就自然想到了Python的pexpect库。
如果对pexpect库不熟悉的可以看下面的文章进行学习:pexpect学习教程

三、方案实现

  • 第一步,使用pexpect跟堡垒机打声招呼,以我司的登录堡垒机的命令为例子,ssh -pxxx username@server_ip,我们首先向服务器打声招呼。
    1
    child = pexpect.spawn('ssh -pxxxxx %s@%s'%(user_name,fortresses_ip))

得到服务器的回应后,对我进行了密码输入的请求,如下图:
输入密码图片

  • 第二步,okay,既然期待的是我输入密码,那么使用pexpect的另外一个大招,匹配返回的操作句柄,并进行密码发送。
    1
    2
    ret_login = child.expect(['%s@%s\'s password:'%(user_name,fortresses_ip),pexpect.TIMEOUT])
    child.sendline(password)

从上面的两行代码我们可以看到,第一行代码使用了pexpect的expect方法,表示上一步返回的内容中是否包含expect里面的列表的关键字。第二行代码表示包含到了我们设想的关键字之后,我们可以模拟发送密码给远端。

  • 第三步,发送完密码之后,我们已经实现了登录堡垒机的功能,如下图所示:
    登录堡垒机
    接下来就是输入我们需要登录的服务器的IP地址,然后再次输入密码,只需要调用两次pexpect的sendline方法即可完成服务器的交互。
1
2
3
4
5
6
7
8
ret_watch_server = child.expect([watch_server_ip,pexpect.TIMEOUT])
if ret_watch_server != 0:
print ('the password is correct,but the server ip maybe you have no perssion,please apply it')
return
else:
child.sendline(watch_server_ip)
child.expect('password')
child.sendline(password)
  • 第四步,但是即使进行免密码登录之后,我们还是很困扰,因为我们有两个问题还没解决,第一个问题是如何当我们想要登录查看的机器很多的时候,难道我每次都去改脚本的服务器的IP地址么?第二个问题是,难道我每次都需要去执行python xxx.py的方式去执行我们的脚本么?

    • 第一个问题的解决方式:我们可以使用docopt库进行在命令行执行Python命令的同时带上你想登录的服务器的IP地址。如下所示:
      server
      这样我们就可以在执行Python命令的时候,按照usage的方式输入然后解析watch_server_ip字段的方式进行自定义查看服务器而无需改脚本的方式。如下图所示,在入口进行简单的判断:
      server4
    • 第二个问题的解决方式:我们可以使用setuptools搞事情,代码如下所示:
      setup
      从上面我们可以看到,我们定义了一个脚本,自定义了一个命令叫freeserver,然后调用freeserver脚本的时候,调用脚本的main方法。
      编写完以上代码之后,我们执行python3 setup.py install 方法,就可以完成自定义命令行的方式输入而无需执行Python xxx.py xxxx_ip的麻烦的方式了。

    • 第五步,让我们来看看效果吧,虽然都打了马赛克,但是红红绿绿的可以看到我们的脚本确实成功了。
      success

果不其然的源代码分享

  • freeserver.py代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
"""免密码登录远端服务器
Usage:
freeserver <watch_server_ip>

Examples:
freeserver xxxxxxx
"""
import pexpect
import os
import getpass
from docopt import docopt
# 实现免密码登录方法
def login(fortresses_ip,user_name,password,watch_server_ip,command):
child = pexpect.spawn('ssh -pxxx %s@%s'%(user_name,fortresses_ip))
ret_login = child.expect(['%s@%s\'s password:'%(user_name,fortresses_ip),pexpect.TIMEOUT])
if ret_login == 1:
print ('login the remote server ip is timeout')
return
else:
child.sendline(password)
ret_password = child.expect(['This is a beta version. If you find bugs, please contact @Securit',pexpect.TIMEOUT])
if ret_password == 1:
print ('the password is wrong,please check the password')
return
else:
child.sendline('p')
ret_watch_server = child.expect([watch_server_ip,pexpect.TIMEOUT])
if ret_watch_server != 0:
print ('the password is correct,but the server ip maybe you have no perssion,please apply it')
return
else:
child.sendline(watch_server_ip)
child.expect('password')
child.sendline(password)
child.expect('Powered')
if command is not None:
child.sendline(command)
child.sendline('tailf web.log')
child.interact()

def main():
arguments = docopt(__doc__)
watch_server_ip = arguments.get('<watch_server_ip>')
user_name = 'your user name'
password = 'your password'
fortresses_ip = 'fortresses_ip'
command = 'your command when your want success enter the ip server'
login(fortresses_ip,user_name,password,watch_server_ip,command)

if __name__ == '__main__':
main()
  • setup.py
1
2
3
4
5
6
7
8
9
from setuptools import setup 
setup(
name='freeserver',
py_modules=['__inti__', 'freeserver'],
install_requires=['pexpect'],
entry_points={
'console_scripts': ['freeserver=freeserver:main']
}
)
坚持原创技术分享,您的支持将鼓励我继续创作!