Skip to content

feat(systemctl): 实现服务管理器初始化和命令执行 #8380

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Apr 17, 2025
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ build_frontend:

build_backend_on_linux:
cd $(SERVER_PATH) \
&& GOOS=$(GOOS) GOARCH=$(GOARCH) $(GOBUILD) -trimpath -ldflags '-s -w' -o $(BUILD_PATH)/$(APP_NAME) $(MAIN)
&& CGO_ENABLED=0 GOOS=$(GOOS) GOARCH=$(GOARCH) $(GOBUILD) -trimpath -ldflags '-s -w' -o $(BUILD_PATH)/$(APP_NAME) $(MAIN)

build_backend_on_darwin:
cd $(SERVER_PATH) \
Expand Down
236 changes: 105 additions & 131 deletions backend/app/service/clam.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package service

import (
"bufio"
"fmt"
"os"
"os/exec"
Expand All @@ -28,14 +27,14 @@ import (
)

const (
clamServiceNameCentOs = "[email protected]"
clamServiceNameUbuntu = "clamav-daemon.service"
freshClamService = "clamav-freshclam.service"
resultDir = "clamav"
clamServiceKey = "clam"
freshClamServiceKey = "freshclam"
resultDir = "clamav"
)

type ClamService struct {
serviceName string
serviceName string
freshClamService string
}

type IClamService interface {
Expand Down Expand Up @@ -63,23 +62,32 @@ func (c *ClamService) LoadBaseInfo() (dto.ClamBaseInfo, error) {
var baseInfo dto.ClamBaseInfo
baseInfo.Version = "-"
baseInfo.FreshVersion = "-"
exist1, _ := systemctl.IsExist(clamServiceNameCentOs)
if exist1 {
c.serviceName = clamServiceNameCentOs
baseInfo.IsExist = true
baseInfo.IsActive, _ = systemctl.IsActive(clamServiceNameCentOs)
}
exist2, _ := systemctl.IsExist(clamServiceNameUbuntu)
if exist2 {
c.serviceName = clamServiceNameUbuntu
baseInfo.IsExist = true
baseInfo.IsActive, _ = systemctl.IsActive(clamServiceNameUbuntu)
}
freshExist, _ := systemctl.IsExist(freshClamService)
if freshExist {
baseInfo.FreshIsExist = true
baseInfo.FreshIsActive, _ = systemctl.IsActive(freshClamService)
clamSvc, err := systemctl.GetServiceName(clamServiceKey)
if err != nil {
baseInfo.IsExist = false
return baseInfo, nil
}
c.serviceName = clamSvc
isExist, err := systemctl.IsExist(c.serviceName)
if err != nil {
baseInfo.IsExist = false
}
baseInfo.IsExist = isExist
baseInfo.IsActive, _ = systemctl.IsActive(clamSvc)

freshSvc, err := systemctl.GetServiceName(freshClamServiceKey)
if err != nil {
baseInfo.FreshIsExist = false
return baseInfo, nil
}
c.freshClamService = freshSvc
freshisExist, err := systemctl.IsExist(c.freshClamService)
if err != nil {
baseInfo.FreshIsExist = false
}
baseInfo.FreshIsExist = freshisExist
baseInfo.FreshIsActive, _ = systemctl.IsActive(freshSvc)

if !cmd.Which("clamdscan") {
baseInfo.IsActive = false
}
Expand Down Expand Up @@ -110,22 +118,27 @@ func (c *ClamService) LoadBaseInfo() (dto.ClamBaseInfo, error) {
}

func (c *ClamService) Operate(operate string) error {
var err error
switch operate {
case "start", "restart", "stop":
stdout, err := cmd.Execf("systemctl %s %s", operate, c.serviceName)
if err != nil {
return fmt.Errorf("%s the %s failed, err: %s", operate, c.serviceName, stdout)
}
return nil
case "fresh-start", "fresh-restart", "fresh-stop":
stdout, err := cmd.Execf("systemctl %s %s", strings.TrimPrefix(operate, "fresh-"), freshClamService)
if err != nil {
return fmt.Errorf("%s the %s failed, err: %s", operate, c.serviceName, stdout)
}
return nil
case "start":
err = systemctl.Start(c.serviceName)
case "stop":
err = systemctl.Stop(c.serviceName)
case "restart":
err = systemctl.Restart(c.serviceName)
case "fresh-start":
err = systemctl.Start(c.freshClamService)
case "fresh-stop":
err = systemctl.Stop(c.freshClamService)
case "fresh-restart":
err = systemctl.Restart(c.freshClamService)
default:
return fmt.Errorf("not support such operation: %v", operate)
return fmt.Errorf("unsupported operation: %s", operate)
}
if err != nil {
return fmt.Errorf("%s %s failed: %v", operate, c.serviceName, err)
}
return nil
}

func (c *ClamService) SearchWithPage(req dto.SearchClamWithPage) (int64, interface{}, error) {
Expand Down Expand Up @@ -432,102 +445,80 @@ func (c *ClamService) LoadFile(req dto.ClamFileReq) (string, error) {
filePath := ""
switch req.Name {
case "clamd":
if c.serviceName == clamServiceNameUbuntu {
filePath = "/etc/clamav/clamd.conf"
} else {
filePath = "/etc/clamd.d/scan.conf"
}
filePath = c.getConfigPath("clamd")
case "clamd-log":
filePath = c.loadLogPath("clamd-log")
if len(filePath) != 0 {
break
}
if c.serviceName == clamServiceNameUbuntu {
filePath = "/var/log/clamav/clamav.log"
} else {
filePath = "/var/log/clamd.scan"
}
case "freshclam":
if c.serviceName == clamServiceNameUbuntu {
filePath = "/etc/clamav/freshclam.conf"
} else {
filePath = "/etc/freshclam.conf"
}
filePath = c.getConfigPath("freshclam")
case "freshclam-log":
filePath = c.loadLogPath("freshclam-log")
if len(filePath) != 0 {
break
}
if c.serviceName == clamServiceNameUbuntu {
filePath = "/var/log/clamav/freshclam.log"
} else {
filePath = "/var/log/freshclam.log"
}
default:
return "", fmt.Errorf("not support such type")
}
if _, err := os.Stat(filePath); err != nil {
return "", buserr.New("ErrHttpReqNotFound")
return "", fmt.Errorf("unsupported file type")
}
var tail string
if req.Tail != "0" {
tail = req.Tail
} else {
tail = "+1"
}
cmd := exec.Command("tail", "-n", tail, filePath)
stdout, err := cmd.CombinedOutput()

content, err := systemctl.ViewConfig(filePath, systemctl.ConfigOption{TailLines: req.Tail})
if err != nil {
return "", fmt.Errorf("tail -n %v failed, err: %v", req.Tail, err)
return "", buserr.New("ErrHttpReqNotFound")
}
return string(stdout), nil
return content, nil
}

func (c *ClamService) UpdateFile(req dto.UpdateByNameAndFile) error {
filePath := ""
service := ""
var (
filePath string
service string
)

switch req.Name {
case "clamd":
if c.serviceName == clamServiceNameUbuntu {
service = clamServiceNameUbuntu
filePath = "/etc/clamav/clamd.conf"
} else {
service = clamServiceNameCentOs
filePath = "/etc/clamd.d/scan.conf"
}
filePath = c.getConfigPath("clamd")
service = c.serviceName
case "freshclam":
if c.serviceName == clamServiceNameUbuntu {
filePath = "/etc/clamav/freshclam.conf"
} else {
filePath = "/etc/freshclam.conf"
}
service = "clamav-freshclam.service"
filePath = c.getConfigPath("freshclam")
service = c.freshClamService
default:
return fmt.Errorf("not support such type")
return fmt.Errorf("unsupported file type")
}

file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_TRUNC, 0640)
if err != nil {
return err
}
defer file.Close()
write := bufio.NewWriter(file)
_, _ = write.WriteString(req.File)
write.Flush()

_ = systemctl.Restart(service)
if _, err := file.WriteString(req.File); err != nil {
return err
}

if err := systemctl.Restart(service); err != nil {
return fmt.Errorf("restart %s failed: %v", service, err)
}
return nil
}

func (c *ClamService) getConfigPath(confType string) string {
switch confType {
case "clamd":
if _, err := os.Stat("/etc/clamav/clamd.conf"); err == nil {
return "/etc/clamav/clamd.conf"
}
return "/etc/clamd.d/scan.conf"
case "freshclam":
if _, err := os.Stat("/etc/clamav/freshclam.conf"); err == nil {
return "/etc/clamav/freshclam.conf"
}
return "/etc/freshclam.conf"
default:
return ""
}
}

func StopAllCronJob(withCheck bool) bool {
if withCheck {
isActive := false
exist1, _ := systemctl.IsExist(clamServiceNameCentOs)
if exist1 {
isActive, _ = systemctl.IsActive(clamServiceNameCentOs)
}
exist2, _ := systemctl.IsExist(clamServiceNameUbuntu)
if exist2 {
isActive, _ = systemctl.IsActive(clamServiceNameUbuntu)
isexist, _ := systemctl.IsExist(clamServiceKey)
if isexist {
isActive, _ = systemctl.IsActive(clamServiceKey)
}
if isActive {
return false
Expand Down Expand Up @@ -590,42 +581,25 @@ func loadResultFromLog(pathItem string) dto.ClamLog {
return data
}
func (c *ClamService) loadLogPath(name string) string {
confPath := ""
if name == "clamd-log" {
if c.serviceName == clamServiceNameUbuntu {
confPath = "/etc/clamav/clamd.conf"
} else {
confPath = "/etc/clamd.d/scan.conf"
}
} else {
if c.serviceName == clamServiceNameUbuntu {
confPath = "/etc/clamav/freshclam.conf"
} else {
confPath = "/etc/freshclam.conf"
}
}
if _, err := os.Stat(confPath); err != nil {
return ""
configKey := "clamd"
searchPrefix := "LogFile "
if name != "clamd-log" {
configKey = "freshclam"
searchPrefix = "UpdateLogFile "
}
confPath := c.getConfigPath(configKey)

content, err := os.ReadFile(confPath)
if err != nil {
global.LOG.Debugf("Failed to read %s config: %v", configKey, err)
return ""
}
lines := strings.Split(string(content), "\n")
if name == "clamd-log" {
for _, line := range lines {
if strings.HasPrefix(line, "LogFile ") {
return strings.Trim(strings.ReplaceAll(line, "LogFile ", ""), " ")
}
}
} else {
for _, line := range lines {
if strings.HasPrefix(line, "UpdateLogFile ") {
return strings.Trim(strings.ReplaceAll(line, "UpdateLogFile ", ""), " ")
}

for _, line := range strings.Split(string(content), "\n") {
if strings.HasPrefix(line, searchPrefix) {
return strings.TrimSpace(strings.TrimPrefix(line, searchPrefix))
}
}

return ""
}

Expand Down
3 changes: 2 additions & 1 deletion backend/app/service/device.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
"github.com/1Panel-dev/1Panel/backend/utils/common"
"github.com/1Panel-dev/1Panel/backend/utils/ntp"
"github.com/1Panel-dev/1Panel/backend/utils/systemctl"
"github.com/shirou/gopsutil/v3/mem"
)

Expand Down Expand Up @@ -121,7 +122,7 @@ func (u *DeviceService) Update(key, value string) error {
return err
}
go func() {
_, err := cmd.Exec("systemctl restart 1panel.service")
err := systemctl.Restart("1panel")
if err != nil {
global.LOG.Errorf("restart system for new time zone failed, err: %v", err)
}
Expand Down
4 changes: 2 additions & 2 deletions backend/app/service/device_clean.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ import (

"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/utils/docker"
"github.com/1Panel-dev/1Panel/backend/utils/systemctl"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"

"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
"github.com/1Panel-dev/1Panel/backend/utils/common"
fileUtils "github.com/1Panel-dev/1Panel/backend/utils/files"
"github.com/google/uuid"
Expand Down Expand Up @@ -285,7 +285,7 @@ func (u *DeviceService) Clean(req []dto.Clean) {

if restart {
go func() {
_, err := cmd.Exec("systemctl restart 1panel.service")
err := systemctl.Restart("1panel")
if err != nil {
global.LOG.Errorf("restart system port failed, err: %v", err)
}
Expand Down
Loading