一、目的
从跳板机登录服务器是每次登录线上服务器都有的操作,如果每次都是手动ssh username@ip的形式就显得低效和繁琐,如果登录跳板机之后,自动执行一个命令,显示自己有登录权限的系统,选择系统后,就会列出该系统的所有节点ip,选择ip后就会自动登录到对应的机器就很方便了。带着这个想法就编写了本文的python脚本。
二、代码实施
2.1、python代码
文件名:smart_ssh,运行环境:python 2.7
#!/usr/bin/python
from optparse import OptionParser
import pexpect
import getpass
import requests
import json
def connect_to_server(ip):
if(ip == None):
return None
ssh_cmd = "ssh iwill@{}".format(ip)
child = pexpect.spawn(ssh_cmd)
child.interact()
def list_authorized_apps(username, part_app_name):
try:
url = "http://localhost:8080/cmdb/list-app?username=%s&app=%s" % (username ,part_app_name)
if part_app_name == None:
url = "http://localhost:8080/cmdb/list-app?username=%s" % (username)
resp = requests.get(url)
if(resp.status_code != 200):
print("request app list from cmdb fail !")
return None
resp_content = json.loads(resp.text)
if(resp_content['success'] =='true'):
result = resp_content['data']
return result
else:
print("request app list from cmdb fail !")
return None
except:
print("cmdb service is not available !")
return None
def list_authorized_ips(username, app_name):
if app_name == None:
return None
try:
url = "http://localhost:8080/cmdb/list-ip?username=%s&artifact_id=%s" % (username, app_name)
resp = requests.get(url)
if(resp.status_code != 200):
print("request server ip list from cmdb fail !")
return None
resp_content = json.loads(resp.text)
if(resp_content['success']=='true'):
result = resp_content['data']
return result
else:
print("request ip list from cmdb fail !")
return None
except:
print("cmdb service is not available !")
return None
def show_app_list(part_app_name, app_name_list):
if(app_name_list == None):
return None
print("all application like %s list below" %(part_app_name))
index = 0
for app_name in app_name_list:
print(" %d : %s " %(index ,app_name))
index = index + 1
show_msg = 'please select app (0...%d) : '%(index-1)
try:
app_index = input(show_msg)
if(app_index < 0 or app_index > index):
print("you input wrong number ! ")
return None
selected_app = app_name_list[app_index]
return selected_app
except:
print("you input wrong number ! ")
return None
def show_ip_list(app_name, app_ip_list):
if(app_ip_list == None):
return None
print("all ips of the application %s list below" %(app_name))
index = 0
for app_ip in app_ip_list:
index = index + 1
print(" %d : %s " %(index ,app_ip))
show_msg = 'please select ip (1...%d) : '%index
try:
id_index = input(show_msg)
if(id_index <= 0 or id_index > index):
print("you input wrong number ! ")
return None
selected_ip = app_ip_list[id_index-1]
return selected_ip
except:
print("you input wrong number ! ")
return None
def main():
parser = OptionParser()
parser.add_option('-a', '--app', dest='app', action='store', type='string', help='the application id in the auv')
(options, args) = parser.parse_args()
username = getpass.getuser()
app_name_list = list_authorized_apps(username, options.app)
if app_name_list == None:
exit()
elif (len(app_name_list) == 0 and options.app == None):
print("you are not authorized to any app ,use jumper directly")
exit()
elif len(app_name_list) == 0 :
print("no app name like %s, use jumper directly" %(options.app))
exit()
elif (len(app_name_list) == 1 and app_name_list[0] == options.app):
app_ip_list = list_authorized_ips(username, options.app)
selected_ip = show_ip_list(options.app, app_ip_list)
connect_to_server(selected_ip)
else :
jumper_name = 'no thanks ,I will use jumper'
app_name_list.insert(0,jumper_name)
selected_app = show_app_list(options.app, app_name_list)
if(selected_app == jumper_name) :
exit()
app_ip_list = list_authorized_ips(username, selected_app)
selected_ip = show_ip_list(selected_app, app_ip_list)
connect_to_server(selected_ip)
exit()
if __name__== '__main__':
main()
2.2、mock的cmdb接口代码
@RestController
@RequestMapping("cmdb")
public class CmdbController {
@GetMapping("list-app")
public String listApp(@RequestParam(value = "username") String username, @RequestParam(value = "app", required = false) String app) {
Result result = new Result("true");
List partApps = new ArrayList<>();
partApps.add("axx-app");
partApps.add("bxx-app");
partApps.add("cxx-app");
result.setData(partApps);
return new Gson().toJson(result);
}
@GetMapping("list-ip")
public String listIp(@RequestParam(value = "username") String username, @RequestParam(value = "artifact_id", required = false) String artifact_id) {
Result result = new Result("true");
List ips = new ArrayList<>();
ips.add("192.168.0.101");
ips.add("192.168.0.102");
ips.add("192.168.0.103");
result.setData(ips);
return new Gson().toJson(result);
}
}
2.3、原理
程序会和cmdb交互两次,第一次交互去获取有登录权限的应用列表或者部分应用列表;第二次会去获取指定应用的ip列表,当用户选择了指定ip后,就会使用pexpect连接到对应的机器。
2.3、系统命令制作
将文件smart_ssh放到/usr/local/bin下,然后suorce一下/etc/profile,在命令行就可以运行smart_ssh了
2.4、用法
2.4.1、不带参数
直接使用smart_ssh时,会列举出当前登录用户所有有登录权限的应用列表,用户选择一个应用后,会列举出该应用的所有ip,用户选择一个ip后,程序就会自动登录到对应的机器。
2.4.2、带参数,模糊匹配
使用smart_ssh -a part_app_name,会列举出当前登录用户所有有登录权限且应用名模糊匹配part_app_name的应用列表,用户选择一个应用后,会列举出该应用的所有ip,用户选择一个ip后,程序就会自动登录到对应的机器。
2.4.3、完全匹配
使用smart_ssh -a app_name,会列举出当前登录用户所有有登录权限且应用名匹配app_name的应用列表进行校验,然后会直接列举出应用的所有ip,用户选择一个ip后,程序就会自动登录到对应的机器。
2.4、运行效果
三、感想
1、工作中,有很多可以挺高工作效率的方法,其中完备的工具就是其中之一。
2、很多事情,不是看到了希望才去做,而是做了才有希望。