换成单集群模式
This commit is contained in:
@@ -6,25 +6,107 @@ package utils
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"os/exec"
|
||||
"time"
|
||||
|
||||
teaconst "github.com/TeaOSLab/EdgeHttpDNS/internal/const"
|
||||
executils "github.com/TeaOSLab/EdgeHttpDNS/internal/utils/exec"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
)
|
||||
|
||||
var systemdServiceFile = "/etc/systemd/system/" + teaconst.SystemdServiceName + ".service"
|
||||
var initServiceFile = "/etc/init.d/" + teaconst.SystemdServiceName
|
||||
|
||||
// Install 安装系统服务
|
||||
func (m *ServiceManager) Install(exePath string, args []string) error {
|
||||
if os.Getgid() != 0 {
|
||||
return errors.New("only root users can install the service")
|
||||
}
|
||||
|
||||
systemd, err := exec.LookPath("systemctl")
|
||||
systemd, err := executils.LookPath("systemctl")
|
||||
if err != nil {
|
||||
return err
|
||||
// systemd 不可用,降级到 init.d
|
||||
return m.installInitService(exePath, args)
|
||||
}
|
||||
|
||||
desc := `[Unit]
|
||||
Description=GoEdge HTTPDNS Node Service
|
||||
return m.installSystemdService(systemd, exePath, args)
|
||||
}
|
||||
|
||||
// Start 启动服务
|
||||
func (m *ServiceManager) Start() error {
|
||||
if os.Getgid() != 0 {
|
||||
return errors.New("only root users can start the service")
|
||||
}
|
||||
|
||||
// 优先检查 systemd
|
||||
if fileExists(systemdServiceFile) {
|
||||
systemd, err := executils.LookPath("systemctl")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return executils.NewTimeoutCmd(10*time.Second, systemd, "start", teaconst.SystemdServiceName+".service").Start()
|
||||
}
|
||||
|
||||
// 降级到 init.d
|
||||
if fileExists(initServiceFile) {
|
||||
return executils.NewTimeoutCmd(10*time.Second, "service", teaconst.ProcessName, "start").Start()
|
||||
}
|
||||
|
||||
return errors.New("no service file found, please install the service first")
|
||||
}
|
||||
|
||||
// Uninstall 删除服务
|
||||
func (m *ServiceManager) Uninstall() error {
|
||||
if os.Getgid() != 0 {
|
||||
return errors.New("only root users can uninstall the service")
|
||||
}
|
||||
|
||||
// systemd
|
||||
if fileExists(systemdServiceFile) {
|
||||
systemd, err := executils.LookPath("systemctl")
|
||||
if err == nil {
|
||||
_ = executils.NewTimeoutCmd(10*time.Second, systemd, "stop", teaconst.SystemdServiceName+".service").Run()
|
||||
_ = executils.NewTimeoutCmd(10*time.Second, systemd, "disable", teaconst.SystemdServiceName+".service").Run()
|
||||
_ = executils.NewTimeoutCmd(10*time.Second, systemd, "daemon-reload").Run()
|
||||
}
|
||||
return os.Remove(systemdServiceFile)
|
||||
}
|
||||
|
||||
// init.d
|
||||
if fileExists(initServiceFile) {
|
||||
_ = executils.NewTimeoutCmd(10*time.Second, "service", teaconst.ProcessName, "stop").Run()
|
||||
chkCmd, err := executils.LookPath("chkconfig")
|
||||
if err == nil {
|
||||
_ = executils.NewTimeoutCmd(10*time.Second, chkCmd, "--del", teaconst.ProcessName).Run()
|
||||
}
|
||||
return os.Remove(initServiceFile)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// installSystemdService 安装 systemd 服务
|
||||
func (m *ServiceManager) installSystemdService(systemd, exePath string, args []string) error {
|
||||
shortName := teaconst.SystemdServiceName
|
||||
longName := "GoEdge HTTPDNS"
|
||||
|
||||
// 用 bash 包装启动命令,兼容路径含空格的场景
|
||||
var startCmd = exePath + " daemon"
|
||||
bashPath, _ := executils.LookPath("bash")
|
||||
if len(bashPath) > 0 {
|
||||
startCmd = bashPath + " -c \"" + startCmd + "\""
|
||||
}
|
||||
|
||||
desc := `### BEGIN INIT INFO
|
||||
# Provides: ` + shortName + `
|
||||
# Required-Start: $all
|
||||
# Required-Stop:
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop:
|
||||
# Short-Description: ` + longName + ` Service
|
||||
### END INIT INFO
|
||||
|
||||
[Unit]
|
||||
Description=` + longName + ` Node Service
|
||||
Before=shutdown.target
|
||||
After=network-online.target
|
||||
|
||||
@@ -32,34 +114,102 @@ After=network-online.target
|
||||
Type=simple
|
||||
Restart=always
|
||||
RestartSec=1s
|
||||
ExecStart=` + exePath + ` daemon
|
||||
ExecStart=` + startCmd + `
|
||||
ExecStop=` + exePath + ` stop
|
||||
ExecReload=` + exePath + ` restart
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target`
|
||||
|
||||
err = os.WriteFile(systemdServiceFile, []byte(desc), 0777)
|
||||
// 权限 0644,systemd 单元文件不需要执行权限
|
||||
err := os.WriteFile(systemdServiceFile, []byte(desc), 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_ = exec.Command(systemd, "stop", teaconst.SystemdServiceName+".service").Run()
|
||||
_ = exec.Command(systemd, "daemon-reload").Run()
|
||||
return exec.Command(systemd, "enable", teaconst.SystemdServiceName+".service").Run()
|
||||
// 停止已有服务
|
||||
_ = executils.NewTimeoutCmd(10*time.Second, systemd, "stop", shortName+".service").Run()
|
||||
|
||||
// 重新加载
|
||||
_ = executils.NewTimeoutCmd(10*time.Second, systemd, "daemon-reload").Run()
|
||||
|
||||
// 启用开机自启
|
||||
return executils.NewTimeoutCmd(10*time.Second, systemd, "enable", shortName+".service").Run()
|
||||
}
|
||||
|
||||
func (m *ServiceManager) Uninstall() error {
|
||||
if os.Getgid() != 0 {
|
||||
return errors.New("only root users can uninstall the service")
|
||||
}
|
||||
// installInitService 安装 init.d 服务(降级方案,适用于无 systemd 的旧系统)
|
||||
func (m *ServiceManager) installInitService(exePath string, args []string) error {
|
||||
shortName := teaconst.SystemdServiceName
|
||||
longName := "GoEdge HTTPDNS"
|
||||
|
||||
systemd, err := exec.LookPath("systemctl")
|
||||
// 生成 init.d 脚本
|
||||
script := `#!/bin/bash
|
||||
### BEGIN INIT INFO
|
||||
# Provides: ` + shortName + `
|
||||
# Required-Start: $all
|
||||
# Required-Stop:
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: ` + longName + ` Service
|
||||
### END INIT INFO
|
||||
|
||||
INSTALL_DIR=` + Tea.Root + `
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
cd "${INSTALL_DIR}"
|
||||
` + exePath + ` daemon &
|
||||
echo "` + longName + ` started"
|
||||
;;
|
||||
stop)
|
||||
cd "${INSTALL_DIR}"
|
||||
` + exePath + ` stop
|
||||
echo "` + longName + ` stopped"
|
||||
;;
|
||||
restart)
|
||||
cd "${INSTALL_DIR}"
|
||||
` + exePath + ` stop
|
||||
sleep 1
|
||||
` + exePath + ` daemon &
|
||||
echo "` + longName + ` restarted"
|
||||
;;
|
||||
status)
|
||||
cd "${INSTALL_DIR}"
|
||||
` + exePath + ` status
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|restart|status}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
exit 0
|
||||
`
|
||||
|
||||
// init.d 脚本需要执行权限
|
||||
err := os.WriteFile(initServiceFile, []byte(script), 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_ = exec.Command(systemd, "disable", teaconst.SystemdServiceName+".service").Run()
|
||||
_ = exec.Command(systemd, "daemon-reload").Run()
|
||||
return os.Remove(systemdServiceFile)
|
||||
// 尝试用 chkconfig 注册(CentOS/RHEL)
|
||||
chkCmd, err := executils.LookPath("chkconfig")
|
||||
if err == nil {
|
||||
_ = executils.NewTimeoutCmd(10*time.Second, chkCmd, "--add", teaconst.ProcessName).Run()
|
||||
return nil
|
||||
}
|
||||
|
||||
// 尝试用 update-rc.d 注册(Debian/Ubuntu)
|
||||
updateRcCmd, err := executils.LookPath("update-rc.d")
|
||||
if err == nil {
|
||||
_ = executils.NewTimeoutCmd(10*time.Second, updateRcCmd, teaconst.ProcessName, "defaults").Run()
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// fileExists 检查文件是否存在
|
||||
func fileExists(path string) bool {
|
||||
_, err := os.Stat(path)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user