使用hta操作nginx停止、重启

这里算是总结一下,这两天的工作,也是自己动手尝试并实现了自己的想法一个案例。

情况大致是这样的:

新上线的webgame需要做一个官网,做好了并上线了(切割、程序、后台,后台使用是java版本的jeecms),但仅仅是自己家的官网做好了,现在上面的想法是需要把这个官网也整理成一个本地能运行的网站给其它游戏的联合运营商以便减少他们工作量(需要全部静态化,所有绝对地址必须改成相对的,图片也必须请求本地指定目录)。最初只是说把当时切割好的静态页面给他们,后来觉得不是很好的一种方案,希望一些不会变的页面,如:游戏的攻略、玩家、常用活动、排行、热门道具等,将这些页面也弄成一个静态的,这样联合运营商就不再需要进行编辑。当准备开始做的时候面临的问题:

1、静态页里面没有数据,即内容模板页content.html中的内容为空;

2、如果便于对整个静态网站的控制,例如:头部、左侧、底部、导航只需要改一处其它所有页面都可以应用并生效;

3、很多文章中的图片是来自主站的,或是自己在后台上传的,如何抓取这些图片并在相应的内容页进行替换;

应对方案:

1、写个爬虫程序,抓取线上所有的静态页面;

2、将共用的部分使用nginx的ssi include语法包含进去;

3、先抓取所有图片,保留其后缀,然后用editplus打开所有文件,用一个正则进行全局替换;

但在第一点与第二点上有一个矛盾点,什么矛盾点?既然是静态页面,后台生成的时候静态页的时候已经没有include,看到的全部是字符串了,因为nginx已经处理过了。

这样只能绕开请求静态页,让爬虫抓取动态页面(需要修改nginx的nginx.conf配置,在请求后台接口时关闭ssi---ssi off;),在模板中使用ssi include语法嵌入共用页。例如文章编辑完成后,后台有一个预览地址:abc.jsp对应前台访问地址页为abc.html,抓取abc.jsp里面的内容,这个时候就能得到如下的内容:

<html>

<!—#include virtual=”….html”—>

..

</html>

然后根据请求的地址,保存为相应的目录层次关系,文件名保留,后缀名为.html

到这差不多算是可以将所有静态页请求下来了,但又面临新的问题,抓取并生成的静态页面中所有的地址都是公网上的死链接,需要将这些链接替换掉。例如公网为http://aa.123.com,我先将所有http://aa.123.com的链接src/href替换为”/”---直接指向根目录,然后在后面发现如果写死根目录,提供出去的就有有问题,如果有这些一家运营商,它的官网地址将是http://a.abc.com/game/gamename/,它的服务器配置可能是直接将game指向一个目录,如果用/则直接指向到了http://a.abc.com/ 这显示是有问题的。那就再根据层次关系加../了,如果是一级目录则使用“./”如果是二级目录则使用“../”依次类推…

到这里,似乎应该能正常工作了,但还没有完,来了新问题。前面使用ssi include共用页,例如nav.html,这个页面可能有引用一些css、js,它的链接地址写的也是相对的,这样会导致请求这些文件时路径不对,出现404,而这个还不是重点,最要命的是nginx里不支持<!—#include virtual=”../nav.html”-->这样的写法,会在nginx的logs目录下的error.log文件中输出unsafe uir的信息(相对目录”./”它是支持的),如下图所示:

这下可真没得玩了,我只再写程序将所有include的地方写成“/”(根目录)了,如果有联合运营商要修改,我大不了修改一个正则,然后重新生成一个打包文件。因为include使用提“/”所以里面请求css、js的路径可以使用相对的也没问题。

到此为止,“全静态”的游戏官网能正常跑起来了。(关于图片的处理方案,上面已经写过了)

这个时候把这zip包如果发给其它联合运营商,它们在本地是无法跑起来了,因为里面有include,我的想法是希望有个小应用程度,接收的人双击一下点击后就能直接浏览游戏官网了。这是我的想法,到这里才回到这篇文章的标题上来。

用.net写一个windows应用程序,还是用hta处理呢,想了一下还是使用hta写了,虽然之前用.net写过类似的windows应用程序(选择指定目录,查找这个文件夹下所有execl中每一个sheet中每一个单元格是否包含需要查找的字符串并记录下,运行完后打开一个html页,html内容上需要显示匹配到的行、列和excel文件链接等信息)。

用.hta有个问题就是在装有360的机器上会不停的访问是否要运行此应用程序,比较讨厌~(反正我机器啥“杀毒”的软件也没装)

初步有想法:

1、读取用户的hosts文件信息,查找文件中是否配置过指定的规则,例如127.0.0.1    www.test.com,没添加过则追加一条规则

2、读取nginx目录下的nginx.conf文件,修改两处:server_name、root

3、使用ie打开www.test.com

第一步还好解决,部分代码如下:

window.fso = new ActiveXObject("Scripting.FileSystemObject");

//假定hosts文件的所在目录为c盘
window.hostpath = getHostPath("c:\\windows\\system32\\drivers\\etc\\hosts");

//使用通过获取注册表信息来尝试获取hosts文件所在目录
var getHostPath = function(path) {
    if (fso.FileExists(path)) {//存在于默认路径直接返回
        return path;
    }
    var Sh = new ActiveXObject("WScript.Shell"),
        key = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\",
        sysroot = Sh.RegRead(key + "SystemRoot");
    path = sysroot + "\\system32\\drivers\\etc\\hosts";
    
    if (fso.FileExists(path)) {
        return path;
    }

    try {
        if (fso.FileExists(path = Sh.RegRead(key + "HostPath"))) {
            return path;
        }
    } catch (ex) {}

    return false;
 }


//接下来就是获取指定文件、保存文件两个method了
var getFileText = function(url) {
    var ts = fso.OpenTextFile(url, 1, true),//1只读、2写方式、8打开并从文件未必开始写 
        text = ts.AtEndOfStream ? "" : ts.ReadAll() ;

    ts.close();

    return text.trim();
}
var setFileText = function(url, text) {
    try {
        var ts = fso.OpenTextFile(url, 2);
        ts.write(text);
        ts.close();
        return true;
    } catch (e) {
        alert("保存文件\n"+url+"\n失败!请检查文件是否为只读属性");
        return false;
    }
}

有了上面的思路,修改nginx.conf也就很容易了。但是我在处理nginx的停止、重启的时候遇到了问题。

我先在nginx的目录下弄了两个bat批处理文件:restart.bat、stop.bat文件,如下图所示:

stop.bat里面的内容:

nginx.exe -s stop nginx.exe -s quit

restart.bat里面的内容:

nginx.exe -s stop nginx.exe -s quit nginx.exe -s reload start nginx

之后我尝试使用下面的方法直接调用两个bat:

var wsh = new ActiveXObject("WScript.Shell");
var ret = wsh.Run(stopBat, 0, true);
//判定ret是否为0,为0则说明调用的时候出问题了

关于WScript.Shell的Run方法,可以参数msdn上的解释:http://msdn.microsoft.com/en-us/library/d5fk67ky(VS.85).aspx

但直接调用却达不到预期效果,怀疑是执行的时候路径不对,因为直接到nginx的目录下运行上面两个bat是没有问题的,想到先要使用cd切换到nginx所在的目录下。关于批处理如何获取路径的问题,可以参考这篇文章(虽然也是转的,也不知道谁是原创了)http://blog.csdn.net/kome2000/archive/2011/04/29/6372050.aspx

这里只需要做两点:

1、切换到nginx所在的盘符,不确定那个zip会在哪个盘解压出来

2、再切换到nginx所在的目录

对应的两条命令是:

cd %~d0 cd %~dp0

这样我再试的时候就OK了,达到要求了。

hta运行效果如下:

但仍需要注意的问题:

1、解压的zip文件不能放在中文目录下,因为nginx会启不来;

2、nginx.conf的默认配置需要事先开启对ssi的支持,如果不开启,打开游戏官网凡有include的地方就空白了,只需要加二行就OK了

ssi on; ssi_silent_errors on;

3、如果装有一些防护软件的机器上,在运行hta文件时需要允许它运行,不然没得完了。

到此为止,想法才算完整的实现了:只需要点击按钮就可以在本地预览官网,无论你将它放在磁盘哪个地方(除了不能放在中文目录下)。

总结一下,用到的技术:phpjavascriptcsshtabatch(批处理)nginx的配置SSI,上面记录下的是在实现那个想法时遇到的一些问题,以及如何定位问题然后解决它的。

完整的hta代码:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>本地运行游戏官网</title>
<style type='text/css'>    
    h3 {border-left:3px solid 666; color:#666; text-indent:10px; margin:15px 0;}
    textarea {border:2px solid #888; background-color:#222; font-family:'Courier New'; font-size:14px; color:#3c0;}
    a {color:#657528;}
    a:hover {background:#c8dc7b;}

    .exec-btn {display:block; border:1px solid #666; background-color:#9c0; color:#360; padding:5px 5px 3px 5px; margin:50px; width:70px; height:30px; vertical-align:middle; cursor:pointer; display:inline-block;}

    #info_list li {margin-top:10px;}
</style>
</head>
<body style='background-color:#eee; margin:0; padding:0; overflow:hidden;'>


<button class="exec-btn">执行操作</button>
<button class="exec-btn">关闭nginx</button>
<button class="exec-btn">访问官网</button>

<ul id="info_list"></ul>

<script type="text/javascript">   1:     2: String.prototype.trim = function(r){   3:     return this.replace(r || /(^\s+)|(\s+$)/g, "");   4: }    5:     6: !(function() {   7:     var getElem = function(id) {   8:         return typeof id === 'string' ? document.getElementById(id) : id;   9:     }  10:       11:     var addMessage = function(msg) {  12:         var ele = getElem("info_list");  13:         var li = document.createElement("li");  14:             li.innerHTML = msg;  15:           16:         ele.appendChild(li);  17:     }  18:    19:     var messageConfig = {  20:         1 : '开始配置nginx.conf',  21:         2 : '完成hosts文件的配置',  22:         3 : '正在启动浏览器',  23:         4 : '开始配置hosts文件',  24:         5 : '完成对配置nginx.conf',  25:         6 : '正在停止nginx应用程序',  26:         7 : '停止nginx应用程序失败',  27:         8 : '停止nginx应用程序成功',  28:         9 : '正在退出nginx',  29:         10 : 'nginx退出失败',  30:         11 : 'nginx退出成功',  31:         12 : '正在启动nginx应用程序',  32:         13 : 'nginx启动失败',  33:         14 : 'nginx启动成功',  34:         15 : '访问网站主页'  35:     };  36:    37:     var WEB_SITE_URL = "http://www.test.com/";  38:     var SERVER_NAME = WEB_SITE_URL.replace(/^http\:\/\//, "").replace(/\/$/, "");  39:     var HOST_RULE_TEXT = "127.0.0.1\t"+SERVER_NAME;  40:    41:     var getHostPath = function(path) {  42:         if (fso.FileExists(path)) return path;  43:         var Sh = new ActiveXObject("WScript.Shell"),  44:             key = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\",  45:             sysroot = Sh.RegRead(key + "SystemRoot");  46:         path = sysroot + "\\system32\\drivers\\etc\\hosts";  47:           48:         if (fso.FileExists(path)) {  49:             return path;  50:         }  51:    52:         try {  53:             if (fso.FileExists(path = Sh.RegRead(key + "HostPath"))) {  54:                 return path;  55:             }  56:         } catch (ex) {}  57:    58:         return false;  59:     }  60:       61:     var getFileText = function(url) {  62:         var ts = fso.OpenTextFile(url, 1, true),//1只读、2写方式、8打开并从文件未必开始写   63:             text = ts.AtEndOfStream ? "" : ts.ReadAll() ;  64:    65:         ts.close();  66:    67:         return text.trim();  68:     }  69:    70:     var setFileText = function(url, text) {  71:         try {  72:             var ts = fso.OpenTextFile(url, 2);  73:             ts.write(text);  74:             ts.close();  75:             return true;  76:         } catch (e) {  77:             alert("保存文件\n"+url+"\n失败!请检查文件是否为只读属性");  78:             return false;  79:         }  80:     }  81:       82:     var getApplicationPath = function() {  83:         var url = document.location.href;  84:             url = url.replace(/[^\.|/]+.hta/, "").replace(/file\:[^\w]+/i, "");  85:    86:         return url;  87:     }  88:    89:     var getNginxPath = function() {  90:         return getApplicationPath() + "nginx-1.0.2";  91:     }  92:    93:     var configHostsCallback = function() {  94:         addMessage(messageConfig['2']);  95:    96:         var path = getNginxPath();  97:         try {  98:             fso.GetFolder(path);  99:         } catch (ex) { 100:             alert("nginx-1.0.2文件夹在当前目录下未找到,请检查配置!"); 101:             return false; 102:         } 103:          104:         addMessage(messageConfig['1']); 105:         var configURL = path + "/conf/nginx.conf"; 106:         var configText = getFileText(configURL); 107:         var arr = configText.split("\n"); 108:         for (var i = 0, len = arr.length; i < len; i++) { 109:             if (/^\s+server_name\s+([\w\.\d]+);\s*$/.test(arr[i])) { 110:                 arr[i] = arr[i].replace(RegExp['$1'],  SERVER_NAME); 111:                 continue; 112:             } 113:   114:             if (/^\s*root\s+([^;]+);\s*$/.test(arr[i])) { 115:                 arr[i] = arr[i].replace(RegExp['$1'], getApplicationPath()); 116:                 break; 117:             } 118:         } 119:         if (arr.join("\n") !== configText) { 120:             setFileText(configURL, arr.join("\n")); 121:         } 122:         addMessage(messageConfig['2']); 123:          124:         var wsh = null; 125:   126:         try{ 127:             wsh = new ActiveXObject("WScript.Shell"); 128:         }catch(e){ 129:             alert(e.message+" 创建脚本宿主对象失败。") 130:             return; 131:         } 132:          133:         var stopBat = path + "/stop.bat", 134:             restartBat = path + "/restart.bat"; 135:          136:         addMessage(messageConfig['6']); 137:         if (wsh.Run(stopBat, 0, true) == 0) { 138:             addMessage(messageConfig['7']); 139:         } else { 140:             addMessage(messageConfig['8']); 141:         } 142:   143:         addMessage(messageConfig['12']);         144:         if (wsh.Run(restartBat, 0, true) == 0) { 145:             addMessage(messageConfig['13']); 146:         } else { 147:             addMessage(messageConfig['14']); 148:         } 149:         addMessage(messageConfig['15']); 150:         openMainPage(); 151:          152:         document.getElementsByTagName("button")[0].setAttribute("disabled", false); 153:     } 154:      155:     var updateHosts = function() { 156:         if (!hostpath) { 157:             alert('无法获取你本机的HOSTS文件,程序将中止继续运行!'); 158:             return false; 159:         } 160:   161:         var hostText = getFileText(hostpath); 162:         var arr = hostText.split('\n'); 163:   164:         for (var i = 0, len = arr.length; i < len; i++) { 165:             if (arr[i].indexOf(HOST_RULE_TEXT) > -1) { 166:                 addMessage("hosts文件中已存在规则“"+HOST_RULE_TEXT+"”"); 167:                 configHostsCallback(); 168:                 return ; 169:             } 170:         } 171:          172:         addMessage(messageConfig['4']); 173:         arr.push("\n\n#本地运行官网\n" + HOST_RULE_TEXT); 174:   175:         if (arr.join("\n") !== hostText) { 176:             setFileText(hostpath, arr.join("\n")); 177:         }         178:   179:         configHostsCallback(); 180:     } 181:      182:     var openMainPage = function() { 183:         var Sh = new ActiveXObject("WScript.Shell"); 184:         Sh.run('iexplore -new ' + WEB_SITE_URL); 185:     } 186:      187:     document.getElementsByTagName("button")[0].onclick = function() { 188:         this.setAttribute("disabled", true); 189:          190:         getElem("info_list").innerHTML = ""; 191:   192:         updateHosts();             193:     } 194:   195:     document.getElementsByTagName("button")[1].onclick = function() { 196:         this.setAttribute("disabled", true); 197:   198:         var path = getNginxPath(); 199:         try { 200:             fso.GetFolder(path); 201:         } catch (ex) { 202:             alert("nginx-1.0.2文件夹在当前目录下未找到,请检查配置!"); 203:             return false; 204:         } 205:   206:         var wsh = null; 207:   208:         try{ 209:             wsh = new ActiveXObject("WScript.Shell"); 210:         }catch(e){ 211:             alert(e.message+" 创建脚本宿主对象失败。") 212:             return; 213:         } 214:          215:         var stopBat = path + "/stop.bat"; 216:          217:         if (wsh.Run(stopBat, 0, true) == 0) { 218:             alert("执行关闭nginx失败"); 219:         } else { 220:             alert("操作成功!"); 221:         } 222:   223:         this.setAttribute("disabled", false); 224:     } 225:   226:     document.getElementsByTagName("button")[2].onclick = openMainPage; 227:   228:     window.fso = new ActiveXObject("Scripting.FileSystemObject"); 229:     window.hostpath = getHostPath("c:\\windows\\system32\\drivers\\etc\\hosts"); 230: })();</script>

</body>
</html>

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏日常学python

用Python实现模拟登录正方教务系统抢课

最近学校开始选课,但是如果选课时间与自己的事情冲突,这时候就可以使用Python脚本自助抢课,抢课的第一步即是模拟登录,需要模拟登录后保存登录信息然后再进行操作...

2930
来自专栏技术小黑屋

快速高效调试移动端前端代码

通常,前端调试输出一些日志信息可以使用alert或者console, 当然在Desktop机器上很容易,很多浏览器都支持,如果是在手机上,可能比较麻烦,怎么得到...

1941
来自专栏冰霜之地

手把手教你利用Jenkins持续集成iOS项目

众所周知,现在App的竞争已经到了用户体验为王,质量为上的白热化阶段。用户们都是很挑剔的。如果一个公司的推广团队好不容易砸了重金推广了一个APP,好不容易有了一...

1653
来自专栏FreeBuf

打开文件夹就运行?COM劫持利用新姿势

*本文原创作者:菠菜,本文属FreeBuf原创奖励计划,未经许可禁止转载 打开文件夹就能运行指定的程序?这不是天方夜谭,而是在现实世界中确实存在的。利用本文探讨...

2538
来自专栏更流畅、简洁的软件开发方式

【自然框架】之通用权限(八):权限到字段(列表、表单、查询)

 通用权限想要写的文章目录:(这是第八章) 1、 简介、数据库的总体结构 2、 介绍人员表组 3、 介绍组织结构表组 4、 介绍角色表组 5、 介绍“项目自我描...

3037
来自专栏pangguoming

最火的Android开源项目整理

一、代码库 1、from  代码家 整理比较好的源码连接 ***************************************************...

8374
来自专栏菩提树下的杨过

monoTouch开发(1):win7 + vmware下安装mac os

iPhone现在越来越火爆了,很多原本在PC上的互联网应用都纷纷推出了iPhone客户端(比如携程,新浪微博),iPhone的最佳开发环境是mac OS + i...

2206
来自专栏c#开发者

Smart Client Software Factory 初试

Smart Client Software Factory 初试 介绍     智能客户端的介绍我就不再这里说明了,大家可以通过Google去发现。 智能...

3746
来自专栏EAWorld

一篇文章全面解析大数据批处理框架Spring Batch

如今微服务架构讨论的如火如荼。但在企业架构里除了大量的OLTP交易外,还存在海量的批处理交易。在诸如银行的金融机构中,每天有3-4万笔的批处理作业需要处理。针对...

6936
来自专栏大内老A

谈谈基于OAuth 2.0的第三方认证 [上篇]

对于目前大部分Web应用来说,用户认证基本上都由应用自身来完成。具体来说,Web应用利用自身存储的用户凭证(基本上是用户名/密码)与用户提供的凭证进行比较进而确...

19810

扫码关注云+社区

领取腾讯云代金券