Golang Gin Api become Windows Service
Use github.com/kardianos/service
package main
import (
"errors"
"fmt"
"io"
"log"
"net"
"net/http"
"os"
"path/filepath"
"strings"
"time"
"github.com/gin-gonic/gin"
"github.com/joho/godotenv"
"github.com/kardianos/service"
)
// Process Windows Service // github.com/kardianos/service
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) Stop(s service.Service) error {
// Stop should not block. Return with a few seconds.
return nil
}
func ExecPath() string {
ex, err := os.Executable()
if err != nil {
panic(err)
}
exPath := filepath.Dir(ex)
return exPath
}
func main() {
File, err := os.Create(ExecPath() + "\\gin_service_run.log")
if err != nil {
File = os.Stdout
}
defer File.Close()
log.SetOutput(File)
var s service.Service
svcConfig := service.Config{
Name: "GinAPI",
DisplayName: "Gin API Service",
Description: "Gin API Server Converter Windows Service",
}
prg := &program{}
s, err = service.New(prg, &svcConfig)
if err != nil {
log.Fatalln(err)
}
logger, err = s.Logger(nil)
if err != nil {
log.Fatalln(err)
}
if len(os.Args) > 1 {
switch os.Args[1] {
case "install":
err := s.Install()
if err != nil {
logger.Errorf("Install Service Fail!", err.Error())
return
}
fmt.Printf("Install Service Success!")
case "uninstall":
err := s.Uninstall()
if err != nil {
logger.Errorf("Uninstall Service Fail!", err.Error())
return
}
fmt.Printf("Uninstall Service Success!")
case "start":
err := s.Start()
if err != nil {
logger.Errorf("Start Service Fail!", err.Error())
return
}
fmt.Printf("Start Service Success!")
case "stop":
err := s.Stop()
if err != nil {
logger.Errorf("Stop Service Fail!", err.Error())
return
}
fmt.Printf("Stop Service Success!")
}
return
}
err = s.Run()
if err != nil {
logger.Error(err)
}
}
func (p *program) run() {
//
// Create Error logger
//
errFile, err := os.OpenFile(ExecPath()+"\\errors.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
log.Fatalf("打開日誌文件失敗:", err)
}
Error = log.New(io.MultiWriter(errFile, os.Stderr), "【Error】", log.Ldate|log.Ltime|log.Lshortfile)
//
// Get .env
//
err = godotenv.Load(ExecPath() + "\\.env")
if err != nil {
msg := "找不到 .env 檔案"
logger.Errorf(msg, err)
Error.Printf(msg, err)
}
web_port := os.Getenv("WEB_PORT")
//
// Start Gin
//
router := gin.Default()
corsConfig := cors.DefaultConfig()
corsConfig.AllowAllOrigins = true
router.Use(cors.New(corsConfig))
router.GET("/", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"status": "Gin Api Success!"})
})
log.Fatal(http.ListenAndServe(":"+web_port, router))
}
1. run server.exe can run Gin Api Server right now.
2. run server install, server uninstall, server start, server stop.
2.1 【Install and Start】run server install Then server start
2.2 【Stop and uninstall】run server stop Then server uninstall
3. log file use absolute path. ExecPath() can get absolute path.
4. .env must use absolute path. Try to use
svcConfig.EnvVars = map[string]string{
"WEB_PORT": web port
}
see register Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\GinAPI have EnvVars Data.
But err := godotenv.Load() can't get anything, just No Error. So must use absolute path.
5. log have two method.
5.1 File, err := os.Create(ExecPath() + "\\gin_service_run.log")
5.2 【logger.Errorf】 This Error Msg showed at Windows Servce and have Error tag.
OK~ Just try. Hope this blog can help.