winsvc
winsvcgolang.org/x/sys/windowssc
windows服务是脱离于登录用户而存在的,因此必须由管理员来管理。
// 管理员身份
// 注册服务
sc create ServiceName binpath="/path/to/exe"
// 删除服务
sc delete ServiceName
// 启动服务
sc start ServiceName
// 停止服务
sc stop ServiceName
示例代码
package main
import (
"flag"
"fmt"
"log"
"net/http"
"os"
"path/filepath"
"time"
"github.com/chai2010/winsvc"
)
var (
appPath string
flagServiceName = flag.String("service-name", "hello-winsvc", "Set service name")
flagServiceDesc = flag.String("service-desc", "hello windows service", "Set service description")
flagServiceInstall = flag.Bool("service-install", false, "Install service")
flagServiceUninstall = flag.Bool("service-remove", false, "Remove service")
flagServiceStart = flag.Bool("service-start", false, "Start service")
flagServiceStop = flag.Bool("service-stop", false, "Stop service")
)
func init() {
flag.Usage = func() {
fmt.Fprintf(os.Stderr, `
Usage:
hello [options]...
Options:
`)
flag.PrintDefaults()
fmt.Fprintf(os.Stderr, "%s\n", `
Example:
# run hello server
$ go build -o hello.exe hello.go
$ hello.exe
# install hello as windows service
$ hello.exe -service-install
# start/stop hello service
$ hello.exe -service-start
$ hello.exe -service-stop
# remove hello service
$ hello.exe -service-remove
# help
$ hello.exe -h
Report bugs to <chaishushan{AT}gmail.com>.`)
}
// change to current dir
var err error
if appPath, err = winsvc.GetAppPath(); err != nil {
log.Fatal(err)
}
if err := os.Chdir(filepath.Dir(appPath)); err != nil {
log.Fatal(err)
}
}
func main() {
flag.Parse()
// install service
if *flagServiceInstall {
if err := winsvc.InstallService(appPath, *flagServiceName, *flagServiceDesc); err != nil {
log.Fatalf("installService(%s, %s): %v\n", *flagServiceName, *flagServiceDesc, err)
}
fmt.Printf("Done\n")
return
}
// remove service
if *flagServiceUninstall {
if err := winsvc.RemoveService(*flagServiceName); err != nil {
log.Fatalln("removeService:", err)
}
fmt.Printf("Done\n")
return
}
// start service
if *flagServiceStart {
if err := winsvc.StartService(*flagServiceName); err != nil {
log.Fatalln("startService:", err)
}
fmt.Printf("Done\n")
return
}
// stop service
if *flagServiceStop {
if err := winsvc.StopService(*flagServiceName); err != nil {
log.Fatalln("stopService:", err)
}
fmt.Printf("Done\n")
return
}
// run as service
if !winsvc.InServiceMode() {
log.Println("main:", "runService")
if err := winsvc.RunAsService(*flagServiceName, StartServer, StopServer, false); err != nil {
log.Fatalf("svc.Run: %v\n", err)
}
return
}
// run as normal
StartServer()
}
func StartServer() {
log.Println("StartServer, port = 8080")
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "winsrv server", time.Now())
})
http.ListenAndServe(":8080", nil)
}
func StopServer() {
log.Println("StopServer")
}
go get -u github.com/chai2010/winsvc
go build
// 注册服务
go-srv.exe -service-name="go-srv" -service-desc="test go service" -service-install
2021/11/30 17:06:29 installService(go-srv, test go service): Access is denied.
// 移除服务
go-srv.exe -service-name="go-srv" -service-remove
......
Access is denied
go-srvlocalhost:8080
尝试1:
打开注册表
win + r --> regedit -->找到路径 HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System --> 将 EnableLUA 改成 0
发现还是不行,难道要重启吗,想了想,这个地方还是不能改,恢复为1。
于是我又打开了win7电脑,发现这个值是1。
尝试2:
srv.bat
d:
cd dev\php\magook\trunk\server\go-srv
go-srv.exe -service-name="go-srv" -service-desc="test go service" -service-install
cmd
右键,以管理员身份运行。
输出
2021/12/01 11:42:41 installService(go-srv, test go service): A system shutdown is in progress.
这次不是权限的问题了,看来在win10中,administrator账户并不是管理员,或者说他也不具备全部的权限,或者说这个电脑被前面的同事做了什么设置。
A system shutdown is in progress.
尝试3:
win + Q --> 输入 cmd --> 右键
> d:
> cd dev\php\magook\trunk\server\go-srv
> go-srv.exe -service-name="go-srv" -service-desc="test go service" -service-install
2021/12/01 11:42:41 installService(go-srv, test go service): A system shutdown is in progress.
效果是一样的。
service
service
示例代码
package main
import (
"fmt"
"log"
"os"
"github.com/kardianos/service"
)
var serviceConfig = &service.Config{
Name: "go-srv",
DisplayName: "go-srv",
Description: "test go service",
}
func main() {
// 构建服务对象
prog := &Program{}
s, err := service.New(prog, serviceConfig)
if err != nil {
log.Fatal(err)
}
// 用于记录系统日志
logger, err := s.Logger(nil)
if err != nil {
log.Fatal(err)
}
if len(os.Args) < 2 {
err = s.Run()
if err != nil {
logger.Error(err)
}
return
}
cmd := os.Args[1]
if cmd == "install" {
err = s.Install()
if err != nil {
log.Fatal(err)
}
fmt.Println("安装成功")
}
if cmd == "uninstall" {
err = s.Uninstall()
if err != nil {
log.Fatal(err)
}
fmt.Println("卸载成功")
}
// install, uninstall, start, stop 的另一种实现方式
// err = service.Control(s, os.Args[1])
// if err != nil {
// log.Fatal(err)
// }
}
type Program struct{}
func (p *Program) Start(s service.Service) error {
log.Println("开始服务")
go p.run()
return nil
}
func (p *Program) Stop(s service.Service) error {
log.Println("停止服务")
return nil
}
func (p *Program) run() {
// 此处编写具体的服务代码
}
go get -u github.com/kardianos/service
go build
win + Q --> 输入 cmd --> 右键
go-srv.exe install
2021/12/01 16:11:43 A system shutdown is in progress.
还是一样的错误。
到这里,不得不重启了!!
重启之后果然就好了。接着测试。
// 管理员身份运行cmd
打开任务管理器,点到服务栏
> go-srv.exe -service-name="go-srv" -service-desc="test go service" -service-install
Done
但是并没有多出一个 go-srv 服务,当然重新打开任务管理器就可以看到了。但是我们可以调用启动命令来使其展示出来。
> go-srv.exe -service-name="go-srv" -service-start
看到了 go-srv 服务,且正在运行。
> go-srv.exe -service-name="go-srv" -service-remove
发现没有什么效果,服务依然在运行着。
> go-srv.exe -service-name="go-srv" -service-stop
停止服务,同时发现,服务被移除了,所以应该先 stop 再来 remove。