复盘一次服务安装失败问题
前言
记录一下本周服务改造过程踩坑经历。近期在做服务改造接入统一配置中心,对一些早期的服务进行升级,由此带来了不少问题,好在都在测试环境解决了,平稳上线。
问题描述
代码自动构建后,部署服务启动失败。到测试服务器上手动启动服务报错“错误1053:服务没有及时响应启动或控制请求”,如图:
修复问题后服务无法重启,希望能找到一个不重启服务器的方法重新安装启动服务。
问题分析
基本套路还是一样的,程序员的法宝:Debug和Log。
日志分析
分析的日志有三个方面可以参考:服务启动打印的日志,系统自带的事件日志,命令行启动日志。 下面逐个分析使用场景和结论。
系统自带日志
一般的程序错误都会在系统日志里面留下痕迹,即使是程序崩溃了,只要系统没有崩溃都会有记录。
遗憾的是,本次应用程序错误后台只有简单提示“服务没有及时响应启动或控制请求”。无法判断是否环境问题。
查看安装日志,如图,没有找到太多有价值信息。
服务启动日志
如果能走到这步,后台有程序输出的记录日志,一般都是启动服务进入到程序里面才报错的,通过调试可以快速定位问题。
查询日志中心,本次没有生成新的日志,开启调试开关,本地也没有生成记录日志。可以判断还没有走到程序内部。
命令行日志
如果是某个没有捕捉到的问题,直接拖到命令行启动倒是一个好方法,可以直接从控制台看到某些错误信息。
果然,通过这一步看到了错误提示。详细日志略过(敏感内容就不贴了。。。),简单的说就是配置没有更新,某个依赖项服务没有注册导致服务dump。
进一步使用SC命令可以查询到其实服务是处于star-pending状态。到此终于可以知道为何启动不起来了。
重启失败服务
接下来我们删除这个启动失败的服务,有两种处理方式:
InstallUtil.exe /u [FullPath\ServiceName.exe]
SC delete [ServiceName]
我采用了第一种使用SC命名的方式,得到了如下的结果
然后安装服务,报1058的错误。查看服务列表,这时候服务还是存在于列表中,只是状态是禁用。
Google了一下,这种情况只需要重启后继续安装就可以。问题来了,服务器能随便重启吗?不说生产的服务器,就是测试的服务器上面也部署了各种服务,几百号人在开发测试呢。。。总不能等到下班后重启服务器吧,找了一下,这种情况就只能删除注册表重新打开服务列表查看:
删除注册表项HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\你的服务名
找了一下卸载的原理,园子里这篇Windows API 之 Windows Service让我了解到:
删除服务的本质是在注册表里面删除该服务的注册表键以及该键的子键。
- 标记该服务为可删除的服务
- 检查该服务是否已经停止,并且该牵涉到该服务的所有句柄都已经被关闭的时候,再来删除该服务;
- 如果该服务一直都在运行状态,那么就等到下次机器重启的时候,来删除该服务
关键点在于:服务所有引用的句柄都已经被关闭。
解决方案
- 修复造成程序启动失败问题
以下几点可以在系统事件查看器看到错误日志:
- 检查安装工具InstallUtil.exe版本是否一致
- 检查配置文件startup的.NETFramework版本是否一致
- 如果添加服务使用了特别账户,检查是否赋予了分组权限
以下几点需要仔细check:
- 配置文件是否正确
- 依赖项是否全部打包正确
- 确认待删除服务没有被占用
- 确保服务器只有你一个用户在线操作待删除服务
- 任务管理器工具(包括Process Explorer等)关闭对待删除服务访问
- 服务控制台和MMC均没有打开待删除服务
- 事件查看器没有打开待删除服务
- Visual Studio远程调试没有打开待删除服务
- 停止(stop)服务,然后删除(delete)服务,最后重建(create)服务
总结
这其实是一个典型的研发,测试,运维合作解决问的过程。每个公司的自动化运维构建平台都会有各种不同的规定,例如配置更新问题。
部署的时候需要按照一定的流程,有一张checklist能减少问题发生。
本文主要讲了安装服务失败后卸载服务的处理方式,记录下来,希望对遇到相同问题的人有一个参考。
推荐使用SC命名行的方式操作安装和卸载服务,可以满足更多的需求而不必重新打包。例如安装不同版本的同一个.exe服务,只是端口和服务名称不一样。
本文同步发表在公众号文章 复盘一次服务安装失败问题
- 博客是我学习和思考的输出,愿你有所收获。
- 有想法请留言,共同探讨学习。
- 由于博主能力有限,文中可能存在描述不当,恳请指正!
- 你也可以关注我的公众号:ProgramLife042,名称:风之程序人生,方便接收最新内容。