Windows Server 2019下Go程序无法作为Windows服务启动报错
Go编写的REST API部署为Windows服务启动失败排查方案
核心故障原因与修复
1. 服务注册参数错误
你当前使用的New-Service命令中BinaryPathName参数的引号嵌套错误,系统会将包含--service参数的完整字符串识别为可执行文件路径,无法找到对应文件导致启动失败。
先执行以下命令删除错误注册的服务:
sc.exe delete AHS
再使用修正后的参数重新注册服务,注意可执行文件路径单独用双引号包裹,参数放在引号外部:
$params = @{ Name = "AHS" BinaryPathName = '"C:\Temp\ah.exe" --service' DisplayName = "AH Service" StartupType = "Manual" Description = "This is a test service." } New-Service @params
2. 代码工作目录异常
Windows服务默认工作目录为C:\Windows\System32,并非可执行文件所在目录。你代码中使用相对路径写入log.txt,会出现两种异常:一是日志文件写入到System32目录不符合预期,二是默认服务账号无System32写入权限时会直接导致进程崩溃退出。
在main函数最开头添加以下代码,将工作目录切换为可执行文件所在目录:
// 先在import块引入"path/filepath" exePath, err := os.Executable() if err == nil { _ = os.Chdir(filepath.Dir(exePath)) }
同时补全service库的配置项,避免平台兼容性问题:
serviceConfig := &service.Config{ Name: serviceName, DisplayName: "AH Service", Description: "This is a test service.", }
3. 日志写入逻辑bug
你当前的writeToFile方法每次调用os.Create都会截断覆盖原有文件,既无法保留历史日志,文件被占用时还会抛出错误。建议改为追加写入模式:
func writeToFile(str string, fileName string) error { file, err := os.OpenFile(fileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { return err } defer file.Close() _, err = file.WriteString(time.Now().Format(time.RFC3339) + " " + str) return err }
通用排查步骤
- 先直接在命令行执行
C:\Temp\ah.exe --service,确认程序本身无逻辑错误,可正常运行、生成日志文件。如果命令行下无法运行,先修复程序本身的bug再注册服务。 - 打开Windows事件查看器,依次进入「Windows日志」-「应用程序」,筛选来源为
Service Control Manager或对应服务名的错误条目,可直接查看服务启动失败的具体原因(如文件不存在、权限不足、进程退出码等)。 - 如果程序需要访问网络共享、特殊权限目录,可在服务属性的「登录」选项卡中,将服务运行账号修改为拥有对应权限的本地账号,默认的Local System账号无网络资源访问权限。
内容的提问来源于stack exchange,提问作者Mohsen Kamrani
相关产品推荐
相关产品推荐

