通过 sc 工具,将golang程序制作成windows服务,启动报错,解决方法

在windows 系统下,通过命令行窗口启动服务,有一个缺点:当鼠标置于窗口内,可能将程序挂起(窗口是交互界面,如果你有在程序内部捕获标准输入输出的话,是会挂起程序的)。所以,将程序制作成服务,以服务的方式启动程序,成了windows系统下服务器程序最佳的启动方式。
但是用golang编写的程序,通过sc工具制作的服务无法正常启动。报错信息如下:
启动报错信息
在网搜索了很多关于这方便的信息,要么是没有结贴的,要么是通过传入参数,自动将程序制作成服务的。但是,这些都不能满足我们项目现在的使用场景。我们需要用手动方式将程序做成服务(通过sc工具),然后在添加开机任务(属其他内容)。
在网上找到了"golang.org/x/sys/windows"包,该包对Windows服务提供了必要的支持。只是这个扩展包比较偏向底层使用比较繁琐。后来又找到了"github.com/kardianos/service"包,这个包是对"golang.org/x/sys/windows"包的进一步封装,使用起来非常方便。示例代码如下:

package main

import (
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/logs"
	"github.com/kardianos/service"
	"log"
)

var logger service.Logger

type program struct{}

func (p *program) Start(s service.Service) error {
	// Start should not block. Do the actual work async.
	go p.run()
	return nil
}
func (p *program) run() {
	// Do work here
	StartServer()
}
func (p *program) Stop(s service.Service) error {
	// Stop should not block. Return with a few seconds.
	return nil
}

func main() {
	svcConfig := &service.Config{
		Name:        "GoServiceTest",
		DisplayName: "Go Service Test",
		Description: "This is a test Go service.",
	}

	prg := &program{}
	s, err := service.New(prg, svcConfig)
	if err != nil {
		log.Fatal(err)
	}
	logger, err = s.Logger(nil)
	if err != nil {
		log.Fatal(err)
	}
	err = s.Run()
	if err != nil {
		logger.Error(err)
	}
	//StartServer()

}

// 开启服务
func StartServer() {
	lwlog.Logs.Info("lwboottask started !!!")
	// TODO :初始化代码
	beego.Run()
}

// 停止服务
func StopServer() {

}

程序启动后,首先检测程序运行模式,根据运行模式不同,决定是否启用windows服务。
下面列出操作命令,分别是注册服务、启动服务、停止服务、删除服务:

sc create lwagentservices binpath= "%~dp0lwyagent.exe" start= auto displayname= "lwyagent"
net start  myserver
net stop   myserver
sc  delete myserver

通过这种方式,成功解决了sc工具制作windows服务后,启动失败问题。
注意:通过服务的方式启动后,一定要注意读取配置文件的路径以及日志文件的输出路径都要采用绝对路径。由于,这个问题,我曾经一直认为通过sc工具做服务失败,其实是读取配置文件失败(路径问题)。后来改用绝对路径后,服务就正常工作了。

Go语言提供了一个内置的包`net/http`,可以用来创建HTTP服务器。在Windows上,可以将这个HTTP服务器作为一个Windows服务运行。 下面是一个简单的示例代码,演示如何使用Go语言创建一个Windows服务程序: ```go package main import ( "fmt" "log" "net/http" "os" "os/signal" "syscall" "time" "golang.org/x/sys/windows/svc" "golang.org/x/sys/windows/svc/debug" ) type myService struct{} func (m *myService) Execute(args []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (ssec bool, errno uint32) { const cmdsAccepted = svc.AcceptStop | svc.AcceptShutdown changes <- svc.Status{State: svc.StartPending} go func() { // 启动HTTP服务器 http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, World!") }) err := http.ListenAndServe(":8080", nil) if err != nil { log.Fatal(err) } }() changes <- svc.Status{State: svc.Running, Accepts: cmdsAccepted} loop: for { select { case c := <-r: switch c.Cmd { case svc.Interrogate: changes <- c.CurrentStatus time.Sleep(100 * time.Millisecond) changes <- c.CurrentStatus case svc.Stop, svc.Shutdown: break loop default: log.Printf("unexpected control request #%d", c) } } } changes <- svc.Status{State: svc.StopPending} return } func main() { isIntSess, err := svc.IsAnInteractiveSession() if err != nil { log.Fatal(err) } if isIntSess { runService() return } debug.Run("MyService", &myService{}) } func runService() { err := svc.Run("MyService", &myService{}) if err != nil { log.Fatal(err) } } ``` 这个示例代码创建了一个简单的HTTP服务器,监听在本地的8080端口。当将这个程序安装为Windows服务后,可以通过访问`http://localhost:8080`来访问该服务。 要将这个程序安装为Windows服务,可以使用`sc`命令或者使用第三方工具如`nssm`。下面是使用`sc`命令的示例: 1. 打开命令提示符,以管理员身份运行。 2. 进入程序所在的目录。 3. 执行以下命令安装服务:`sc create MyService binPath= "<程序路径>" start= auto` 4. 执行以下命令启动服务:`sc start MyService` 现在,你可以通过访问`http://localhost:8080`来测试这个服务
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值