背景
为了进一步完善自己写的小运维系统,今天就继续来补充一个批量执行shell脚本,并记录操作用于审计!
一、思路
实现批量执行shell脚本刚开始的思路是,获取本地脚本的路径,用Paramiko上传脚本,给权限,执行,反馈结果。但是没过一会就醒悟,呀,这不符合一个系统的思路阿!这不是脚本呀!所以需要将本地的脚本上传到系统地址,再上传到服务器进行执行才对!
那么思路就明确啦
1.当建立websocket与ssh连接后,上传脚本到系统
2.由系统上传脚本导服务器
3.给脚本权限并执行脚本
4.反馈脚本信息
二、实现
1.当建立websocket与ssh连接后,上传脚本到系统
一开始是想既然建立了websocket连接了,直接用websocket上传文件就好啦,无奈测试了几遍都没达到效果,估计是我这才刚开始用websocket吧。下面是上传文件的实现的核心:
html:
<!--选择文件-->
<label class="form-inline">执行的shell脚本:
<input id="myfile" type="file" accept=".sh" style="display: none" multiple>
<!--显示上传的文件名字-->
<input type="text" id="showfilename" class="form-control" value="点击选择脚本" readonly="true" onclick="$('input[id=myfile]').click();">
<button class="btn btn-primary " type="button" id="shangchuan" >上传</button>
<button class="btn btn-success " type="button" id="sendbashscrip">执行</button><br>
(先上传脚本,再执行脚本;<br>上传后将脚本上传到/usr/目录,脚本命名为:名字+上传时间;<br>
自动给予脚本755权限;)
</label>
js:
$('input[id=myfile]').change(function () {
var myfiles = document.getElementById("myfile").files;
var filename = "";
filename = myfiles.name;
$('#showfilename').val(filename);
})
function Upload(){
var myfiles = document.getElementById("myfile").files;
var data = new FormData();
data.append('file', myfiles);
$.ajax({
type: "POST",
url: "{% url 'Upload' %}",
data: data,
processData: false,
contentType: false,
dataType:"json",
success: function(result){
}
});
}
上传逻辑函数:
@csrf_exempt
def Upload(req):
global file_name
file = req.FILES.get('file')
nowtime = time.strftime("%Y%m%d%H%M%S")
uploadshellpath = settings.BASE_DIR + '/static/batchshellscript/'
if not os.path.exists(uploadshellpath):
os.makedirs(uploadshellpath)
if file:
file_name = nowtime+file.name
shellwrite= open(uploadshellpath+file_name, 'wb+')
for chunk in file.chunks():
shellwrite.write(chunk)
shellwrite.close()
file_path = uploadshellpath + file_name
json_data = {}
response_data['filename'] = file_name
response_data['path'] = file_path
json_data = json.dumps(response_data)
return HttpResponse(json_data)
批量处理脚本逻辑函数:
在昨天batch函数的基础上修改这部分逻辑:
for shell in request.websocket:
if shell.decode('utf-8') == 'sendbatchscript':
addactionshell = models.batchaction()
addactionshell.hostaddress = hostip
addactionshell.username = request.session['username']
addactionshell.actionshell = 'acction:' + globals()['file_name']
addactionshell.starttime = time.strftime("%Y%m%d%H%M%S")
addactionshell.save()
for i in range(hostnum):
try :
e[i].put(settings.BASE_DIR + r'/static/batchshellscript/'+globals()['file_name'],r'/usr/'+globals()['file_name'])
cmd = 'cd /usr;chmod 755 '+ globals()['file_name']+';' + './' + globals()['file_name']
b[i], c[i], d[i] = a[i].exec_command(cmd) # num个对象执行e命令
output = '-' * 97 + f'{hostip[i]}执行结果' + '-' * 90 + c[i].read().decode('utf-8') + d[i].read().decode('utf-8')
request.websocket.send(output.encode('utf-8'))
except:
print('脚本执行失败')
shellscrpmess = '-' * 97 + f'{hostip[i]}执行结果' + '-' * 94 +'执行失败!'
request.websocket.send(shellscrpmess.encode('utf-8'))
else:
addactionshell = models.batchaction()
addactionshell.hostaddress = hostip
addactionshell.username = request.session['username']
addactionshell.actionshell = shell.decode('utf-8')
addactionshell.starttime = time.strftime("%Y%m%d%H%M%S")
addactionshell.save()
for i in range(hostnum):
b[i], c[i], d[i] = a[i].exec_command(shell) # num个对象执行e命令
# print(f'----------------------{hostip[i]}执行结果----------------------')
# print(c[i].read().decode('utf-8')) # 打印正确输出
# print(d[i].read().decode('utf-8')) # 打印错误输出
output = '-'*97 + f'{hostip[i]}执行结果' + '-'*90 + c[i].read().decode('utf-8') + d[i].read().decode('utf-8')
request.websocket.send(output.encode('utf-8'))
效果:
执行一个helloword脚本:
审计:
目前实现批量执行shell脚本的思路与实现就是这个样子啦~要实现成什么样子就看大家怎么去做了。
(个人感觉这一个页面按钮太多了。。。但是更高级的技术或者实现技巧目前还不太会,只能慢慢改善吧,有大佬指点指点就更好拉~)
三、结束
好了,今天又实现一个小功能,只能说只是实现了哈,人性化或者隐藏bug多得很!!