package zdaemon import ( "fmt" "git.swzry.com/zry/SatorIPC/golang/sipc_conn" "git.swzry.com/zry/pathutils" "github.com/gin-gonic/gin" "net" "os" "os/exec" "path" "path/filepath" "runtime" "strconv" ) type ZDaemon struct { daemonName string description string initFunc func() ProgramInterface executableFileName string programPath string zdaemonPath string daemonConfig *yamldef_DaemonConfig daemonProgram ProgramInterface ipcserver *sipc_conn.Server webserver *gin.Engine ipclistener net.Listener ipcurlhost string startOrder int stopOrder int programStdin *os.File programStdout *os.File programStderr *os.File } func NewZDaemon(cfg *ZDaemonConfig) *ZDaemon { zd := &ZDaemon{ daemonName: cfg.DaemonName, initFunc: cfg.InitRunnerFunction, ipcurlhost: fmt.Sprintf("zdaemon-satoripc-client-pid-%d", os.Getpid()), startOrder: cfg.StartOrder, stopOrder: cfg.StopOrder, description: cfg.Description, programStdin: cfg.ProgramStdin, programStdout: cfg.ProgramStdout, programStderr: cfg.ProgramStderr, } if zd.startOrder <= 0 { zd.startOrder = 99 } if zd.startOrder <= 0 { zd.stopOrder = 99 } return zd } func (zd *ZDaemon) Run() { var err error zd.executableFileName, err = filepath.Abs(os.Args[0]) if err != nil { fmt.Println("Failed get executable path: ", err.Error()) return } zd.programPath = filepath.Dir(zd.executableFileName) zd.zdaemonPath = path.Join(zd.programPath, "zdaemon") zd.makeDir() zd.getStatus() if len(os.Args) > 1 { cmdop := os.Args[1] switch cmdop { case "install": zd.install() break case "uninstall": zd.uninstall() break case "start": zd.start() break case "stop": zd.stop() break case "status": zd.status() break case "restart": zd.restart() break case "enable": zd.enable() break case "disable": zd.disable() break case "help": zd.help() break case "__run__": zd.directRun() break default: zd.otherOp(cmdop) break } } else { fmt.Println("Usage: ", zd.daemonName, "{help|start|stop|restart|install|uninstall|enable|disable|...}") } } func (zd *ZDaemon) makeDir() { err := pathutils.MkDirIfNotExist(zd.zdaemonPath, 0777) if err != nil { fmt.Println("Failed create 'zdaemon' directory: ", err.Error()) os.Exit(-1) } } func (zd *ZDaemon) install() { if len(os.Args) == 3 { mode := os.Args[2] switch mode { case "winsvc": zd.install_winsvc() break case "wintray": zd.install_wintray() break case "sysv": zd.install_sysv() break case "systemd": zd.install_systemd() break case "openwrt": zd.install_openwrt() break default: zd.help_install() break } } else { zd.help_install() } } func (zd *ZDaemon) enable() { fmt.Println("Not supported yet.") } func (zd *ZDaemon) disable() { fmt.Println("Not supported yet.") } func (zd *ZDaemon) uninstall() { switch zd.daemonConfig.InstallMode { case "winsvc": zd.uninstall_winsvc() break case "wintray": zd.uninstall_wintray() break case "sysv": zd.uninstall_sysv() break case "systemd": zd.uninstall_systemd() break case "openwrt": zd.uninstall_openwrt() break default: fmt.Println("No installed yet.") break } } func (zd *ZDaemon) forceQuit() { zd.killProcess(zd.daemonConfig.PID) zd.daemonConfig.IsRunning = false zd.daemonConfig.IpcAddr = "" zd.daemonConfig.PID = -1 } func (zd *ZDaemon) checkRunning() bool { if zd.daemonConfig.IsRunning { if zd.daemonConfig.PID > 0 { if zd.daemonConfig.IpcAddr == "" { zd.forceQuit() return false } else { al := zd.ipcAppCheckAlive() if al { return true } else { zd.forceQuit() return false } } } else { zd.daemonConfig.IsRunning = false return false } } return false } func (zd *ZDaemon) stop() { if !zd.checkRunning() { fmt.Println("Daemon", zd.daemonName, "not running.") return } ks := zd.ipcAppStop() if !ks { fmt.Println("Force killing daemon...") zd.killProcess(zd.daemonConfig.PID) fmt.Println("End.") } } func (zd *ZDaemon) restart() { if zd.checkRunning() { ks := zd.ipcAppStop() if !ks { fmt.Println("Force killing daemon...") zd.killProcess(zd.daemonConfig.PID) fmt.Println("End.") } } else { fmt.Println("Daemon", zd.daemonName, "not running.") } zd.start() } func (zd *ZDaemon) status() { if zd.checkRunning() { zd.ipcAppGetStatus() } else { fmt.Println("Status: not running.") return } } func (zd *ZDaemon) otherOp(op string) { uargs := os.Args[2:] if zd.checkRunning() { zd.ipcAppOtherOperation(op, uargs) } else { fmt.Println("Faild do operation", op, ": daemon not running.") return } } func (zd *ZDaemon) killProcess(pid int) { if pid < 1 { return } if runtime.GOOS == "windows" { cmd := exec.Command("taskkill.exe", "/F", "/PID", strconv.Itoa(pid)) _ = cmd.Run() } else { cmd := exec.Command("kill", strconv.Itoa(pid)) _ = cmd.Run() cmd = exec.Command("kill", "-9", strconv.Itoa(pid)) _ = cmd.Run() } }