背景介绍:
实现如上图所示的,页面一键控制服务器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