2008年11月11日星期二

windows 服务无法关闭的问题解决过程

问题:服务启动后,通过 windows 的服务管理程序停止服务时,报 "1053 错误,无法正常关闭服务",但实际上所有的应用,包括 mysql 都已经关掉。

解决步骤及思路:

1. 在系统信息里查看详细的报错信息,系统没有记录(可能是 windows 不记录其他应用服务的报错信息)

2. Google,查到 MSDN 文档,说的很清楚,就是调用关闭服务的时候超时(默认 30 秒),解决这个问题需要安装 .Net Framework 1.1 SP1

3. 由于我的机器本身安装了 .Net Framework 2.0 SP1,所以怀疑不是这个的原因,另外一个原因是懒的卸载 2.0再安装 1.1

4. 由于安装服务的命令是 windows 自带的 SC 命令,查找 SC 的用法,看是否有增加延时设置的地方,未果

5. 再 Google ,未找到合适的解决方案

6. 下载 .net 1.1 及 sp1,卸载本机 .net 2.0,安装 .net 1.1 sp1,重启机器,问题未解决

7. 想到可能是在关闭服务的时候,在等待其他应用返回或关闭,而造成超时。检查脚本及代码,发现关闭应用时,同时会关闭 数据库,试者手动关闭数据库,再关闭服务,成功。怀疑问题出在这里,但尚未确认。

8. 检查关闭数据库的代码,是在 tomcat 关闭时,在 Servlet 的 destroy 方法中关闭,代码如下:
public void destroy()
{
logger.info("SecFox server is stopping......");
try
{
ManageServer.getManageServer().shutdown();
}catch(Exception e)
{
logger.info("Stop SecFox server:",e);
}

try
{
String stopdb = serverpro.getProperty("stopdb");
if (!stopdb.equals(""))
{
Runtime.getRuntime().exec(stopdb,null,new File(rootDir));
logger.info("Stop database.");
}
}catch(Exception e)
{
logger.info("Stop database:",e);
}
logger.info("SecFox server has stop.");

System.exit(0);
}

9. 检查代码,怀疑是 最后一句 System.exit(0) 造成 jvm 强行退出,而关闭服务的进程还在等待返回,试着注释掉这句,重启应用,结果依旧;试着把 mysql 手动停掉,再关服务,可以正常关闭。多次起动/关闭服务,前两次可以正常关闭,以后又失败。

10. 想啊想,不得其解,觉得问题还是在这里,怀疑是缓存问题,第二天试着把 tomcat 缓存清掉,再试,成功

11. 换一台机器,在不改代码的情况下试,问题依旧;换代码,清缓存,再试,问题解决

12. 由于服务启动的过程中,需要调用脚本启动 mysql,服务启动后,mysql 要过一会儿才能启动,如果此时关闭服务,由于 mysql 还没有启动,所以仍然会报 1053 错误;测试:
a. 启动服务,马上关闭服务,报错落
b. 启动服务,等 mysql 起来后,再关闭服务,正常

--------------------------
附 Runtime.exit() 的JavaDoc :

通过启动虚拟机的关闭序列,终止当前正在运行的 Java 虚拟机。此方法从不正常返回。可以将变量作为一个状态码;根据惯例,非零的状态码表示非正常终止。

虚拟机的关闭序列包含两个阶段。在第一个阶段中,会以某种未指定的顺序启动所有已注册的关闭挂钩(如果有的话),并且允许它们同时运行直至结束。在第二个阶段中,如果已启用退出终结,则运行所有未调用的终结方法。一旦完成这个阶段,虚拟机就会暂停。

如果在虚拟机已开始其关闭序列后才调用此方法,那么若正在运行关闭挂钩,则将无限期地阻断此方法。如果已经运行完关闭挂钩,并且已启用退出终结 (on-exit finalization),那么此方法将利用给定的状态码(如果状态码是非零值)暂停虚拟机;否则将无限期地阻断虚拟机。

没有评论: