背景介绍:
实现如上图所示的,页面一键控制服务器IISRESET
服务器上部署了EnvAgency这个Service来接受请求并处理以及返回,但是IISRESET这个请求特殊,因为IISRESET后会重启程序池,包括EnvAgency程序,就不能返回IISRESET请求的具体结果,但是IISRESET的单次成功率不高,又后果失败影响大,所以必须保证IISRESET的成功。试过很多中方法,具体尝试方法记录于http://4453154.blog.51cto.com/4443154/1689318,某些情况下,这些方法是可行的。但是我这边由于严格的域帐号机器帐号控制导致不可行。所以换了如下方法:
环境系统调用服务器上代理,代理触发服务器上IISRESET的应用,该应用会启动iisreset并且读取返回,如果返回是正确的,就退出,否则继续调用iisreset,这样就确保多次后iis启动成功。由于IISRESET应用是写成Console程序,不受IIS程序池影响。并且加入Nlog来记录相应信息,方便出问题后排查。
在判断iis启动成功方面:采用循环5秒请求下服务器时间,看服务器是否有反应来判断启动是否成功。
应用存放目录:
D:\\websites\\EnvCmd\\cmdtest
IISRESET的应用配置具体代码如下:
using NLog; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; namespace cmdtest { public class ProcessUtil { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); public static bool IISReset() { Logger.Info("Start IISRESET"); int flag = 0; string output = IISResetProcess(); Logger.Info(output); string regx = "正在尝试停止...\r\r\nInternet 服务已成功停止\r\r\n正在尝试启动...\r\r\nInternet 服务已成功启动"; while (flag < 10 && !output.Contains(regx)) { output = IISResetProcess(); Logger.Info(output); flag++; } bool result = output.Contains(regx); Logger.Info("Finish IISRESET - result : " + result); return result; } public static string IISResetProcess() { Process pro = new Process(); // 设置命令行、参数 pro.StartInfo.FileName = "cmd.exe"; pro.StartInfo.UseShellExecute = false; pro.StartInfo.RedirectStandardInput = true; pro.StartInfo.RedirectStandardOutput = true; pro.StartInfo.RedirectStandardError = true; pro.StartInfo.CreateNoWindow = true; // 启动CMD pro.Start(); // 运行端口检查命令 pro.StandardInput.WriteLine("iisreset"); pro.StandardInput.WriteLine("exit"); return pro.StandardOutput.ReadToEnd(); } } }
using NLog; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; namespace cmdtest { class Program { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); static void Main(string[] args) { Logger.Info("test"); Console.WriteLine(ProcessUtil.IISReset()); } } }
服务器代理EvnAgency中IISReset调用如下:
public JsonResult IISReset(PostPackBase pack) { var resp = new APIResponse<string>() { StateCode = StateCode.Success, Message = "" }; var accessToken = LoginSecurity.DecodeAccessToken(pack.Token); if (accessToken == null) { resp.StateCode = StateCode.Fail; resp.Message = "操作用户无法识别!"; } else if (accessToken.ExpiredTime < DateTime.Now) { resp.StateCode = StateCode.Fail; resp.Message = "登陆信息过期!"; } else { try { var token = LoginSecurity.DecodeAccessToken(pack.Token); EnvMachine envmachine = EnvMachineBiz.GetCurrentMachine(); string ip = envmachine.IP; Logger.Info("IISReset start by " + token.Alias + " on " + ip); string str = string.Format("{0} Reset IIS on {1} ", token.Alias, ip) ; EnvOperationLogBiz.LogOptIISReset(envmachine.EnvSubId, token.Alias, str, envmachine.Id); IISUtil.IISReset(); } catch (Exception ex) { resp.StateCode = StateCode.Fail; resp.Message += ex.ToString(); Logger.ErrorException("IISReset status result : Exception, " + ex.ToString(), ex); } } return Json(resp, JsonRequestBehavior.DenyGet); }
具体调用应用程序代码如下:
public static void IISReset() { Logger.Info("Start D:\\websites\\EnvCmd\\cmdtest"); Process.Start("D:\\websites\\EnvCmd\\cmdtest"); }
环境管理系统中前端代码如下:
html代码如下
<li><a onclick="javascript: pageui.render(‘iisreset‘)">IIS Reset</a></li>
js代码如下
////// 主页面 ////// pageui = { render: function (pageType) { var page; if (pageType == ‘iisreset‘) { page = iisresetpage; } page.render(); } }; var iisresetpage = { render: function () { var container = $(pageid.mainContent); container.empty(); chcoreui.attachLoader(container, pageid.loader, 410, 100); var url = ‘/IIS/GetAllMachines‘; var pack = new Object(); pack.Token = $.readCookie(‘accessToken‘); var submitData = JSON.stringify(pack); $.ajax({ type: "POST", url: url, data: submitData, dataType: "json", contentType: "application/json", crossDomain: true, success: function (results) { if (results.StateCode == 0) { // 成功 var bodyContent = ‘‘; $.each(results.Data, function (idx, item) { bodyContent += ‘<tr><td style="text-align:center;"><button class="link iisresetbtn"><i class="icon-play"></i></button></td><td>‘ + item.MachineName + ‘</td><td>‘ + item.IPAddress + ‘</td><td style="text-align:center;">‘ + item.DomainName + ‘</td><td><button class="link logbtn"><span class="mif-loop2"></span>日志</button></td></tr>‘; }); container.empty(); container.html(‘<table class="table bordered striped hovered dataTable" cellspacing="0" id="apppooltable"><thead><tr><th><button class="resetallbtn warning"><i class="icon-play on-left"></i>重启IIS</button></th><th>机器名</th><th>IP地址</th><th>环境名称</th><th>Actions</th></tr></thead><tbody>‘ + bodyContent + ‘</tbody></table>‘); $(‘#apppooltable‘).dataTable({ "paging": false, "searching": true, "ordering": true, "info": "程序池信息表", // "scrollY": "450px", "scrollCollapse": true, "dom": ‘<"tool1bar">fr1tip‘ }); $(".iisresetbtn").click(function () { iisresetpage.startReset($(this)); }); $(".resetallbtn").click(function () { if (!$(this).hasClass(‘disabled‘)) { var syncbtns = $(‘.iisresetbtn‘); $(this).addClass(‘disabled‘); $.each(syncbtns, function (idx, item) { item.click(); }); } }); $(".logbtn").click(function () { iisresetpage.getResetLog($(this)); }); } }, error: function (xhr, status, error) { $.note(‘Error‘, ‘获取程序池信息失败,请联系管理员.‘, ‘error‘); } }); }, startReset: function (sender) { var parentObj = sender.parent(); var ip = parentObj.next().next().text(); iisresetpage.postReset(ip, sender); }, postReset:function(ip,sender) { var parentObj = sender.parent(); parentObj.empty(); parentObj.append(‘<img src="../img/loading.jpg" style="width:30px;" id="iloader" />‘); commonajax.postIISReset(ip); var flag = 0; iisresetpage.checkPostResult(ip, parentObj,flag); }, checkPostResult: function (ip, parentObj, flag) { setTimeout( function () { var result = commonajax.pingServerTime(ip, function () { parentObj.empty(); $.note(null, ip + ‘IISReset成功!‘); parentObj.append(‘<button class="link resetsuccessbtn" style="margin-left:30px;"><i class="icon-checkmark fg-green" style="margin-left:45px;"></i></button>‘); $(‘.resetsuccessbtn‘).click(function () { iisresetpage.startReset($(this)); }); }, function () { if (flag > 10) { $.note(‘Error‘, ip + ‘IISReset失败!请联系管理员处理!‘, ‘error‘); parentObj.append(‘<button class="link resetfailbtn" style="margin-left:30px;"><i class="icon-cancel-2 fg-red"></i></button>‘); $(‘.resetfailbtn‘).click(function () { iisresetpage.startReset($(this)); }); } else { checkPostResult(ip, parentObj, ++flag); } }); }, 5000); }, getResetLog: function (sender) { debugger; var parentObj = sender.parent(); var ip = parentObj.prev().prev().text(); var url = ‘/IIS/GetIISResetLog‘; $.Dialog({ overlay: true, shadow: true, flat: true, icon: null, title: ‘日志‘, content: null, onShow: function (_dialog) { var content = _dialog.children(‘.content‘); content.html(‘<div style="margin:15px; width:900px;height:500px;OVERFLOW: auto;" id="ilogcontainer"></div>‘); chcoreui.attachLoader($(‘#ilogcontainer‘), pageid.loader, 410, 130); // 准备提交数据 var pack = new Object(); pack.ip = ip pack.time = "1"; pack.Token = $.readCookie(‘accessToken‘); var submitData = JSON.stringify(pack); $.ajax({ type: "POST", url: url, data: submitData, dataType: "json", contentType: "application/json", crossDomain: true, success: function (data) { if (data.StateCode == 0) { var bodyContent = ‘‘; $.each(data.Data, function (idx, item) { bodyContent += ‘<tr><td style="text-align:center">‘ + item.Id + ‘</td><td style="text-align:center">‘ + $.convertToDateStr(item.OpTime) + ‘</td><td style="text-align:center">‘ + item.OpAlias + ‘</td><td>‘ + item.Des + ‘</td></tr>‘; }); $(‘#ilogcontainer‘).empty(); $(‘#ilogcontainer‘).html(‘<table class="table bordered striped hovered dataTable" cellspacing="0" id="ilogtable"><thead><tr><th>编号</th><th>操作日期</th><th>操作人</th><th>内容</th></tr></thead><tbody>‘ + bodyContent + ‘</tbody></table>‘); $(‘#ilogtable‘).dataTable({ "paging": true, "searching": false, "ordering": false, "info": false, "dom": ‘<"tool1bar">fr1tip‘ }); } }, error: function (xhr, status, error) { $.note(null, "获取IISRest日志失败!", "error"); } }); } }); } }; var commonajax = { // Ping服务器时间 pingServerTime: function (ip,successcallback,failcallback) { var url = ‘http://‘ + ip + ‘:8167/Monitor/Ping‘; $.ajax({ type: "POST", url: url, dataType: "json", contentType: "application/json", crossDomain: true, success: function (results) { var reg = /\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}/; if (reg.test(results)) { successcallback(); } else { failcallback(); } } }); }, postIISReset: function (ip) { var url = ‘http://‘ + ip + ‘:8167/IIS/IISReset‘; // 准备提交数据 var pack = new Object(); pack.Token = $.readCookie(‘accessToken‘); var submitData = JSON.stringify(pack); $.ajax({ type: "POST", url: url, data: submitData, dataType: "json", contentType: "application/json", crossDomain: true, success: function (results) { }, error: function (xhr, status, error) { } }); } }
至此,完美实现,可靠的IISRESET功能。
本文出自 “爱工作爱生活” 博客,谢绝转载!
原文地址:http://4453154.blog.51cto.com/4443154/1693411