背景

为了进一步完善自己写的小运维系统,今天就继续来补充一个批量执行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脚本:

anotherredis 批量执行命令 批量执行shell_python


审计:

anotherredis 批量执行命令 批量执行shell_django_02


目前实现批量执行shell脚本的思路与实现就是这个样子啦~要实现成什么样子就看大家怎么去做了。

(个人感觉这一个页面按钮太多了。。。但是更高级的技术或者实现技巧目前还不太会,只能慢慢改善吧,有大佬指点指点就更好拉~)

三、结束

好了,今天又实现一个小功能,只能说只是实现了哈,人性化或者隐藏bug多得很!!