221 lines
5.4 KiB
Go
221 lines
5.4 KiB
Go
/*
|
|
* Copyright (C) 2020-2022, IrineSistiana
|
|
*
|
|
* This file is part of mosdns.
|
|
*
|
|
* mosdns is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* mosdns is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
package coremain
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/IrineSistiana/mosdns/v5/mlog"
|
|
"github.com/kardianos/service"
|
|
"github.com/spf13/cobra"
|
|
"go.uber.org/zap"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
)
|
|
|
|
var (
|
|
// initialized by "service" sub command
|
|
svc service.Service
|
|
svcCfg = &service.Config{
|
|
Name: "mosdns",
|
|
DisplayName: "mosdns",
|
|
Description: "A DNS forwarder",
|
|
}
|
|
)
|
|
|
|
type serverService struct {
|
|
f *serverFlags
|
|
m *Mosdns
|
|
}
|
|
|
|
func (ss *serverService) Start(s service.Service) error {
|
|
mlog.L().Info("starting service", zap.String("platform", s.Platform()))
|
|
m, err := NewServer(ss.f)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
ss.m = m
|
|
go func() {
|
|
err := m.GetSafeClose().WaitClosed()
|
|
if err != nil {
|
|
m.Logger().Fatal("server exited", zap.Error(err))
|
|
} else {
|
|
m.Logger().Info("server exited")
|
|
}
|
|
}()
|
|
return nil
|
|
}
|
|
|
|
func (ss *serverService) Stop(_ service.Service) error {
|
|
ss.m.Logger().Info("service is shutting down")
|
|
ss.m.GetSafeClose().SendCloseSignal(nil)
|
|
return ss.m.GetSafeClose().WaitClosed()
|
|
}
|
|
|
|
// initService will init svc for sub command "service"
|
|
func initService(_ *cobra.Command, _ []string) error {
|
|
s, err := service.New(&serverService{}, svcCfg)
|
|
if err != nil {
|
|
return fmt.Errorf("cannot init service, %w", err)
|
|
}
|
|
svc = s
|
|
return nil
|
|
}
|
|
|
|
func newSvcInstallCmd() *cobra.Command {
|
|
sf := new(serverFlags)
|
|
c := &cobra.Command{
|
|
Use: "install [-d working_dir] [-c config_file]",
|
|
Short: "Install mosdns as a system service.",
|
|
Args: cobra.NoArgs,
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
if len(sf.dir) > 0 {
|
|
absWd, err := filepath.Abs(sf.dir)
|
|
if err != nil {
|
|
return fmt.Errorf("cannot solve absolute working dir path, %w", err)
|
|
} else {
|
|
sf.dir = absWd
|
|
}
|
|
} else {
|
|
ep, err := os.Executable()
|
|
if err != nil {
|
|
return fmt.Errorf("cannot solve current executable path, %w", err)
|
|
}
|
|
sf.dir = filepath.Dir(ep)
|
|
}
|
|
mlog.S().Infof("set service working dir as %s", sf.dir)
|
|
svcCfg.Arguments = []string{"start", "--as-service", "-d", sf.dir}
|
|
if len(sf.c) > 0 {
|
|
svcCfg.Arguments = append(svcCfg.Arguments, "-c", sf.c)
|
|
}
|
|
return svc.Install()
|
|
},
|
|
DisableFlagsInUseLine: true,
|
|
SilenceUsage: true,
|
|
}
|
|
c.Flags().StringVarP(&sf.dir, "dir", "d", "", "working dir")
|
|
c.Flags().StringVarP(&sf.c, "config", "c", "", "config path")
|
|
return c
|
|
}
|
|
|
|
func newSvcUninstallCmd() *cobra.Command {
|
|
c := &cobra.Command{
|
|
Use: "uninstall",
|
|
Short: "Uninstall mosdns from system service.",
|
|
Args: cobra.NoArgs,
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
return svc.Uninstall()
|
|
},
|
|
DisableFlagsInUseLine: true,
|
|
SilenceUsage: true,
|
|
}
|
|
return c
|
|
}
|
|
|
|
func newSvcStartCmd() *cobra.Command {
|
|
c := &cobra.Command{
|
|
Use: "start",
|
|
Short: "Start mosdns system service.",
|
|
Args: cobra.NoArgs,
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
if err := svc.Start(); err != nil {
|
|
return err
|
|
}
|
|
|
|
mlog.S().Info("service is starting")
|
|
time.Sleep(time.Second)
|
|
s, err := svc.Status()
|
|
if err != nil {
|
|
mlog.S().Warn("cannot get service status, %w", err)
|
|
} else {
|
|
switch s {
|
|
case service.StatusRunning:
|
|
mlog.S().Info("service is running")
|
|
case service.StatusStopped:
|
|
mlog.S().Error("service is stopped, check mosdns and system service log for more info")
|
|
default:
|
|
mlog.S().Warn("cannot get service status, system may not support this operation")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
},
|
|
DisableFlagsInUseLine: true,
|
|
SilenceUsage: true,
|
|
}
|
|
return c
|
|
}
|
|
|
|
func newSvcStopCmd() *cobra.Command {
|
|
c := &cobra.Command{
|
|
Use: "stop",
|
|
Short: "Stop mosdns system service.",
|
|
Args: cobra.NoArgs,
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
return svc.Stop()
|
|
},
|
|
DisableFlagsInUseLine: true,
|
|
SilenceUsage: true,
|
|
}
|
|
return c
|
|
}
|
|
|
|
func newSvcRestartCmd() *cobra.Command {
|
|
c := &cobra.Command{
|
|
Use: "restart",
|
|
Short: "Restart mosdns system service.",
|
|
Args: cobra.NoArgs,
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
return svc.Restart()
|
|
},
|
|
DisableFlagsInUseLine: true,
|
|
SilenceUsage: true,
|
|
}
|
|
return c
|
|
}
|
|
|
|
func newSvcStatusCmd() *cobra.Command {
|
|
c := &cobra.Command{
|
|
Use: "status",
|
|
Short: "Status of mosdns system service.",
|
|
Args: cobra.NoArgs,
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
s, err := svc.Status()
|
|
if err != nil {
|
|
return fmt.Errorf("cannot get service status, %w", err)
|
|
}
|
|
var out string
|
|
switch s {
|
|
case service.StatusRunning:
|
|
out = "running"
|
|
case service.StatusStopped:
|
|
out = "stopped"
|
|
case service.StatusUnknown:
|
|
out = "unknown"
|
|
}
|
|
println(out)
|
|
return nil
|
|
},
|
|
DisableFlagsInUseLine: true,
|
|
SilenceUsage: true,
|
|
}
|
|
return c
|
|
}
|