2
0
mirror of https://github.com/acepanel/panel.git synced 2026-02-04 11:27:17 +08:00

refactor: 重构 tools.Exec 函数

This commit is contained in:
耗子
2023-11-14 01:54:26 +08:00
parent 1c5b32a7a9
commit 2b1b58ea2b
39 changed files with 1843 additions and 1332 deletions

View File

@@ -125,7 +125,11 @@ func (receiver *Panel) Handle(ctx console.Context) error {
return nil
}
port := tools.Exec(`cat /www/panel/panel.conf | grep APP_PORT | awk -F '=' '{print $2}' | tr -d '\n'`)
port, err := tools.Exec(`cat /www/panel/panel.conf | grep APP_PORT | awk -F '=' '{print $2}' | tr -d '\n'`)
if err != nil {
color.Redln("获取面板端口失败")
return nil
}
color.Greenln("用户名: " + user.Username)
color.Greenln("密码: " + password)
@@ -133,15 +137,27 @@ func (receiver *Panel) Handle(ctx console.Context) error {
color.Greenln("面板入口: " + facades.Config().GetString("http.entrance"))
case "getPort":
port := tools.Exec("cat /www/panel/panel.conf | grep APP_PORT | awk -F '=' '{print $2}'")
port, err := tools.Exec(`cat /www/panel/panel.conf | grep APP_PORT | awk -F '=' '{print $2}' | tr -d '\n'`)
if err != nil {
color.Redln("获取面板端口失败")
return nil
}
color.Greenln("面板端口: " + port)
case "getEntrance":
color.Greenln("面板入口: " + facades.Config().GetString("http.entrance"))
case "deleteEntrance":
oldEntrance := tools.Exec(`cat /www/panel/panel.conf | grep APP_ENTRANCE | awk -F '=' '{print $2}' | tr -d '\n'`)
tools.Exec("sed -i 's!APP_ENTRANCE=" + oldEntrance + "!APP_ENTRANCE=/!g' /www/panel/panel.conf")
oldEntrance, err := tools.Exec(`cat /www/panel/panel.conf | grep APP_ENTRANCE | awk -F '=' '{print $2}' | tr -d '\n'`)
if err != nil {
color.Redln("获取面板入口失败")
return nil
}
if _, err = tools.Exec("sed -i 's!APP_ENTRANCE=" + oldEntrance + "!APP_ENTRANCE=/!g' /www/panel/panel.conf"); err != nil {
color.Redln("删除面板入口失败")
return nil
}
color.Greenln("删除面板入口成功")
@@ -245,7 +261,10 @@ func (receiver *Panel) Handle(ctx console.Context) error {
}
backupFile := path + "/" + website.Name + "_" + carbon.Now().ToShortDateTimeString() + ".zip"
tools.Exec(`cd '` + website.Path + `' && zip -r '` + backupFile + `' .`)
if _, err := tools.Exec(`cd '` + website.Path + `' && zip -r '` + backupFile + `' .`); err != nil {
color.Redln("|-备份失败: " + err.Error())
return nil
}
color.Greenln("|-备份成功")
case "mysql":
@@ -261,10 +280,16 @@ func (receiver *Panel) Handle(ctx console.Context) error {
color.Greenln("|-目标MySQL数据库: " + name)
color.Greenln("|-开始导出")
tools.Exec(`mysqldump -uroot ` + name + ` > /tmp/` + backupFile + ` 2>&1`)
if _, err = tools.Exec(`mysqldump -uroot ` + name + ` > /tmp/` + backupFile + ` 2>&1`); err != nil {
color.Redln("|-导出失败: " + err.Error())
return nil
}
color.Greenln("|-导出成功")
color.Greenln("|-开始压缩")
tools.Exec("cd /tmp && zip -r " + backupFile + ".zip " + backupFile)
if _, err = tools.Exec("cd /tmp && zip -r " + backupFile + ".zip " + backupFile); err != nil {
color.Redln("|-压缩失败: " + err.Error())
return nil
}
tools.Remove("/tmp/" + backupFile)
color.Greenln("|-压缩成功")
color.Greenln("|-开始移动")
@@ -278,7 +303,12 @@ func (receiver *Panel) Handle(ctx console.Context) error {
case "postgresql":
backupFile := name + "_" + carbon.Now().ToShortDateTimeString() + ".sql"
check := tools.Exec(`su - postgres -c "psql -l" 2>&1`)
check, err := tools.Exec(`su - postgres -c "psql -l" 2>&1`)
if err != nil {
color.Redln("|-获取数据库失败: " + err.Error())
color.Greenln(hr)
return nil
}
if strings.Contains(check, name) {
color.Redln("|-数据库不存在")
color.Greenln(hr)
@@ -287,10 +317,16 @@ func (receiver *Panel) Handle(ctx console.Context) error {
color.Greenln("|-目标PostgreSQL数据库: " + name)
color.Greenln("|-开始导出")
tools.Exec(`su - postgres -c "pg_dump '` + name + `'" > /tmp/` + backupFile + ` 2>&1`)
if _, err = tools.Exec(`su - postgres -c "pg_dump '` + name + `'" > /tmp/` + backupFile + ` 2>&1`); err != nil {
color.Redln("|-导出失败: " + err.Error())
return nil
}
color.Greenln("|-导出成功")
color.Greenln("|-开始压缩")
tools.Exec("cd /tmp && zip -r " + backupFile + ".zip " + backupFile)
if _, err = tools.Exec("cd /tmp && zip -r " + backupFile + ".zip " + backupFile); err != nil {
color.Redln("|-压缩失败: " + err.Error())
return nil
}
tools.Remove("/tmp/" + backupFile)
color.Greenln("|-压缩成功")
color.Greenln("|-开始移动")
@@ -360,8 +396,14 @@ func (receiver *Panel) Handle(ctx console.Context) error {
}
backupPath := "/www/wwwlogs/" + website.Name + "_" + carbon.Now().ToShortDateTimeString() + ".log.zip"
tools.Exec(`cd /www/wwwlogs && zip -r ` + backupPath + ` ` + website.Name + ".log")
tools.Exec(`echo "" > ` + logPath)
if _, err := tools.Exec(`cd /www/wwwlogs && zip -r ` + backupPath + ` ` + website.Name + ".log"); err != nil {
color.Redln("|-备份失败: " + err.Error())
return nil
}
if _, err := tools.Exec(`echo "" > ` + logPath); err != nil {
color.Redln("|-清空失败: " + err.Error())
return nil
}
color.Greenln("|-切割成功")
color.Greenln(hr)

View File

@@ -35,7 +35,7 @@ func Success(ctx http.Context, data any) http.Response {
func Error(ctx http.Context, code int, message string) http.Response {
return ctx.Response().Json(http.StatusOK, &ErrorResponse{
Code: code,
Message: message,
Message: "错误: " + message,
})
}

View File

@@ -26,7 +26,7 @@ func NewCronController() *CronController {
}
// List 获取计划任务列表
func (c *CronController) List(ctx http.Context) http.Response {
func (r *CronController) List(ctx http.Context) http.Response {
limit := ctx.Request().QueryInt("limit", 10)
page := ctx.Request().QueryInt("page", 1)
@@ -34,7 +34,9 @@ func (c *CronController) List(ctx http.Context) http.Response {
var total int64
err := facades.Orm().Query().Paginate(page, limit, &crons, &total)
if err != nil {
facades.Log().Info("[面板][CronController] 查询计划任务列表失败 ", err)
facades.Log().Request(ctx.Request()).Tags("面板", "计划任务").With(map[string]any{
"error": err.Error(),
}).Info("查询计划任务列表失败")
return ErrorSystem(ctx)
}
@@ -45,7 +47,7 @@ func (c *CronController) List(ctx http.Context) http.Response {
}
// Add 添加计划任务
func (c *CronController) Add(ctx http.Context) http.Response {
func (r *CronController) Add(ctx http.Context) http.Response {
validator, err := ctx.Request().Validate(map[string]string{
"name": "required|min_len:1|max_len:255",
"time": "required",
@@ -75,7 +77,7 @@ func (c *CronController) Add(ctx http.Context) http.Response {
}
backupPath := ctx.Request().Input("backup_path")
if len(backupPath) == 0 {
backupPath = c.setting.Get(models.SettingKeyBackupPath) + "/" + backupType
backupPath = r.setting.Get(models.SettingKeyBackupPath) + "/" + backupType
}
backupSave := ctx.Request().InputInt("save", 10)
shell = `#!/bin/bash
@@ -111,19 +113,18 @@ panel cutoff ${name} ${save} 2>&1
shellDir := "/www/server/cron/"
shellLogDir := "/www/server/cron/logs/"
if !tools.Exists(shellDir) {
facades.Log().Info("[面板][CronController] 计划任务目录不存在")
return Error(ctx, http.StatusInternalServerError, "计划任务目录不存在")
}
if !tools.Exists(shellLogDir) {
facades.Log().Info("[面板][CronController] 计划任务日志目录不存在")
return Error(ctx, http.StatusInternalServerError, "计划任务日志目录不存在")
}
shellFile := strconv.Itoa(int(carbon.Now().Timestamp())) + tools.RandomString(16)
if err = tools.Write(shellDir+shellFile+".sh", shell, 0700); err != nil {
facades.Log().Info("[面板][CronController] 创建计划任务脚本失败 ", err)
return ErrorSystem(ctx)
return Error(ctx, http.StatusInternalServerError, err.Error())
}
if out, err := tools.Exec("dos2unix " + shellDir + shellFile + ".sh"); err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
tools.Exec("dos2unix " + shellDir + shellFile + ".sh")
var cron models.Cron
cron.Name = ctx.Request().Input("name")
@@ -135,11 +136,15 @@ panel cutoff ${name} ${save} 2>&1
err = facades.Orm().Query().Create(&cron)
if err != nil {
facades.Log().Info("[面板][CronController] 创建计划任务失败 ", err)
facades.Log().Request(ctx.Request()).Tags("面板", "计划任务").With(map[string]any{
"error": err.Error(),
}).Info("保存计划任务失败")
return ErrorSystem(ctx)
}
c.cron.AddToSystem(cron)
if err := r.cron.AddToSystem(cron); err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
return Success(ctx, http.Json{
"id": cron.ID,
@@ -147,7 +152,7 @@ panel cutoff ${name} ${save} 2>&1
}
// Script 获取脚本内容
func (c *CronController) Script(ctx http.Context) http.Response {
func (r *CronController) Script(ctx http.Context) http.Response {
var cron models.Cron
err := facades.Orm().Query().Where("id", ctx.Request().Input("id")).FirstOrFail(&cron)
if err != nil {
@@ -158,7 +163,7 @@ func (c *CronController) Script(ctx http.Context) http.Response {
}
// Update 更新计划任务
func (c *CronController) Update(ctx http.Context) http.Response {
func (r *CronController) Update(ctx http.Context) http.Response {
validator, err := ctx.Request().Validate(map[string]string{
"name": "required|min_len:1|max_len:255",
"time": "required",
@@ -190,38 +195,47 @@ func (c *CronController) Update(ctx http.Context) http.Response {
cron.Name = ctx.Request().Input("name")
err = facades.Orm().Query().Save(&cron)
if err != nil {
facades.Log().Info("[面板][CronController] 更新计划任务失败 ", err)
facades.Log().Request(ctx.Request()).Tags("面板", "计划任务").With(map[string]any{
"error": err.Error(),
}).Info("更新计划任务失败")
return ErrorSystem(ctx)
}
if err = tools.Write(cron.Shell, ctx.Request().Input("script"), 0644); err != nil {
facades.Log().Info("[面板][CronController] 更新计划任务脚本失败 ", err)
return ErrorSystem(ctx)
return Error(ctx, http.StatusInternalServerError, err.Error())
}
if out, err := tools.Exec("dos2unix " + cron.Shell); err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
tools.Exec("dos2unix " + cron.Shell)
c.cron.DeleteFromSystem(cron)
if err := r.cron.DeleteFromSystem(cron); err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
if cron.Status {
c.cron.AddToSystem(cron)
if err := r.cron.AddToSystem(cron); err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
}
return Success(ctx, nil)
}
// Delete 删除计划任务
func (c *CronController) Delete(ctx http.Context) http.Response {
func (r *CronController) Delete(ctx http.Context) http.Response {
var cron models.Cron
err := facades.Orm().Query().Where("id", ctx.Request().Input("id")).FirstOrFail(&cron)
if err != nil {
if err := facades.Orm().Query().Where("id", ctx.Request().Input("id")).FirstOrFail(&cron); err != nil {
return Error(ctx, http.StatusUnprocessableEntity, "计划任务不存在")
}
c.cron.DeleteFromSystem(cron)
if err := r.cron.DeleteFromSystem(cron); err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
tools.Remove(cron.Shell)
_, err = facades.Orm().Query().Delete(&cron)
if err != nil {
facades.Log().Info("[面板][CronController] 删除计划任务失败 ", err)
if _, err := facades.Orm().Query().Delete(&cron); err != nil {
facades.Log().Request(ctx.Request()).Tags("面板", "计划任务").With(map[string]any{
"error": err.Error(),
}).Info("删除计划任务失败")
return ErrorSystem(ctx)
}
@@ -229,7 +243,7 @@ func (c *CronController) Delete(ctx http.Context) http.Response {
}
// Status 更新计划任务状态
func (c *CronController) Status(ctx http.Context) http.Response {
func (r *CronController) Status(ctx http.Context) http.Response {
validator, err := ctx.Request().Validate(map[string]string{
"status": "bool",
})
@@ -249,23 +263,28 @@ func (c *CronController) Status(ctx http.Context) http.Response {
cron.Status = ctx.Request().InputBool("status")
err = facades.Orm().Query().Save(&cron)
if err != nil {
facades.Log().Info("[面板][CronController] 更新计划任务状态失败 ", err)
facades.Log().Request(ctx.Request()).Tags("面板", "计划任务").With(map[string]any{
"error": err.Error(),
}).Info("更新计划任务状态失败")
return ErrorSystem(ctx)
}
c.cron.DeleteFromSystem(cron)
if err := r.cron.DeleteFromSystem(cron); err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
if cron.Status {
c.cron.AddToSystem(cron)
if err := r.cron.AddToSystem(cron); err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
}
return Success(ctx, nil)
}
// Log 获取计划任务日志
func (c *CronController) Log(ctx http.Context) http.Response {
func (r *CronController) Log(ctx http.Context) http.Response {
var cron models.Cron
err := facades.Orm().Query().Where("id", ctx.Request().Input("id")).FirstOrFail(&cron)
if err != nil {
if err := facades.Orm().Query().Where("id", ctx.Request().Input("id")).FirstOrFail(&cron); err != nil {
return Error(ctx, http.StatusUnprocessableEntity, "计划任务不存在")
}
@@ -273,7 +292,10 @@ func (c *CronController) Log(ctx http.Context) http.Response {
return Error(ctx, http.StatusUnprocessableEntity, "日志文件不存在")
}
log := tools.Exec("tail -n 1000 " + cron.Log)
log, err := tools.Exec("tail -n 1000 " + cron.Log)
if err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
return Success(ctx, log)
}

View File

@@ -34,25 +34,20 @@ func NewInfoController() *InfoController {
}
// Name 获取面板名称
func (c *InfoController) Name(ctx http.Context) http.Response {
var setting models.Setting
err := facades.Orm().Query().Where("key", "name").First(&setting)
if err != nil {
facades.Log().Info("[面板][InfoController] 查询面板名称失败 ", err)
return ErrorSystem(ctx)
}
func (r *InfoController) Name(ctx http.Context) http.Response {
return Success(ctx, http.Json{
"name": setting.Value,
"name": r.setting.Get(models.SettingKeyName),
})
}
// HomePlugins 获取首页插件
func (c *InfoController) HomePlugins(ctx http.Context) http.Response {
func (r *InfoController) HomePlugins(ctx http.Context) http.Response {
var plugins []models.Plugin
err := facades.Orm().Query().Where("show", 1).Find(&plugins)
if err != nil {
facades.Log().Info("[面板][InfoController] 查询首页插件失败 ", err)
facades.Log().Request(ctx.Request()).Tags("面板", "基础信息").With(map[string]any{
"error": err.Error(),
}).Info("获取首页插件失败")
return ErrorSystem(ctx)
}
@@ -73,12 +68,12 @@ func (c *InfoController) HomePlugins(ctx http.Context) http.Response {
}
// NowMonitor 获取当前监控信息
func (c *InfoController) NowMonitor(ctx http.Context) http.Response {
func (r *InfoController) NowMonitor(ctx http.Context) http.Response {
return Success(ctx, tools.GetMonitoringInfo())
}
// SystemInfo 获取系统信息
func (c *InfoController) SystemInfo(ctx http.Context) http.Response {
func (r *InfoController) SystemInfo(ctx http.Context) http.Response {
monitorInfo := tools.GetMonitoringInfo()
return Success(ctx, http.Json{
@@ -89,7 +84,7 @@ func (c *InfoController) SystemInfo(ctx http.Context) http.Response {
}
// CountInfo 获取面板统计信息
func (c *InfoController) CountInfo(ctx http.Context) http.Response {
func (r *InfoController) CountInfo(ctx http.Context) http.Response {
var websiteCount int64
err := facades.Orm().Query().Model(models.Website{}).Count(&websiteCount)
if err != nil {
@@ -110,26 +105,26 @@ func (c *InfoController) CountInfo(ctx http.Context) http.Response {
}
var databaseCount int64
if mysqlInstalled {
status := tools.Exec("systemctl status mysqld | grep Active | grep -v grep | awk '{print $2}'")
if status == "active" {
rootPassword := c.setting.Get(models.SettingKeyMysqlRootPassword)
status, err := tools.Exec("systemctl status mysqld | grep Active | grep -v grep | awk '{print $2}'")
if status == "active" && err == nil {
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
type database struct {
Name string `json:"name"`
}
db, err := sql.Open("mysql", "root:"+rootPassword+"@unix(/tmp/mysql.sock)/")
if err != nil {
facades.Log().Request(ctx.Request()).With(map[string]any{
facades.Log().Request(ctx.Request()).Tags("面板", "基础信息").With(map[string]any{
"error": err.Error(),
}).Info("[面板][InfoController] 获取数据库列表失败")
}).Info("获取数据库列表失败")
databaseCount = -1
} else {
defer db.Close()
rows, err := db.Query("SHOW DATABASES")
if err != nil {
facades.Log().Request(ctx.Request()).With(map[string]any{
facades.Log().Request(ctx.Request()).Tags("面板", "基础信息").With(map[string]any{
"error": err.Error(),
}).Info("[面板][InfoController] 获取数据库列表失败")
}).Info("获取数据库列表失败")
databaseCount = -1
} else {
defer rows.Close()
@@ -152,29 +147,31 @@ func (c *InfoController) CountInfo(ctx http.Context) http.Response {
}
}
if postgresqlInstalled {
status := tools.Exec("systemctl status postgresql | grep Active | grep -v grep | awk '{print $2}'")
if status == "active" {
raw := tools.Exec(`echo "\l" | su - postgres -c "psql"`)
databases := strings.Split(raw, "\n")
if len(databases) >= 4 {
databases = databases[3 : len(databases)-1]
for _, db := range databases {
parts := strings.Split(db, "|")
if len(parts) != 9 || len(strings.TrimSpace(parts[0])) == 0 || strings.TrimSpace(parts[0]) == "template0" || strings.TrimSpace(parts[0]) == "template1" || strings.TrimSpace(parts[0]) == "postgres" {
continue
}
status, err := tools.Exec("systemctl status postgresql | grep Active | grep -v grep | awk '{print $2}'")
if status == "active" && err == nil {
raw, err := tools.Exec(`echo "\l" | su - postgres -c "psql"`)
if err == nil {
databases := strings.Split(raw, "\n")
if len(databases) >= 4 {
databases = databases[3 : len(databases)-1]
for _, db := range databases {
parts := strings.Split(db, "|")
if len(parts) != 9 || len(strings.TrimSpace(parts[0])) == 0 || strings.TrimSpace(parts[0]) == "template0" || strings.TrimSpace(parts[0]) == "template1" || strings.TrimSpace(parts[0]) == "postgres" {
continue
}
databaseCount++
databaseCount++
}
}
}
}
}
var ftpCount int64
var ftpPlugin = c.plugin.GetInstalledBySlug("pureftpd")
var ftpPlugin = r.plugin.GetInstalledBySlug("pureftpd")
if ftpPlugin.ID != 0 {
listRaw := tools.Exec("pure-pw list")
if len(listRaw) != 0 {
listRaw, err := tools.Exec("pure-pw list")
if len(listRaw) != 0 && err == nil {
listArr := strings.Split(listRaw, "\n")
ftpCount = int64(len(listArr))
}
@@ -195,7 +192,7 @@ func (c *InfoController) CountInfo(ctx http.Context) http.Response {
}
// InstalledDbAndPhp 获取已安装的数据库和 PHP 版本
func (c *InfoController) InstalledDbAndPhp(ctx http.Context) http.Response {
func (r *InfoController) InstalledDbAndPhp(ctx http.Context) http.Response {
var php []models.Plugin
err := facades.Orm().Query().Where("slug like ?", "php%").Find(&php)
if err != nil {
@@ -230,7 +227,7 @@ func (c *InfoController) InstalledDbAndPhp(ctx http.Context) http.Response {
continue
}
phpData = append(phpData, data{Value: strings.ReplaceAll(p.Slug, "php", ""), Label: c.plugin.GetBySlug(p.Slug).Name})
phpData = append(phpData, data{Value: strings.ReplaceAll(p.Slug, "php", ""), Label: r.plugin.GetBySlug(p.Slug).Name})
}
if mysqlInstalled {
@@ -247,7 +244,7 @@ func (c *InfoController) InstalledDbAndPhp(ctx http.Context) http.Response {
}
// CheckUpdate 检查面板更新
func (c *InfoController) CheckUpdate(ctx http.Context) http.Response {
func (r *InfoController) CheckUpdate(ctx http.Context) http.Response {
version := facades.Config().GetString("panel.version")
remote, err := tools.GetLatestPanelVersion()
if err != nil {
@@ -266,7 +263,7 @@ func (c *InfoController) CheckUpdate(ctx http.Context) http.Response {
}
// UpdateInfo 获取更新信息
func (c *InfoController) UpdateInfo(ctx http.Context) http.Response {
func (r *InfoController) UpdateInfo(ctx http.Context) http.Response {
version := facades.Config().GetString("panel.version")
current, err := tools.GetLatestPanelVersion()
if err != nil {
@@ -296,7 +293,7 @@ func (c *InfoController) UpdateInfo(ctx http.Context) http.Response {
}
// Update 更新面板
func (c *InfoController) Update(ctx http.Context) http.Response {
func (r *InfoController) Update(ctx http.Context) http.Response {
var task models.Task
err := facades.Orm().Query().Where("status", models.TaskStatusRunning).OrWhere("status", models.TaskStatusWaiting).FirstOrFail(&task)
if err == nil {
@@ -305,18 +302,18 @@ func (c *InfoController) Update(ctx http.Context) http.Response {
panel, err := tools.GetLatestPanelVersion()
if err != nil {
facades.Log().Request(ctx.Request()).With(map[string]any{
facades.Log().Request(ctx.Request()).Tags("面板", "基础信息").With(map[string]any{
"error": err.Error(),
}).Info("[面板][InfoController] 获取最新版本失败")
}).Info("获取最新版本失败")
return Error(ctx, http.StatusInternalServerError, "获取最新版本失败")
}
err = tools.UpdatePanel(panel)
if err != nil {
facades.Log().Request(ctx.Request()).With(map[string]any{
facades.Log().Request(ctx.Request()).Tags("面板", "基础信息").With(map[string]any{
"error": err.Error(),
}).Info("[面板][InfoController] 更新面板失败")
return Error(ctx, http.StatusInternalServerError, "更新失败: "+err.Error())
}).Info("更新面板失败")
return Error(ctx, http.StatusInternalServerError, err.Error())
}
tools.RestartPanel()
@@ -324,7 +321,7 @@ func (c *InfoController) Update(ctx http.Context) http.Response {
}
// Restart 重启面板
func (c *InfoController) Restart(ctx http.Context) http.Response {
func (r *InfoController) Restart(ctx http.Context) http.Response {
var task models.Task
err := facades.Orm().Query().Where("status", models.TaskStatusRunning).OrWhere("status", models.TaskStatusWaiting).FirstOrFail(&task)
if err == nil {

View File

@@ -7,6 +7,7 @@ import (
"github.com/goravel/framework/facades"
"github.com/goravel/framework/support/carbon"
"github.com/spf13/cast"
"panel/app/models"
"panel/app/services"
)
@@ -26,7 +27,10 @@ func (r *MonitorController) Switch(ctx http.Context) http.Response {
value := ctx.Request().InputBool("monitor")
err := r.setting.Set(models.SettingKeyMonitor, cast.ToString(value))
if err != nil {
facades.Log().Info("[面板][MonitorController] 更新监控开关失败 ", err)
facades.Log().Request(ctx.Request()).Tags("面板", "资源监控").With(map[string]any{
"monitor": value,
"error": err.Error(),
}).Info("更新监控开关失败")
return ErrorSystem(ctx)
}
@@ -38,7 +42,10 @@ func (r *MonitorController) SaveDays(ctx http.Context) http.Response {
days := ctx.Request().Input("days")
err := r.setting.Set(models.SettingKeyMonitorDays, days)
if err != nil {
facades.Log().Info("[面板][MonitorController] 更新监控天数失败 ", err)
facades.Log().Request(ctx.Request()).Tags("面板", "资源监控").With(map[string]any{
"days": days,
"error": err.Error(),
}).Info("更新监控开关失败")
return ErrorSystem(ctx)
}
@@ -60,7 +67,9 @@ func (r *MonitorController) SwitchAndDays(ctx http.Context) http.Response {
func (r *MonitorController) Clear(ctx http.Context) http.Response {
_, err := facades.Orm().Query().Where("1 = 1").Delete(&models.Monitor{})
if err != nil {
facades.Log().Info("[面板][MonitorController] 清空监控数据失败 ", err)
facades.Log().Request(ctx.Request()).Tags("面板", "资源监控").With(map[string]any{
"error": err.Error(),
}).Info("清空监控数据失败")
return ErrorSystem(ctx)
}
@@ -77,7 +86,11 @@ func (r *MonitorController) List(ctx http.Context) http.Response {
var monitors []models.Monitor
err := facades.Orm().Query().Where("created_at >= ?", startTime.ToDateTimeString()).Where("created_at <= ?", endTime.ToDateTimeString()).Get(&monitors)
if err != nil {
facades.Log().Info("[面板][MonitorController] 查询监控数据失败 ", err)
facades.Log().Request(ctx.Request()).Tags("面板", "资源监控").With(map[string]any{
"start": startTime.ToDateTimeString(),
"end": endTime.ToDateTimeString(),
"error": err.Error(),
}).Info("获取监控数据失败")
return ErrorSystem(ctx)
}

View File

@@ -100,7 +100,9 @@ func (r *PluginController) Install(ctx http.Context) http.Response {
installedPlugin := r.plugin.GetInstalledBySlug(slug)
installedPlugins, err := r.plugin.AllInstalled()
if err != nil {
facades.Log().Info("[面板][PluginController] 获取已安装插件失败")
facades.Log().Request(ctx.Request()).Tags("面板", "插件中心").With(map[string]any{
"slug": slug,
}).Info("检查插件安装状态失败")
return ErrorSystem(ctx)
}
@@ -141,7 +143,10 @@ func (r *PluginController) Install(ctx http.Context) http.Response {
task.Shell = plugin.Install + " >> /tmp/" + plugin.Slug + ".log 2>&1"
task.Log = "/tmp/" + plugin.Slug + ".log"
if err := facades.Orm().Query().Create(&task); err != nil {
facades.Log().Info("[面板][PluginController] 创建任务失败: " + err.Error())
facades.Log().Request(ctx.Request()).Tags("面板", "插件中心").With(map[string]any{
"slug": slug,
"err": err.Error(),
}).Info("创建任务失败")
return ErrorSystem(ctx)
}
@@ -156,7 +161,9 @@ func (r *PluginController) Uninstall(ctx http.Context) http.Response {
installedPlugin := r.plugin.GetInstalledBySlug(slug)
installedPlugins, err := r.plugin.AllInstalled()
if err != nil {
facades.Log().Info("[面板][PluginController] 获取已安装插件失败")
facades.Log().Request(ctx.Request()).Tags("面板", "插件中心").With(map[string]any{
"slug": slug,
}).Info("检查插件安装状态失败")
return ErrorSystem(ctx)
}
@@ -197,7 +204,10 @@ func (r *PluginController) Uninstall(ctx http.Context) http.Response {
task.Shell = plugin.Uninstall + " >> /tmp/" + plugin.Slug + ".log 2>&1"
task.Log = "/tmp/" + plugin.Slug + ".log"
if err := facades.Orm().Query().Create(&task); err != nil {
facades.Log().Info("[面板][PluginController] 创建任务失败: " + err.Error())
facades.Log().Request(ctx.Request()).Tags("面板", "插件中心").With(map[string]any{
"slug": slug,
"err": err.Error(),
}).Info("创建任务失败")
return ErrorSystem(ctx)
}
@@ -212,7 +222,9 @@ func (r *PluginController) Update(ctx http.Context) http.Response {
installedPlugin := r.plugin.GetInstalledBySlug(slug)
installedPlugins, err := r.plugin.AllInstalled()
if err != nil {
facades.Log().Info("[面板][PluginController] 获取已安装插件失败")
facades.Log().Request(ctx.Request()).Tags("面板", "插件中心").With(map[string]any{
"slug": slug,
}).Info("检查插件安装状态失败")
return ErrorSystem(ctx)
}
@@ -253,7 +265,10 @@ func (r *PluginController) Update(ctx http.Context) http.Response {
task.Shell = plugin.Update + " >> /tmp/" + plugin.Slug + ".log 2>&1"
task.Log = "/tmp/" + plugin.Slug + ".log"
if err := facades.Orm().Query().Create(&task); err != nil {
facades.Log().Info("[面板][PluginController] 创建任务失败: " + err.Error())
facades.Log().Request(ctx.Request()).Tags("面板", "插件中心").With(map[string]any{
"slug": slug,
"err": err.Error(),
}).Info("创建任务失败")
return ErrorSystem(ctx)
}
@@ -268,7 +283,10 @@ func (r *PluginController) UpdateShow(ctx http.Context) http.Response {
var plugin models.Plugin
if err := facades.Orm().Query().Where("slug", slug).First(&plugin); err != nil {
facades.Log().Info("[面板][PluginController] 查询插件失败: " + err.Error())
facades.Log().Request(ctx.Request()).Tags("面板", "插件中心").With(map[string]any{
"slug": slug,
"err": err.Error(),
}).Info("获取插件失败")
return ErrorSystem(ctx)
}
if plugin.ID == 0 {
@@ -277,7 +295,10 @@ func (r *PluginController) UpdateShow(ctx http.Context) http.Response {
plugin.Show = show
if err := facades.Orm().Query().Save(&plugin); err != nil {
facades.Log().Info("[面板][PluginController] 更新插件失败: " + err.Error())
facades.Log().Request(ctx.Request()).Tags("面板", "插件中心").With(map[string]any{
"slug": slug,
"err": err.Error(),
}).Info("更新插件失败")
return ErrorSystem(ctx)
}

View File

@@ -31,16 +31,12 @@ func (r *Fail2banController) Status(ctx http.Context) http.Response {
return check
}
status := tools.Exec("systemctl status fail2ban | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
status, err := tools.ServiceStatus("fail2ban")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取服务运行状态失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, status)
}
// Reload 重载配置
@@ -50,17 +46,11 @@ func (r *Fail2banController) Reload(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl reload fail2ban")
status := tools.Exec("systemctl status fail2ban | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取服务运行状态失败")
if _, err := tools.Exec("systemctl reload fail2ban"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重载配置失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
// Restart 重启服务
@@ -70,17 +60,11 @@ func (r *Fail2banController) Restart(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl restart fail2ban")
status := tools.Exec("systemctl status fail2ban | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取服务运行状态失败")
if err := tools.ServiceRestart("fail2ban"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重启服务失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
// Start 启动服务
@@ -90,17 +74,11 @@ func (r *Fail2banController) Start(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl start fail2ban")
status := tools.Exec("systemctl status fail2ban | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取服务运行状态失败")
if err := tools.ServiceStart("fail2ban"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "启动服务失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
// Stop 停止服务
@@ -110,17 +88,15 @@ func (r *Fail2banController) Stop(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl stop fail2ban")
status := tools.Exec("systemctl status fail2ban | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
if err := tools.ServiceStop("fail2ban"); err != nil {
return nil
}
status, err := tools.ServiceStatus("fail2ban")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取服务运行状态失败")
}
if status != "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, !status)
}
// List 所有 Fail2ban 规则
@@ -289,6 +265,7 @@ ignoreregex =
var logPath string
var filter string
var port string
var err error
switch jailName {
case "ssh":
if tools.IsDebian() {
@@ -297,19 +274,19 @@ ignoreregex =
logPath = "/var/log/secure"
}
filter = "sshd"
port = tools.Exec("cat /etc/ssh/sshd_config | grep 'Port ' | awk '{print $2}'")
port, err = tools.Exec("cat /etc/ssh/sshd_config | grep 'Port ' | awk '{print $2}'")
case "mysql":
logPath = "/www/server/mysql/mysql-error.log"
filter = "mysqld-auth"
port = tools.Exec("cat /www/server/mysql/conf/my.cnf | grep 'port' | head -n 1 | awk '{print $3}'")
port, err = tools.Exec("cat /www/server/mysql/conf/my.cnf | grep 'port' | head -n 1 | awk '{print $3}'")
case "pure-ftpd":
logPath = "/var/log/messages"
filter = "pure-ftpd"
port = tools.Exec(`cat /www/server/pure-ftpd/etc/pure-ftpd.conf | grep "Bind" | awk '{print $2}' | awk -F "," '{print $2}'`)
port, err = tools.Exec(`cat /www/server/pure-ftpd/etc/pure-ftpd.conf | grep "Bind" | awk '{print $2}' | awk -F "," '{print $2}'`)
default:
return controllers.Error(ctx, http.StatusUnprocessableEntity, "未知服务")
}
if len(port) == 0 {
if len(port) == 0 || err != nil {
return controllers.Error(ctx, http.StatusUnprocessableEntity, "获取服务端口失败,请检查是否安装")
}
@@ -332,7 +309,10 @@ logpath = ` + logPath + `
}
}
tools.Exec("fail2ban-client reload")
if _, err := tools.Exec("fail2ban-client reload"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重载配置失败")
}
return controllers.Success(ctx, nil)
}
@@ -356,7 +336,10 @@ func (r *Fail2banController) Delete(ctx http.Context) http.Response {
return controllers.Error(ctx, http.StatusInternalServerError, "写入Fail2ban规则失败")
}
tools.Exec("fail2ban-client reload")
if _, err := tools.Exec("fail2ban-client reload"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重载配置失败")
}
return controllers.Success(ctx, nil)
}
@@ -372,9 +355,18 @@ func (r *Fail2banController) BanList(ctx http.Context) http.Response {
return controllers.Error(ctx, http.StatusUnprocessableEntity, "缺少参数")
}
currentlyBan := tools.Exec(`fail2ban-client status ` + name + ` | grep "Currently banned" | awk '{print $4}'`)
totalBan := tools.Exec(`fail2ban-client status ` + name + ` | grep "Total banned" | awk '{print $4}'`)
bannedIp := tools.Exec(`fail2ban-client status ` + name + ` | grep "Banned IP list" | awk -F ":" '{print $2}'`)
currentlyBan, err := tools.Exec(`fail2ban-client status ` + name + ` | grep "Currently banned" | awk '{print $4}'`)
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取封禁列表失败")
}
totalBan, err := tools.Exec(`fail2ban-client status ` + name + ` | grep "Total banned" | awk '{print $4}'`)
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取封禁列表失败")
}
bannedIp, err := tools.Exec(`fail2ban-client status ` + name + ` | grep "Banned IP list" | awk -F ":" '{print $2}'`)
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取封禁列表失败")
}
bannedIpList := strings.Split(bannedIp, " ")
var list []map[string]string
@@ -410,7 +402,10 @@ func (r *Fail2banController) Unban(ctx http.Context) http.Response {
return controllers.Error(ctx, http.StatusUnprocessableEntity, "缺少参数")
}
tools.Exec("fail2ban-client set " + name + " unbanip " + ip)
if _, err := tools.Exec("fail2ban-client set " + name + " unbanip " + ip); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "解封失败")
}
return controllers.Success(ctx, nil)
}
@@ -438,7 +433,10 @@ func (r *Fail2banController) SetWhiteList(ctx http.Context) http.Response {
if err := tools.Write("/etc/fail2ban/jail.local", raw, 0644); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "写入Fail2ban规则失败")
}
tools.Exec("fail2ban-client reload")
if _, err := tools.Exec("fail2ban-client reload"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重载配置失败")
}
return controllers.Success(ctx, nil)
}

View File

@@ -4,10 +4,8 @@ import (
"database/sql"
"fmt"
"regexp"
"strings"
"github.com/goravel/framework/contracts/http"
"github.com/goravel/framework/facades"
"github.com/spf13/cast"
"panel/app/http/controllers"
@@ -35,16 +33,12 @@ func (r *Mysql57Controller) Status(ctx http.Context) http.Response {
return check
}
status := tools.Exec("systemctl status mysqld | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
status, err := tools.ServiceStatus("mysqld")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取MySQL状态失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, status)
}
// Reload 重载配置
@@ -54,17 +48,11 @@ func (r *Mysql57Controller) Reload(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl reload mysqld")
status := tools.Exec("systemctl status mysqld | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取MySQL状态失败")
if err := tools.ServiceReload("mysqld"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重载MySQL失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
// Restart 重启服务
@@ -74,17 +62,11 @@ func (r *Mysql57Controller) Restart(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl restart mysqld")
status := tools.Exec("systemctl status mysqld | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取MySQL状态失败")
if err := tools.ServiceRestart("mysqld"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重启MySQL服务失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
// Start 启动服务
@@ -94,17 +76,11 @@ func (r *Mysql57Controller) Start(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl start mysqld")
status := tools.Exec("systemctl status mysqld | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取MySQL状态失败")
if err := tools.ServiceStart("mysqld"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "启动MySQL服务失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
// Stop 停止服务
@@ -114,17 +90,11 @@ func (r *Mysql57Controller) Stop(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl stop mysqld")
status := tools.Exec("systemctl status mysqld | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取MySQL状态失败")
if err := tools.ServiceStop("mysqld"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "停止MySQL服务失败")
}
if status != "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
// GetConfig 获取配置
@@ -174,16 +144,16 @@ func (r *Mysql57Controller) Load(ctx http.Context) http.Response {
return controllers.Error(ctx, http.StatusUnprocessableEntity, "MySQL root密码为空")
}
status := tools.Exec("systemctl status mysqld | grep Active | grep -v grep | awk '{print $2}'")
if status != "active" {
return controllers.Error(ctx, http.StatusInternalServerError, "MySQL 已停止运行")
status, err := tools.ServiceStatus("mysqld")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取MySQL状态失败")
}
if !status {
return controllers.Error(ctx, http.StatusInternalServerError, "MySQL 未运行")
}
raw := tools.Exec("/www/server/mysql/bin/mysqladmin -uroot -p" + rootPassword + " extended-status 2>&1")
if strings.Contains(raw, "Access denied for user") {
return controllers.Error(ctx, http.StatusUnprocessableEntity, "MySQL root密码错误")
}
if !strings.Contains(raw, "Uptime") {
raw, err := tools.Exec("/www/server/mysql/bin/mysqladmin -uroot -p" + rootPassword + " extended-status 2>&1")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取MySQL负载失败")
}
@@ -244,7 +214,11 @@ func (r *Mysql57Controller) ErrorLog(ctx http.Context) http.Response {
return check
}
log := tools.Escape(tools.Exec("tail -n 100 /www/server/mysql/mysql-error.log"))
log, err := tools.Exec("tail -n 100 /www/server/mysql/mysql-error.log")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, log)
}
return controllers.Success(ctx, log)
}
@@ -255,8 +229,11 @@ func (r *Mysql57Controller) ClearErrorLog(ctx http.Context) http.Response {
return check
}
tools.Exec("echo '' > /www/server/mysql/mysql-error.log")
return controllers.Success(ctx, "清空错误日志成功")
if out, err := tools.Exec("echo '' > /www/server/mysql/mysql-error.log"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}
// SlowLog 获取慢查询日志
@@ -266,7 +243,11 @@ func (r *Mysql57Controller) SlowLog(ctx http.Context) http.Response {
return check
}
log := tools.Escape(tools.Exec("tail -n 100 /www/server/mysql/mysql-slow.log"))
log, err := tools.Exec("tail -n 100 /www/server/mysql/mysql-slow.log")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, log)
}
return controllers.Success(ctx, log)
}
@@ -277,8 +258,10 @@ func (r *Mysql57Controller) ClearSlowLog(ctx http.Context) http.Response {
return check
}
tools.Exec("echo '' > /www/server/mysql/mysql-slow.log")
return controllers.Success(ctx, "清空慢查询日志成功")
if out, err := tools.Exec("echo '' > /www/server/mysql/mysql-slow.log"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}
// GetRootPassword 获取root密码
@@ -303,11 +286,11 @@ func (r *Mysql57Controller) SetRootPassword(ctx http.Context) http.Response {
return check
}
status := tools.Exec("systemctl status mysqld | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
status, err := tools.ServiceStatus("mysqld")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取MySQL状态失败")
}
if status != "active" {
if !status {
return controllers.Error(ctx, http.StatusInternalServerError, "MySQL 未运行")
}
@@ -318,17 +301,25 @@ func (r *Mysql57Controller) SetRootPassword(ctx http.Context) http.Response {
oldRootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
if oldRootPassword != rootPassword {
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + oldRootPassword + " -e \"ALTER USER 'root'@'localhost' IDENTIFIED BY '" + rootPassword + "';\"")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + oldRootPassword + " -e \"FLUSH PRIVILEGES;\"")
if _, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + oldRootPassword + " -e \"ALTER USER 'root'@'localhost' IDENTIFIED BY '" + rootPassword + "';\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "设置root密码失败")
}
if _, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + oldRootPassword + " -e \"FLUSH PRIVILEGES;\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "设置root密码失败")
}
err := r.setting.Set(models.SettingKeyMysqlRootPassword, rootPassword)
if err != nil {
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"ALTER USER 'root'@'localhost' IDENTIFIED BY '" + oldRootPassword + "';\"")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"FLUSH PRIVILEGES;\"")
if _, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"ALTER USER 'root'@'localhost' IDENTIFIED BY '" + oldRootPassword + "';\""); err != nil {
return nil
}
if _, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"FLUSH PRIVILEGES;\""); err != nil {
return nil
}
return controllers.Error(ctx, http.StatusInternalServerError, "设置root密码失败")
}
}
return controllers.Success(ctx, "设置root密码成功")
return controllers.Success(ctx, nil)
}
// DatabaseList 获取数据库列表
@@ -345,15 +336,13 @@ func (r *Mysql57Controller) DatabaseList(ctx http.Context) http.Response {
db, err := sql.Open("mysql", "root:"+rootPassword+"@unix(/tmp/mysql.sock)/")
if err != nil {
facades.Log().Info("[MySQL57] 连接数据库失败" + err.Error())
return controllers.Error(ctx, http.StatusInternalServerError, "连接数据库失败")
return controllers.Error(ctx, http.StatusInternalServerError, err.Error())
}
defer db.Close()
rows, err := db.Query("SHOW DATABASES")
if err != nil {
facades.Log().Info("[MySQL57] 获取数据库列表失败" + err.Error())
return controllers.Error(ctx, http.StatusInternalServerError, "获取数据库列表失败")
return controllers.Error(ctx, http.StatusInternalServerError, err.Error())
}
defer rows.Close()
@@ -369,7 +358,6 @@ func (r *Mysql57Controller) DatabaseList(ctx http.Context) http.Response {
}
if err := rows.Err(); err != nil {
facades.Log().Info("[MySQL57] 获取数据库列表失败" + err.Error())
return controllers.Error(ctx, http.StatusInternalServerError, "获取数据库列表失败")
}
@@ -418,12 +406,20 @@ func (r *Mysql57Controller) AddDatabase(ctx http.Context) http.Response {
user := ctx.Request().Input("user")
password := ctx.Request().Input("password")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"CREATE DATABASE IF NOT EXISTS " + database + " DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci;\"")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"CREATE USER '" + user + "'@'localhost' IDENTIFIED BY '" + password + "';\"")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"GRANT ALL PRIVILEGES ON " + database + ".* TO '" + user + "'@'localhost';\"")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"FLUSH PRIVILEGES;\"")
if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"CREATE DATABASE IF NOT EXISTS " + database + " DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci;\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"CREATE USER '" + user + "'@'localhost' IDENTIFIED BY '" + password + "';\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"GRANT ALL PRIVILEGES ON " + database + ".* TO '" + user + "'@'localhost';\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"FLUSH PRIVILEGES;\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, "添加数据库成功")
return controllers.Success(ctx, nil)
}
// DeleteDatabase 删除数据库
@@ -445,9 +441,11 @@ func (r *Mysql57Controller) DeleteDatabase(ctx http.Context) http.Response {
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
database := ctx.Request().Input("database")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"DROP DATABASE IF EXISTS " + database + ";\"")
if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"DROP DATABASE IF EXISTS " + database + ";\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, "删除数据库成功")
return controllers.Success(ctx, nil)
}
// BackupList 获取备份列表
@@ -459,8 +457,7 @@ func (r *Mysql57Controller) BackupList(ctx http.Context) http.Response {
backupList, err := r.backup.MysqlList()
if err != nil {
facades.Log().Info("[MySQL57] 获取备份列表失败:" + err.Error())
return controllers.Error(ctx, http.StatusInternalServerError, "获取备份列表失败")
return controllers.Error(ctx, http.StatusInternalServerError, err.Error())
}
page := ctx.Request().QueryInt("page", 1)
@@ -512,7 +509,7 @@ func (r *Mysql57Controller) UploadBackup(ctx http.Context) http.Response {
return controllers.Error(ctx, http.StatusUnprocessableEntity, "上传文件失败")
}
return controllers.Success(ctx, "上传文件成功")
return controllers.Success(ctx, nil)
}
// CreateBackup 创建备份
@@ -535,11 +532,10 @@ func (r *Mysql57Controller) CreateBackup(ctx http.Context) http.Response {
database := ctx.Request().Input("database")
err = r.backup.MysqlBackup(database)
if err != nil {
facades.Log().Info("[MYSQL57] 创建备份失败:" + err.Error())
return controllers.Error(ctx, http.StatusInternalServerError, "创建备份失败")
return controllers.Error(ctx, http.StatusInternalServerError, err.Error())
}
return controllers.Success(ctx, "备份成功")
return controllers.Success(ctx, nil)
}
// DeleteBackup 删除备份
@@ -563,7 +559,7 @@ func (r *Mysql57Controller) DeleteBackup(ctx http.Context) http.Response {
fileName := ctx.Request().Input("name")
tools.Remove(backupPath + "/" + fileName)
return controllers.Success(ctx, "删除备份成功")
return controllers.Success(ctx, nil)
}
// RestoreBackup 还原备份
@@ -586,11 +582,10 @@ func (r *Mysql57Controller) RestoreBackup(ctx http.Context) http.Response {
err = r.backup.MysqlRestore(ctx.Request().Input("database"), ctx.Request().Input("backup"))
if err != nil {
facades.Log().Info("[MYSQL57] 还原失败:" + err.Error())
return controllers.Error(ctx, http.StatusInternalServerError, "还原失败: "+err.Error())
return controllers.Error(ctx, http.StatusInternalServerError, err.Error())
}
return controllers.Success(ctx, "还原成功")
return controllers.Success(ctx, nil)
}
// UserList 用户列表
@@ -609,15 +604,13 @@ func (r *Mysql57Controller) UserList(ctx http.Context) http.Response {
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
db, err := sql.Open("mysql", "root:"+rootPassword+"@unix(/tmp/mysql.sock)/")
if err != nil {
facades.Log().Info("[MYSQL57] 连接数据库失败:" + err.Error())
return controllers.Error(ctx, http.StatusInternalServerError, "连接数据库失败")
return controllers.Error(ctx, http.StatusInternalServerError, err.Error())
}
defer db.Close()
rows, err := db.Query("SELECT user, host FROM mysql.user")
if err != nil {
facades.Log().Info("[MYSQL57] 查询数据库失败:" + err.Error())
return controllers.Error(ctx, http.StatusInternalServerError, "查询数据库失败")
return controllers.Error(ctx, http.StatusInternalServerError, err.Error())
}
defer rows.Close()
@@ -702,11 +695,17 @@ func (r *Mysql57Controller) AddUser(ctx http.Context) http.Response {
user := ctx.Request().Input("user")
password := ctx.Request().Input("password")
database := ctx.Request().Input("database")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"CREATE USER '" + user + "'@'localhost' IDENTIFIED BY '" + password + ";'\"")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"GRANT ALL PRIVILEGES ON " + database + ".* TO '" + user + "'@'localhost';\"")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"FLUSH PRIVILEGES;\"")
if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"CREATE USER '" + user + "'@'localhost' IDENTIFIED BY '" + password + ";'\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"GRANT ALL PRIVILEGES ON " + database + ".* TO '" + user + "'@'localhost';\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"FLUSH PRIVILEGES;\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, "添加成功")
return controllers.Success(ctx, nil)
}
// DeleteUser 删除用户
@@ -728,9 +727,11 @@ func (r *Mysql57Controller) DeleteUser(ctx http.Context) http.Response {
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
user := ctx.Request().Input("user")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"DROP USER '" + user + "'@'localhost';\"")
if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"DROP USER '" + user + "'@'localhost';\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, "删除成功")
return controllers.Success(ctx, nil)
}
// SetUserPassword 设置用户密码
@@ -754,10 +755,14 @@ func (r *Mysql57Controller) SetUserPassword(ctx http.Context) http.Response {
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
user := ctx.Request().Input("user")
password := ctx.Request().Input("password")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"ALTER USER '" + user + "'@'localhost' IDENTIFIED BY '" + password + "';\"")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"FLUSH PRIVILEGES;\"")
if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"ALTER USER '" + user + "'@'localhost' IDENTIFIED BY '" + password + "';\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"FLUSH PRIVILEGES;\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, "修改成功")
return controllers.Success(ctx, nil)
}
// SetUserPrivileges 设置用户权限
@@ -781,9 +786,15 @@ func (r *Mysql57Controller) SetUserPrivileges(ctx http.Context) http.Response {
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
user := ctx.Request().Input("user")
database := ctx.Request().Input("database")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"REVOKE ALL PRIVILEGES ON *.* FROM '" + user + "'@'localhost';\"")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"GRANT ALL PRIVILEGES ON " + database + ".* TO '" + user + "'@'localhost';\"")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"FLUSH PRIVILEGES;\"")
if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"REVOKE ALL PRIVILEGES ON *.* FROM '" + user + "'@'localhost';\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"GRANT ALL PRIVILEGES ON " + database + ".* TO '" + user + "'@'localhost';\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"FLUSH PRIVILEGES;\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, "修改成功")
return controllers.Success(ctx, nil)
}

View File

@@ -4,10 +4,8 @@ import (
"database/sql"
"fmt"
"regexp"
"strings"
"github.com/goravel/framework/contracts/http"
"github.com/goravel/framework/facades"
"github.com/spf13/cast"
"panel/app/http/controllers"
@@ -35,16 +33,12 @@ func (r *Mysql80Controller) Status(ctx http.Context) http.Response {
return check
}
status := tools.Exec("systemctl status mysqld | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
status, err := tools.ServiceStatus("mysqld")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取MySQL状态失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, status)
}
// Reload 重载配置
@@ -54,17 +48,11 @@ func (r *Mysql80Controller) Reload(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl reload mysqld")
status := tools.Exec("systemctl status mysqld | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取MySQL状态失败")
if err := tools.ServiceReload("mysqld"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重载MySQL配置失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
// Restart 重启服务
@@ -74,17 +62,11 @@ func (r *Mysql80Controller) Restart(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl restart mysqld")
status := tools.Exec("systemctl status mysqld | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取MySQL状态失败")
if err := tools.ServiceRestart("mysqld"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重启MySQL服务失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
// Start 启动服务
@@ -94,17 +76,11 @@ func (r *Mysql80Controller) Start(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl start mysqld")
status := tools.Exec("systemctl status mysqld | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取MySQL状态失败")
if err := tools.ServiceStart("mysqld"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "启动MySQL服务失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
// Stop 停止服务
@@ -114,17 +90,11 @@ func (r *Mysql80Controller) Stop(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl stop mysqld")
status := tools.Exec("systemctl status mysqld | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取MySQL状态失败")
if err := tools.ServiceStop("mysqld"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "停止MySQL服务失败")
}
if status != "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
// GetConfig 获取配置
@@ -174,16 +144,16 @@ func (r *Mysql80Controller) Load(ctx http.Context) http.Response {
return controllers.Error(ctx, http.StatusUnprocessableEntity, "MySQL root密码为空")
}
status := tools.Exec("systemctl status mysqld | grep Active | grep -v grep | awk '{print $2}'")
if status != "active" {
return controllers.Error(ctx, http.StatusInternalServerError, "MySQL 已停止运行")
status, err := tools.ServiceStatus("mysqld")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取MySQL状态失败")
}
if !status {
return controllers.Error(ctx, http.StatusInternalServerError, "MySQL 未运行")
}
raw := tools.Exec("/www/server/mysql/bin/mysqladmin -uroot -p" + rootPassword + " extended-status 2>&1")
if strings.Contains(raw, "Access denied for user") {
return controllers.Error(ctx, http.StatusUnprocessableEntity, "MySQL root密码错误")
}
if !strings.Contains(raw, "Uptime") {
raw, err := tools.Exec("/www/server/mysql/bin/mysqladmin -uroot -p" + rootPassword + " extended-status 2>&1")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取MySQL负载失败")
}
@@ -244,7 +214,11 @@ func (r *Mysql80Controller) ErrorLog(ctx http.Context) http.Response {
return check
}
log := tools.Escape(tools.Exec("tail -n 100 /www/server/mysql/mysql-error.log"))
log, err := tools.Exec("tail -n 100 /www/server/mysql/mysql-error.log")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, log)
}
return controllers.Success(ctx, log)
}
@@ -255,8 +229,11 @@ func (r *Mysql80Controller) ClearErrorLog(ctx http.Context) http.Response {
return check
}
tools.Exec("echo '' > /www/server/mysql/mysql-error.log")
return controllers.Success(ctx, "清空错误日志成功")
if out, err := tools.Exec("echo '' > /www/server/mysql/mysql-error.log"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}
// SlowLog 获取慢查询日志
@@ -266,7 +243,11 @@ func (r *Mysql80Controller) SlowLog(ctx http.Context) http.Response {
return check
}
log := tools.Escape(tools.Exec("tail -n 100 /www/server/mysql/mysql-slow.log"))
log, err := tools.Exec("tail -n 100 /www/server/mysql/mysql-slow.log")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, log)
}
return controllers.Success(ctx, log)
}
@@ -277,8 +258,10 @@ func (r *Mysql80Controller) ClearSlowLog(ctx http.Context) http.Response {
return check
}
tools.Exec("echo '' > /www/server/mysql/mysql-slow.log")
return controllers.Success(ctx, "清空慢查询日志成功")
if out, err := tools.Exec("echo '' > /www/server/mysql/mysql-slow.log"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}
// GetRootPassword 获取root密码
@@ -303,11 +286,11 @@ func (r *Mysql80Controller) SetRootPassword(ctx http.Context) http.Response {
return check
}
status := tools.Exec("systemctl status mysqld | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
status, err := tools.ServiceStatus("mysqld")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取MySQL状态失败")
}
if status != "active" {
if !status {
return controllers.Error(ctx, http.StatusInternalServerError, "MySQL 未运行")
}
@@ -318,17 +301,25 @@ func (r *Mysql80Controller) SetRootPassword(ctx http.Context) http.Response {
oldRootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
if oldRootPassword != rootPassword {
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + oldRootPassword + " -e \"ALTER USER 'root'@'localhost' IDENTIFIED BY '" + rootPassword + "';\"")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + oldRootPassword + " -e \"FLUSH PRIVILEGES;\"")
if _, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + oldRootPassword + " -e \"ALTER USER 'root'@'localhost' IDENTIFIED BY '" + rootPassword + "';\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "设置root密码失败")
}
if _, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + oldRootPassword + " -e \"FLUSH PRIVILEGES;\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "设置root密码失败")
}
err := r.setting.Set(models.SettingKeyMysqlRootPassword, rootPassword)
if err != nil {
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"ALTER USER 'root'@'localhost' IDENTIFIED BY '" + oldRootPassword + "';\"")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"FLUSH PRIVILEGES;\"")
if _, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"ALTER USER 'root'@'localhost' IDENTIFIED BY '" + oldRootPassword + "';\""); err != nil {
return nil
}
if _, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"FLUSH PRIVILEGES;\""); err != nil {
return nil
}
return controllers.Error(ctx, http.StatusInternalServerError, "设置root密码失败")
}
}
return controllers.Success(ctx, "设置root密码成功")
return controllers.Success(ctx, nil)
}
// DatabaseList 获取数据库列表
@@ -345,15 +336,13 @@ func (r *Mysql80Controller) DatabaseList(ctx http.Context) http.Response {
db, err := sql.Open("mysql", "root:"+rootPassword+"@unix(/tmp/mysql.sock)/")
if err != nil {
facades.Log().Info("[MySQL80] 连接数据库失败" + err.Error())
return controllers.Error(ctx, http.StatusInternalServerError, "连接数据库失败")
return controllers.Error(ctx, http.StatusInternalServerError, err.Error())
}
defer db.Close()
rows, err := db.Query("SHOW DATABASES")
if err != nil {
facades.Log().Info("[MySQL80] 获取数据库列表失败" + err.Error())
return controllers.Error(ctx, http.StatusInternalServerError, "获取数据库列表失败")
return controllers.Error(ctx, http.StatusInternalServerError, err.Error())
}
defer rows.Close()
@@ -369,7 +358,6 @@ func (r *Mysql80Controller) DatabaseList(ctx http.Context) http.Response {
}
if err := rows.Err(); err != nil {
facades.Log().Info("[MySQL80] 获取数据库列表失败" + err.Error())
return controllers.Error(ctx, http.StatusInternalServerError, "获取数据库列表失败")
}
@@ -418,12 +406,20 @@ func (r *Mysql80Controller) AddDatabase(ctx http.Context) http.Response {
user := ctx.Request().Input("user")
password := ctx.Request().Input("password")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"CREATE DATABASE IF NOT EXISTS " + database + " DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci;\"")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"CREATE USER '" + user + "'@'localhost' IDENTIFIED BY '" + password + "';\"")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"GRANT ALL PRIVILEGES ON " + database + ".* TO '" + user + "'@'localhost';\"")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"FLUSH PRIVILEGES;\"")
if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"CREATE DATABASE IF NOT EXISTS " + database + " DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci;\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"CREATE USER '" + user + "'@'localhost' IDENTIFIED BY '" + password + "';\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"GRANT ALL PRIVILEGES ON " + database + ".* TO '" + user + "'@'localhost';\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"FLUSH PRIVILEGES;\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, "添加数据库成功")
return controllers.Success(ctx, nil)
}
// DeleteDatabase 删除数据库
@@ -445,9 +441,11 @@ func (r *Mysql80Controller) DeleteDatabase(ctx http.Context) http.Response {
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
database := ctx.Request().Input("database")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"DROP DATABASE IF EXISTS " + database + ";\"")
if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"DROP DATABASE IF EXISTS " + database + ";\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, "删除数据库成功")
return controllers.Success(ctx, nil)
}
// BackupList 获取备份列表
@@ -459,8 +457,7 @@ func (r *Mysql80Controller) BackupList(ctx http.Context) http.Response {
backupList, err := r.backup.MysqlList()
if err != nil {
facades.Log().Info("[MySQL80] 获取备份列表失败:" + err.Error())
return controllers.Error(ctx, http.StatusInternalServerError, "获取备份列表失败")
return controllers.Error(ctx, http.StatusInternalServerError, err.Error())
}
page := ctx.Request().QueryInt("page", 1)
@@ -512,7 +509,7 @@ func (r *Mysql80Controller) UploadBackup(ctx http.Context) http.Response {
return controllers.Error(ctx, http.StatusUnprocessableEntity, "上传文件失败")
}
return controllers.Success(ctx, "上传文件成功")
return controllers.Success(ctx, nil)
}
// CreateBackup 创建备份
@@ -535,11 +532,10 @@ func (r *Mysql80Controller) CreateBackup(ctx http.Context) http.Response {
database := ctx.Request().Input("database")
err = r.backup.MysqlBackup(database)
if err != nil {
facades.Log().Info("[MYSQL80] 创建备份失败:" + err.Error())
return controllers.Error(ctx, http.StatusInternalServerError, "创建备份失败")
return controllers.Error(ctx, http.StatusInternalServerError, err.Error())
}
return controllers.Success(ctx, "备份成功")
return controllers.Success(ctx, nil)
}
// DeleteBackup 删除备份
@@ -563,7 +559,7 @@ func (r *Mysql80Controller) DeleteBackup(ctx http.Context) http.Response {
fileName := ctx.Request().Input("name")
tools.Remove(backupPath + "/" + fileName)
return controllers.Success(ctx, "删除备份成功")
return controllers.Success(ctx, nil)
}
// RestoreBackup 还原备份
@@ -586,11 +582,10 @@ func (r *Mysql80Controller) RestoreBackup(ctx http.Context) http.Response {
err = r.backup.MysqlRestore(ctx.Request().Input("database"), ctx.Request().Input("backup"))
if err != nil {
facades.Log().Info("[MYSQL80] 还原失败:" + err.Error())
return controllers.Error(ctx, http.StatusInternalServerError, "还原失败: "+err.Error())
return controllers.Error(ctx, http.StatusInternalServerError, err.Error())
}
return controllers.Success(ctx, "还原成功")
return controllers.Success(ctx, nil)
}
// UserList 用户列表
@@ -609,15 +604,13 @@ func (r *Mysql80Controller) UserList(ctx http.Context) http.Response {
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
db, err := sql.Open("mysql", "root:"+rootPassword+"@unix(/tmp/mysql.sock)/")
if err != nil {
facades.Log().Info("[MYSQL80] 连接数据库失败:" + err.Error())
return controllers.Error(ctx, http.StatusInternalServerError, "连接数据库失败")
return controllers.Error(ctx, http.StatusInternalServerError, err.Error())
}
defer db.Close()
rows, err := db.Query("SELECT user, host FROM mysql.user")
if err != nil {
facades.Log().Info("[MYSQL80] 查询数据库失败:" + err.Error())
return controllers.Error(ctx, http.StatusInternalServerError, "查询数据库失败")
return controllers.Error(ctx, http.StatusInternalServerError, err.Error())
}
defer rows.Close()
@@ -702,11 +695,17 @@ func (r *Mysql80Controller) AddUser(ctx http.Context) http.Response {
user := ctx.Request().Input("user")
password := ctx.Request().Input("password")
database := ctx.Request().Input("database")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"CREATE USER '" + user + "'@'localhost' IDENTIFIED BY '" + password + ";'\"")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"GRANT ALL PRIVILEGES ON " + database + ".* TO '" + user + "'@'localhost';\"")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"FLUSH PRIVILEGES;\"")
if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"CREATE USER '" + user + "'@'localhost' IDENTIFIED BY '" + password + ";'\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"GRANT ALL PRIVILEGES ON " + database + ".* TO '" + user + "'@'localhost';\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"FLUSH PRIVILEGES;\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, "添加成功")
return controllers.Success(ctx, nil)
}
// DeleteUser 删除用户
@@ -728,9 +727,11 @@ func (r *Mysql80Controller) DeleteUser(ctx http.Context) http.Response {
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
user := ctx.Request().Input("user")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"DROP USER '" + user + "'@'localhost';\"")
if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"DROP USER '" + user + "'@'localhost';\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, "删除成功")
return controllers.Success(ctx, nil)
}
// SetUserPassword 设置用户密码
@@ -754,10 +755,14 @@ func (r *Mysql80Controller) SetUserPassword(ctx http.Context) http.Response {
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
user := ctx.Request().Input("user")
password := ctx.Request().Input("password")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"ALTER USER '" + user + "'@'localhost' IDENTIFIED BY '" + password + "';\"")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"FLUSH PRIVILEGES;\"")
if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"ALTER USER '" + user + "'@'localhost' IDENTIFIED BY '" + password + "';\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"FLUSH PRIVILEGES;\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, "修改成功")
return controllers.Success(ctx, nil)
}
// SetUserPrivileges 设置用户权限
@@ -781,9 +786,15 @@ func (r *Mysql80Controller) SetUserPrivileges(ctx http.Context) http.Response {
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
user := ctx.Request().Input("user")
database := ctx.Request().Input("database")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"REVOKE ALL PRIVILEGES ON *.* FROM '" + user + "'@'localhost';\"")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"GRANT ALL PRIVILEGES ON " + database + ".* TO '" + user + "'@'localhost';\"")
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"FLUSH PRIVILEGES;\"")
if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"REVOKE ALL PRIVILEGES ON *.* FROM '" + user + "'@'localhost';\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"GRANT ALL PRIVILEGES ON " + database + ".* TO '" + user + "'@'localhost';\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"FLUSH PRIVILEGES;\""); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, "修改成功")
return controllers.Success(ctx, nil)
}

View File

@@ -5,7 +5,6 @@ import (
"time"
"github.com/goravel/framework/contracts/http"
"github.com/goravel/framework/facades"
"github.com/imroc/req/v3"
"github.com/spf13/cast"
@@ -30,16 +29,12 @@ func (r *OpenRestyController) Status(ctx http.Context) http.Response {
return check
}
status := tools.Exec("systemctl status openresty | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
status, err := tools.ServiceStatus("openresty")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取OpenResty状态失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, status)
}
// Reload 重载配置
@@ -49,17 +44,11 @@ func (r *OpenRestyController) Reload(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl reload openresty")
status := tools.Exec("systemctl status openresty | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取OpenResty状态失败")
if err := tools.ServiceReload("openresty"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重载OpenResty失败")
}
if status == "active" {
return controllers.Success(ctx, "重载OpenResty成功")
} else {
return controllers.Error(ctx, 1, "重载OpenResty失败: "+status)
}
return controllers.Success(ctx, nil)
}
// Start 启动OpenResty
@@ -69,17 +58,11 @@ func (r *OpenRestyController) Start(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl start openresty")
status := tools.Exec("systemctl status openresty | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取OpenResty状态失败")
if err := tools.ServiceStart("openresty"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "启动OpenResty失败")
}
if status == "active" {
return controllers.Success(ctx, "启动OpenResty成功")
} else {
return controllers.Error(ctx, 1, "启动OpenResty失败: "+status)
}
return controllers.Success(ctx, nil)
}
// Stop 停止OpenResty
@@ -89,17 +72,11 @@ func (r *OpenRestyController) Stop(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl stop openresty")
status := tools.Exec("systemctl status openresty | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取OpenResty状态失败")
if err := tools.ServiceStop("openresty"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "停止OpenResty失败")
}
if status != "active" {
return controllers.Success(ctx, "停止OpenResty成功")
} else {
return controllers.Error(ctx, 1, "停止OpenResty失败: "+status)
}
return controllers.Success(ctx, nil)
}
// Restart 重启OpenResty
@@ -109,17 +86,11 @@ func (r *OpenRestyController) Restart(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl restart openresty")
status := tools.Exec("systemctl status openresty | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取OpenResty状态失败")
if err := tools.ServiceRestart("openresty"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重启OpenResty失败")
}
if status == "active" {
return controllers.Success(ctx, "重启OpenResty成功")
} else {
return controllers.Error(ctx, 1, "重启OpenResty失败: "+status)
}
return controllers.Success(ctx, nil)
}
// GetConfig 获取配置
@@ -167,7 +138,11 @@ func (r *OpenRestyController) ErrorLog(ctx http.Context) http.Response {
return controllers.Success(ctx, "")
}
out := tools.Exec("tail -n 100 /www/wwwlogs/nginx_error.log")
out, err := tools.Exec("tail -n 100 /www/wwwlogs/nginx_error.log")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, out)
}
@@ -178,8 +153,11 @@ func (r *OpenRestyController) ClearErrorLog(ctx http.Context) http.Response {
return check
}
tools.Exec("echo '' > /www/wwwlogs/nginx_error.log")
return controllers.Success(ctx, "清空OpenResty错误日志成功")
if out, err := tools.Exec("echo '' > /www/wwwlogs/nginx_error.log"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}
// Load 获取负载
@@ -192,7 +170,6 @@ func (r *OpenRestyController) Load(ctx http.Context) http.Response {
client := req.C().SetTimeout(10 * time.Second)
resp, err := client.R().Get("http://127.0.0.1/nginx_status")
if err != nil || !resp.IsSuccessState() {
facades.Log().Info("[OpenResty] 获取OpenResty负载失败: " + err.Error())
return controllers.Error(ctx, http.StatusInternalServerError, "获取OpenResty负载失败")
}
@@ -203,13 +180,19 @@ func (r *OpenRestyController) Load(ctx http.Context) http.Response {
}
var data []nginxStatus
workers := tools.Exec("ps aux | grep nginx | grep 'worker process' | wc -l")
workers, err := tools.Exec("ps aux | grep nginx | grep 'worker process' | wc -l")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取OpenResty负载失败")
}
data = append(data, nginxStatus{
Name: "工作进程",
Value: workers,
})
out := tools.Exec("ps aux | grep nginx | grep 'worker process' | awk '{memsum+=$6};END {print memsum}'")
out, err := tools.Exec("ps aux | grep nginx | grep 'worker process' | awk '{memsum+=$6};END {print memsum}'")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取OpenResty负载失败")
}
mem := tools.FormatBytes(cast.ToFloat64(out))
data = append(data, nginxStatus{
Name: "内存占用",

View File

@@ -36,16 +36,12 @@ func (r *Php74Controller) Status(ctx http.Context) http.Response {
return check
}
status := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
status, err := tools.ServiceStatus("php-fpm-" + r.version)
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, status)
}
func (r *Php74Controller) Reload(ctx http.Context) http.Response {
@@ -54,18 +50,11 @@ func (r *Php74Controller) Reload(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl reload php-fpm-" + r.version)
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
status := strings.TrimSpace(out)
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
if err := tools.ServiceReload("php-fpm-" + r.version); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重载PHP-"+r.version+"失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
func (r *Php74Controller) Start(ctx http.Context) http.Response {
@@ -74,18 +63,11 @@ func (r *Php74Controller) Start(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl start php-fpm-" + r.version)
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
status := strings.TrimSpace(out)
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
if err := tools.ServiceStart("php-fpm-" + r.version); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "启动PHP-"+r.version+"失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
func (r *Php74Controller) Stop(ctx http.Context) http.Response {
@@ -94,18 +76,11 @@ func (r *Php74Controller) Stop(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl stop php-fpm-" + r.version)
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
status := strings.TrimSpace(out)
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
if err := tools.ServiceStop("php-fpm-" + r.version); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "停止PHP-"+r.version+"失败")
}
if status != "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
func (r *Php74Controller) Restart(ctx http.Context) http.Response {
@@ -114,18 +89,11 @@ func (r *Php74Controller) Restart(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl restart php-fpm-" + r.version)
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
status := strings.TrimSpace(out)
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
if err := tools.ServiceRestart("php-fpm-" + r.version); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重启PHP-"+r.version+"失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
func (r *Php74Controller) GetConfig(ctx http.Context) http.Response {
@@ -193,7 +161,11 @@ func (r *Php74Controller) ErrorLog(ctx http.Context) http.Response {
return check
}
log := tools.Escape(tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/php-fpm.log"))
log, err := tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/php-fpm.log")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, log)
}
return controllers.Success(ctx, log)
}
@@ -203,7 +175,11 @@ func (r *Php74Controller) SlowLog(ctx http.Context) http.Response {
return check
}
log := tools.Escape(tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/slow.log"))
log, err := tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/slow.log")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, log)
}
return controllers.Success(ctx, log)
}
@@ -213,8 +189,11 @@ func (r *Php74Controller) ClearErrorLog(ctx http.Context) http.Response {
return check
}
tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/php-fpm.log")
return controllers.Success(ctx, true)
if out, err := tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/php-fpm.log"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}
func (r *Php74Controller) ClearSlowLog(ctx http.Context) http.Response {
@@ -223,8 +202,10 @@ func (r *Php74Controller) ClearSlowLog(ctx http.Context) http.Response {
return check
}
tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/slow.log")
return controllers.Success(ctx, true)
if out, err := tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/slow.log"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}
func (r *Php74Controller) GetExtensionList(ctx http.Context) http.Response {
@@ -350,9 +331,12 @@ func (r *Php74Controller) GetExtensions() []PHPExtension {
Installed: false,
})
raw := tools.Exec("/www/server/php/" + r.version + "/bin/php -m")
rawExtensionList := strings.Split(raw, "\n")
raw, err := tools.Exec("/www/server/php/" + r.version + "/bin/php -m")
if err != nil {
return extensions
}
rawExtensionList := strings.Split(raw, "\n")
for _, item := range rawExtensionList {
if !strings.Contains(item, "[") && item != "" {
for i := range extensions {

View File

@@ -36,16 +36,12 @@ func (r *Php80Controller) Status(ctx http.Context) http.Response {
return check
}
status := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
status, err := tools.ServiceStatus("php-fpm-" + r.version)
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, status)
}
func (r *Php80Controller) Reload(ctx http.Context) http.Response {
@@ -54,18 +50,11 @@ func (r *Php80Controller) Reload(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl reload php-fpm-" + r.version)
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
status := strings.TrimSpace(out)
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
if err := tools.ServiceReload("php-fpm-" + r.version); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重载PHP-"+r.version+"失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
func (r *Php80Controller) Start(ctx http.Context) http.Response {
@@ -74,18 +63,11 @@ func (r *Php80Controller) Start(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl start php-fpm-" + r.version)
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
status := strings.TrimSpace(out)
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
if err := tools.ServiceStart("php-fpm-" + r.version); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "启动PHP-"+r.version+"失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
func (r *Php80Controller) Stop(ctx http.Context) http.Response {
@@ -94,18 +76,11 @@ func (r *Php80Controller) Stop(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl stop php-fpm-" + r.version)
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
status := strings.TrimSpace(out)
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
if err := tools.ServiceStop("php-fpm-" + r.version); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "停止PHP-"+r.version+"失败")
}
if status != "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
func (r *Php80Controller) Restart(ctx http.Context) http.Response {
@@ -114,18 +89,11 @@ func (r *Php80Controller) Restart(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl restart php-fpm-" + r.version)
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
status := strings.TrimSpace(out)
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
if err := tools.ServiceRestart("php-fpm-" + r.version); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重启PHP-"+r.version+"失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
func (r *Php80Controller) GetConfig(ctx http.Context) http.Response {
@@ -193,7 +161,11 @@ func (r *Php80Controller) ErrorLog(ctx http.Context) http.Response {
return check
}
log := tools.Escape(tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/php-fpm.log"))
log, err := tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/php-fpm.log")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, log)
}
return controllers.Success(ctx, log)
}
@@ -203,7 +175,11 @@ func (r *Php80Controller) SlowLog(ctx http.Context) http.Response {
return check
}
log := tools.Escape(tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/slow.log"))
log, err := tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/slow.log")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, log)
}
return controllers.Success(ctx, log)
}
@@ -213,8 +189,11 @@ func (r *Php80Controller) ClearErrorLog(ctx http.Context) http.Response {
return check
}
tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/php-fpm.log")
return controllers.Success(ctx, true)
if out, err := tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/php-fpm.log"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}
func (r *Php80Controller) ClearSlowLog(ctx http.Context) http.Response {
@@ -223,8 +202,10 @@ func (r *Php80Controller) ClearSlowLog(ctx http.Context) http.Response {
return check
}
tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/slow.log")
return controllers.Success(ctx, true)
if out, err := tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/slow.log"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}
func (r *Php80Controller) GetExtensionList(ctx http.Context) http.Response {
@@ -350,9 +331,12 @@ func (r *Php80Controller) GetExtensions() []PHPExtension {
Installed: false,
})
raw := tools.Exec("/www/server/php/" + r.version + "/bin/php -m")
rawExtensionList := strings.Split(raw, "\n")
raw, err := tools.Exec("/www/server/php/" + r.version + "/bin/php -m")
if err != nil {
return extensions
}
rawExtensionList := strings.Split(raw, "\n")
for _, item := range rawExtensionList {
if !strings.Contains(item, "[") && item != "" {
for i := range extensions {

View File

@@ -36,16 +36,12 @@ func (r *Php81Controller) Status(ctx http.Context) http.Response {
return check
}
status := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
status, err := tools.ServiceStatus("php-fpm-" + r.version)
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, status)
}
func (r *Php81Controller) Reload(ctx http.Context) http.Response {
@@ -54,18 +50,11 @@ func (r *Php81Controller) Reload(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl reload php-fpm-" + r.version)
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
status := strings.TrimSpace(out)
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
if err := tools.ServiceReload("php-fpm-" + r.version); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重载PHP-"+r.version+"失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
func (r *Php81Controller) Start(ctx http.Context) http.Response {
@@ -74,18 +63,11 @@ func (r *Php81Controller) Start(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl start php-fpm-" + r.version)
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
status := strings.TrimSpace(out)
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
if err := tools.ServiceStart("php-fpm-" + r.version); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "启动PHP-"+r.version+"失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
func (r *Php81Controller) Stop(ctx http.Context) http.Response {
@@ -94,18 +76,11 @@ func (r *Php81Controller) Stop(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl stop php-fpm-" + r.version)
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
status := strings.TrimSpace(out)
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
if err := tools.ServiceStop("php-fpm-" + r.version); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "停止PHP-"+r.version+"失败")
}
if status != "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
func (r *Php81Controller) Restart(ctx http.Context) http.Response {
@@ -114,18 +89,11 @@ func (r *Php81Controller) Restart(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl restart php-fpm-" + r.version)
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
status := strings.TrimSpace(out)
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
if err := tools.ServiceRestart("php-fpm-" + r.version); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重启PHP-"+r.version+"失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
func (r *Php81Controller) GetConfig(ctx http.Context) http.Response {
@@ -193,7 +161,11 @@ func (r *Php81Controller) ErrorLog(ctx http.Context) http.Response {
return check
}
log := tools.Escape(tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/php-fpm.log"))
log, err := tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/php-fpm.log")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, log)
}
return controllers.Success(ctx, log)
}
@@ -203,7 +175,11 @@ func (r *Php81Controller) SlowLog(ctx http.Context) http.Response {
return check
}
log := tools.Escape(tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/slow.log"))
log, err := tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/slow.log")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, log)
}
return controllers.Success(ctx, log)
}
@@ -213,8 +189,11 @@ func (r *Php81Controller) ClearErrorLog(ctx http.Context) http.Response {
return check
}
tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/php-fpm.log")
return controllers.Success(ctx, true)
if out, err := tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/php-fpm.log"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}
func (r *Php81Controller) ClearSlowLog(ctx http.Context) http.Response {
@@ -223,8 +202,10 @@ func (r *Php81Controller) ClearSlowLog(ctx http.Context) http.Response {
return check
}
tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/slow.log")
return controllers.Success(ctx, true)
if out, err := tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/slow.log"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}
func (r *Php81Controller) GetExtensionList(ctx http.Context) http.Response {
@@ -350,9 +331,12 @@ func (r *Php81Controller) GetExtensions() []PHPExtension {
Installed: false,
})
raw := tools.Exec("/www/server/php/" + r.version + "/bin/php -m")
rawExtensionList := strings.Split(raw, "\n")
raw, err := tools.Exec("/www/server/php/" + r.version + "/bin/php -m")
if err != nil {
return extensions
}
rawExtensionList := strings.Split(raw, "\n")
for _, item := range rawExtensionList {
if !strings.Contains(item, "[") && item != "" {
for i := range extensions {

View File

@@ -36,16 +36,12 @@ func (r *Php82Controller) Status(ctx http.Context) http.Response {
return check
}
status := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
status, err := tools.ServiceStatus("php-fpm-" + r.version)
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, status)
}
func (r *Php82Controller) Reload(ctx http.Context) http.Response {
@@ -54,18 +50,11 @@ func (r *Php82Controller) Reload(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl reload php-fpm-" + r.version)
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
status := strings.TrimSpace(out)
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
if err := tools.ServiceReload("php-fpm-" + r.version); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重载PHP-"+r.version+"失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
func (r *Php82Controller) Start(ctx http.Context) http.Response {
@@ -74,18 +63,11 @@ func (r *Php82Controller) Start(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl start php-fpm-" + r.version)
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
status := strings.TrimSpace(out)
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
if err := tools.ServiceStart("php-fpm-" + r.version); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "启动PHP-"+r.version+"失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
func (r *Php82Controller) Stop(ctx http.Context) http.Response {
@@ -94,18 +76,11 @@ func (r *Php82Controller) Stop(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl stop php-fpm-" + r.version)
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
status := strings.TrimSpace(out)
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
if err := tools.ServiceStop("php-fpm-" + r.version); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "停止PHP-"+r.version+"失败")
}
if status != "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
func (r *Php82Controller) Restart(ctx http.Context) http.Response {
@@ -114,18 +89,11 @@ func (r *Php82Controller) Restart(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl restart php-fpm-" + r.version)
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
status := strings.TrimSpace(out)
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
if err := tools.ServiceRestart("php-fpm-" + r.version); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重启PHP-"+r.version+"失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
func (r *Php82Controller) GetConfig(ctx http.Context) http.Response {
@@ -193,7 +161,11 @@ func (r *Php82Controller) ErrorLog(ctx http.Context) http.Response {
return check
}
log := tools.Escape(tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/php-fpm.log"))
log, err := tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/php-fpm.log")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, log)
}
return controllers.Success(ctx, log)
}
@@ -203,7 +175,11 @@ func (r *Php82Controller) SlowLog(ctx http.Context) http.Response {
return check
}
log := tools.Escape(tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/slow.log"))
log, err := tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/slow.log")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, log)
}
return controllers.Success(ctx, log)
}
@@ -213,8 +189,11 @@ func (r *Php82Controller) ClearErrorLog(ctx http.Context) http.Response {
return check
}
tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/php-fpm.log")
return controllers.Success(ctx, true)
if out, err := tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/php-fpm.log"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}
func (r *Php82Controller) ClearSlowLog(ctx http.Context) http.Response {
@@ -223,8 +202,10 @@ func (r *Php82Controller) ClearSlowLog(ctx http.Context) http.Response {
return check
}
tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/slow.log")
return controllers.Success(ctx, true)
if out, err := tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/slow.log"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}
func (r *Php82Controller) GetExtensionList(ctx http.Context) http.Response {
@@ -344,9 +325,12 @@ func (r *Php82Controller) GetExtensions() []PHPExtension {
Installed: false,
})
raw := tools.Exec("/www/server/php/" + r.version + "/bin/php -m")
rawExtensionList := strings.Split(raw, "\n")
raw, err := tools.Exec("/www/server/php/" + r.version + "/bin/php -m")
if err != nil {
return extensions
}
rawExtensionList := strings.Split(raw, "\n")
for _, item := range rawExtensionList {
if !strings.Contains(item, "[") && item != "" {
for i := range extensions {

View File

@@ -28,7 +28,7 @@ func (r *PhpMyAdminController) Info(ctx http.Context) http.Response {
files, err := os.ReadDir("/www/server/phpmyadmin")
if err != nil {
return controllers.Error(ctx, http.StatusUnprocessableEntity, "找不到 phpMyAdmin 目录")
return controllers.Error(ctx, http.StatusInternalServerError, "找不到 phpMyAdmin 目录")
}
var phpmyadmin string
@@ -38,13 +38,13 @@ func (r *PhpMyAdminController) Info(ctx http.Context) http.Response {
}
}
if len(phpmyadmin) == 0 {
return controllers.Error(ctx, http.StatusUnprocessableEntity, "找不到 phpMyAdmin 目录")
return controllers.Error(ctx, http.StatusInternalServerError, "找不到 phpMyAdmin 目录")
}
conf := tools.Read("/www/server/vhost/phpmyadmin.conf")
match := regexp.MustCompile(`listen\s+(\d+);`).FindStringSubmatch(conf)
if len(match) == 0 {
return controllers.Error(ctx, http.StatusUnprocessableEntity, "找不到 phpMyAdmin 端口")
return controllers.Error(ctx, http.StatusInternalServerError, "找不到 phpMyAdmin 端口")
}
return controllers.Success(ctx, http.Json{
@@ -61,7 +61,7 @@ func (r *PhpMyAdminController) SetPort(ctx http.Context) http.Response {
port := ctx.Request().Input("port")
if len(port) == 0 {
return controllers.Error(ctx, http.StatusUnprocessableEntity, "端口不能为空")
return controllers.Error(ctx, http.StatusInternalServerError, "端口不能为空")
}
conf := tools.Read("/www/server/vhost/phpmyadmin.conf")
@@ -74,13 +74,25 @@ func (r *PhpMyAdminController) SetPort(ctx http.Context) http.Response {
}
if tools.IsRHEL() {
tools.Exec("firewall-cmd --zone=public --add-port=" + port + "/tcp --permanent")
tools.Exec("firewall-cmd --reload")
if out, err := tools.Exec("firewall-cmd --zone=public --add-port=" + port + "/tcp --permanent"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("firewall-cmd --reload"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
} else {
tools.Exec("ufw allow " + port + "/tcp")
tools.Exec("ufw reload")
if out, err := tools.Exec("ufw allow " + port + "/tcp"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("ufw reload"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
}
err := tools.ServiceReload("openresty")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重载OpenResty失败")
}
tools.Exec("systemctl reload openresty")
return controllers.Success(ctx, nil)
}

View File

@@ -4,7 +4,6 @@ import (
"strings"
"github.com/goravel/framework/contracts/http"
"github.com/goravel/framework/facades"
"github.com/goravel/framework/support/carbon"
"panel/app/http/controllers"
@@ -32,16 +31,12 @@ func (r *Postgresql15Controller) Status(ctx http.Context) http.Response {
return check
}
status := tools.Exec("systemctl status postgresql | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
status, err := tools.ServiceStatus("postgresql")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PostgreSQL状态失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, status)
}
// Reload 重载配置
@@ -51,17 +46,11 @@ func (r *Postgresql15Controller) Reload(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl reload postgresql")
status := tools.Exec("systemctl status postgresql | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PostgreSQL状态失败")
if err := tools.ServiceReload("postgresql"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重载PostgreSQL失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
// Restart 重启服务
@@ -71,17 +60,11 @@ func (r *Postgresql15Controller) Restart(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl restart postgresql")
status := tools.Exec("systemctl status postgresql | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PostgreSQL状态失败")
if err := tools.ServiceRestart("postgresql"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重启PostgreSQL失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
// Start 启动服务
@@ -91,17 +74,11 @@ func (r *Postgresql15Controller) Start(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl start postgresql")
status := tools.Exec("systemctl status postgresql | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PostgreSQL状态失败")
if err := tools.ServiceStart("postgresql"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "启动PostgreSQL失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
// Stop 停止服务
@@ -111,17 +88,11 @@ func (r *Postgresql15Controller) Stop(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl stop postgresql")
status := tools.Exec("systemctl status postgresql | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PostgreSQL状态失败")
if err := tools.ServiceStop("postgresql"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "停止PostgreSQL失败")
}
if status != "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
// GetConfig 获取配置
@@ -201,17 +172,41 @@ func (r *Postgresql15Controller) Load(ctx http.Context) http.Response {
return check
}
status := tools.Exec("systemctl status postgresql | grep Active | grep -v grep | awk '{print $2}'")
if status != "active" {
return controllers.Error(ctx, http.StatusInternalServerError, "PostgreSQL 已停止运行")
status, err := tools.ServiceStatus("postgresql")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PostgreSQL状态失败")
}
if !status {
return controllers.Error(ctx, http.StatusInternalServerError, "PostgreSQL已停止运行")
}
time, err := tools.Exec(`echo "select pg_postmaster_start_time();" | su - postgres -c "psql" | sed -n 3p | cut -d'.' -f1`)
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PostgreSQL启动时间失败")
}
pid, err := tools.Exec(`echo "select pg_backend_pid();" | su - postgres -c "psql" | sed -n 3p`)
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PostgreSQL进程PID失败")
}
process, err := tools.Exec(`ps aux | grep postgres | grep -v grep | wc -l`)
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PostgreSQL进程数失败")
}
connections, err := tools.Exec(`echo "SELECT count(*) FROM pg_stat_activity WHERE NOT pid=pg_backend_pid();" | su - postgres -c "psql" | sed -n 3p`)
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PostgreSQL连接数失败")
}
storage, err := tools.Exec(`echo "select pg_size_pretty(pg_database_size('postgres'));" | su - postgres -c "psql" | sed -n 3p`)
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PostgreSQL空间占用失败")
}
data := []LoadInfo{
{"启动时间", carbon.Parse(tools.Exec(`echo "select pg_postmaster_start_time();" | su - postgres -c "psql" | sed -n 3p | cut -d'.' -f1`)).ToDateTimeString()},
{"进程 PID", tools.Exec(`echo "select pg_backend_pid();" | su - postgres -c "psql" | sed -n 3p`)},
{"进程数", tools.Exec(`ps aux | grep postgres | grep -v grep | wc -l`)},
{"总连接数", tools.Exec(`echo "SELECT count(*) FROM pg_stat_activity WHERE NOT pid=pg_backend_pid();" | su - postgres -c "psql" | sed -n 3p`)},
{"空间占用", tools.Exec(`echo "select pg_size_pretty(pg_database_size('postgres'));" | su - postgres -c "psql" | sed -n 3p`)},
{"启动时间", carbon.Parse(time).ToDateTimeString()},
{"进程 PID", pid},
{"进程数", process},
{"总连接数", connections},
{"空间占用", storage},
}
return controllers.Success(ctx, data)
@@ -224,7 +219,11 @@ func (r *Postgresql15Controller) Log(ctx http.Context) http.Response {
return check
}
log := tools.Exec("tail -n 100 /www/server/postgresql/logs/postgresql-" + carbon.Now().ToDateString() + ".log")
log, err := tools.Exec("tail -n 100 /www/server/postgresql/logs/postgresql-" + carbon.Now().ToDateString() + ".log")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, log)
}
return controllers.Success(ctx, log)
}
@@ -235,7 +234,10 @@ func (r *Postgresql15Controller) ClearLog(ctx http.Context) http.Response {
return check
}
tools.Exec("echo '' > /www/server/postgresql/logs/postgresql-" + carbon.Now().ToDateString() + ".log")
if out, err := tools.Exec("echo '' > /www/server/postgresql/logs/postgresql-" + carbon.Now().ToDateString() + ".log"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}
@@ -246,9 +248,12 @@ func (r *Postgresql15Controller) DatabaseList(ctx http.Context) http.Response {
return check
}
status := tools.Exec("systemctl status postgresql | grep Active | grep -v grep | awk '{print $2}'")
if status != "active" {
return controllers.Error(ctx, http.StatusInternalServerError, "PostgreSQL 已停止运行")
status, err := tools.ServiceStatus("postgresql")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PostgreSQL状态失败")
}
if !status {
return controllers.Error(ctx, http.StatusInternalServerError, "PostgreSQL已停止运行")
}
type database struct {
@@ -257,7 +262,10 @@ func (r *Postgresql15Controller) DatabaseList(ctx http.Context) http.Response {
Encoding string `json:"encoding"`
}
raw := tools.Exec(`echo "\l" | su - postgres -c "psql"`)
raw, err := tools.Exec(`echo "\l" | su - postgres -c "psql"`)
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, raw)
}
databases := strings.Split(raw, "\n")
if len(databases) >= 4 {
databases = databases[3 : len(databases)-1]
@@ -326,13 +334,23 @@ func (r *Postgresql15Controller) AddDatabase(ctx http.Context) http.Response {
user := ctx.Request().Input("user")
password := ctx.Request().Input("password")
tools.Exec(`echo "CREATE DATABASE ` + database + `;" | su - postgres -c "psql"`)
tools.Exec(`echo "CREATE USER ` + user + ` WITH PASSWORD '` + password + `';" | su - postgres -c "psql"`)
tools.Exec(`echo "ALTER DATABASE ` + database + ` OWNER TO ` + user + `;" | su - postgres -c "psql"`)
tools.Exec(`echo "GRANT ALL PRIVILEGES ON DATABASE ` + database + ` TO ` + user + `;" | su - postgres -c "psql"`)
if out, err := tools.Exec(`echo "CREATE DATABASE ` + database + `;" | su - postgres -c "psql"`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec(`echo "CREATE USER ` + user + ` WITH PASSWORD '` + password + `';" | su - postgres -c "psql"`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec(`echo "ALTER DATABASE ` + database + ` OWNER TO ` + user + `;" | su - postgres -c "psql"`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec(`echo "GRANT ALL PRIVILEGES ON DATABASE ` + database + ` TO ` + user + `;" | su - postgres -c "psql"`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
userConfig := "host " + database + " " + user + " 127.0.0.1/32 scram-sha-256"
tools.Exec(`echo "` + userConfig + `" >> /www/server/postgresql/data/pg_hba.conf`)
if out, err := tools.Exec(`echo "` + userConfig + `" >> /www/server/postgresql/data/pg_hba.conf`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return r.Reload(ctx)
}
@@ -355,7 +373,9 @@ func (r *Postgresql15Controller) DeleteDatabase(ctx http.Context) http.Response
}
database := ctx.Request().Input("database")
tools.Exec(`echo "DROP DATABASE ` + database + `;" | su - postgres -c "psql"`)
if out, err := tools.Exec(`echo "DROP DATABASE ` + database + `;" | su - postgres -c "psql"`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}
@@ -369,7 +389,6 @@ func (r *Postgresql15Controller) BackupList(ctx http.Context) http.Response {
backupList, err := r.backup.PostgresqlList()
if err != nil {
facades.Log().Info("[PostgreSQL] 获取备份列表失败:" + err.Error())
return controllers.Error(ctx, http.StatusInternalServerError, "获取备份列表失败")
}
@@ -445,8 +464,7 @@ func (r *Postgresql15Controller) CreateBackup(ctx http.Context) http.Response {
database := ctx.Request().Input("database")
err = r.backup.PostgresqlBackup(database)
if err != nil {
facades.Log().Info("[PostgreSQL] 创建备份失败:" + err.Error())
return controllers.Error(ctx, http.StatusInternalServerError, "创建备份失败")
return controllers.Error(ctx, http.StatusInternalServerError, err.Error())
}
return controllers.Success(ctx, nil)
@@ -496,7 +514,6 @@ func (r *Postgresql15Controller) RestoreBackup(ctx http.Context) http.Response {
err = r.backup.PostgresqlRestore(ctx.Request().Input("database"), ctx.Request().Input("backup"))
if err != nil {
facades.Log().Info("[PostgreSQL] 还原失败:" + err.Error())
return controllers.Error(ctx, http.StatusInternalServerError, "还原失败: "+err.Error())
}
@@ -515,7 +532,10 @@ func (r *Postgresql15Controller) UserList(ctx http.Context) http.Response {
Role string `json:"role"`
}
raw := tools.Exec(`echo "\du" | su - postgres -c "psql"`)
raw, err := tools.Exec(`echo "\du" | su - postgres -c "psql"`)
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, raw)
}
users := strings.Split(raw, "\n")
if len(users) < 4 {
return controllers.Error(ctx, http.StatusInternalServerError, "用户列表为空")
@@ -578,11 +598,17 @@ func (r *Postgresql15Controller) AddUser(ctx http.Context) http.Response {
user := ctx.Request().Input("user")
password := ctx.Request().Input("password")
database := ctx.Request().Input("database")
tools.Exec(`echo "CREATE USER ` + user + ` WITH PASSWORD '` + password + `';" | su - postgres -c "psql"`)
tools.Exec(`echo "GRANT ALL PRIVILEGES ON DATABASE ` + database + ` TO ` + user + `;" | su - postgres -c "psql"`)
if out, err := tools.Exec(`echo "CREATE USER ` + user + ` WITH PASSWORD '` + password + `';" | su - postgres -c "psql"`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec(`echo "GRANT ALL PRIVILEGES ON DATABASE ` + database + ` TO ` + user + `;" | su - postgres -c "psql"`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
userConfig := "host " + database + " " + user + " 127.0.0.1/32 scram-sha-256"
tools.Exec(`echo "` + userConfig + `" >> /www/server/postgresql/data/pg_hba.conf`)
if out, err := tools.Exec(`echo "` + userConfig + `" >> /www/server/postgresql/data/pg_hba.conf`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return r.Reload(ctx)
}
@@ -605,8 +631,12 @@ func (r *Postgresql15Controller) DeleteUser(ctx http.Context) http.Response {
}
user := ctx.Request().Input("user")
tools.Exec(`echo "DROP USER ` + user + `;" | su - postgres -c "psql"`)
tools.Exec(`sed -i '/` + user + `/d' /www/server/postgresql/data/pg_hba.conf`)
if out, err := tools.Exec(`echo "DROP USER ` + user + `;" | su - postgres -c "psql"`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec(`sed -i '/` + user + `/d' /www/server/postgresql/data/pg_hba.conf`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return r.Reload(ctx)
}
@@ -631,7 +661,9 @@ func (r *Postgresql15Controller) SetUserPassword(ctx http.Context) http.Response
user := ctx.Request().Input("user")
password := ctx.Request().Input("password")
tools.Exec(`echo "ALTER USER ` + user + ` WITH PASSWORD '` + password + `';" | su - postgres -c "psql"`)
if out, err := tools.Exec(`echo "ALTER USER ` + user + ` WITH PASSWORD '` + password + `';" | su - postgres -c "psql"`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}

View File

@@ -4,7 +4,6 @@ import (
"strings"
"github.com/goravel/framework/contracts/http"
"github.com/goravel/framework/facades"
"github.com/goravel/framework/support/carbon"
"panel/app/http/controllers"
@@ -32,16 +31,12 @@ func (r *Postgresql16Controller) Status(ctx http.Context) http.Response {
return check
}
status := tools.Exec("systemctl status postgresql | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
status, err := tools.ServiceStatus("postgresql")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PostgreSQL状态失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, status)
}
// Reload 重载配置
@@ -51,17 +46,11 @@ func (r *Postgresql16Controller) Reload(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl reload postgresql")
status := tools.Exec("systemctl status postgresql | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PostgreSQL状态失败")
if err := tools.ServiceReload("postgresql"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重载PostgreSQL失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
// Restart 重启服务
@@ -71,17 +60,11 @@ func (r *Postgresql16Controller) Restart(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl restart postgresql")
status := tools.Exec("systemctl status postgresql | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PostgreSQL状态失败")
if err := tools.ServiceRestart("postgresql"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重启PostgreSQL失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
// Start 启动服务
@@ -91,17 +74,11 @@ func (r *Postgresql16Controller) Start(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl start postgresql")
status := tools.Exec("systemctl status postgresql | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PostgreSQL状态失败")
if err := tools.ServiceStart("postgresql"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "启动PostgreSQL失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
// Stop 停止服务
@@ -111,17 +88,11 @@ func (r *Postgresql16Controller) Stop(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl stop postgresql")
status := tools.Exec("systemctl status postgresql | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PostgreSQL状态失败")
if err := tools.ServiceStop("postgresql"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "停止PostgreSQL失败")
}
if status != "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
// GetConfig 获取配置
@@ -201,17 +172,41 @@ func (r *Postgresql16Controller) Load(ctx http.Context) http.Response {
return check
}
status := tools.Exec("systemctl status postgresql | grep Active | grep -v grep | awk '{print $2}'")
if status != "active" {
return controllers.Error(ctx, http.StatusInternalServerError, "PostgreSQL 已停止运行")
status, err := tools.ServiceStatus("postgresql")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PostgreSQL状态失败")
}
if !status {
return controllers.Error(ctx, http.StatusInternalServerError, "PostgreSQL已停止运行")
}
time, err := tools.Exec(`echo "select pg_postmaster_start_time();" | su - postgres -c "psql" | sed -n 3p | cut -d'.' -f1`)
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PostgreSQL启动时间失败")
}
pid, err := tools.Exec(`echo "select pg_backend_pid();" | su - postgres -c "psql" | sed -n 3p`)
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PostgreSQL进程PID失败")
}
process, err := tools.Exec(`ps aux | grep postgres | grep -v grep | wc -l`)
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PostgreSQL进程数失败")
}
connections, err := tools.Exec(`echo "SELECT count(*) FROM pg_stat_activity WHERE NOT pid=pg_backend_pid();" | su - postgres -c "psql" | sed -n 3p`)
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PostgreSQL连接数失败")
}
storage, err := tools.Exec(`echo "select pg_size_pretty(pg_database_size('postgres'));" | su - postgres -c "psql" | sed -n 3p`)
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PostgreSQL空间占用失败")
}
data := []LoadInfo{
{"启动时间", carbon.Parse(tools.Exec(`echo "select pg_postmaster_start_time();" | su - postgres -c "psql" | sed -n 3p | cut -d'.' -f1`)).ToDateTimeString()},
{"进程 PID", tools.Exec(`echo "select pg_backend_pid();" | su - postgres -c "psql" | sed -n 3p`)},
{"进程数", tools.Exec(`ps aux | grep postgres | grep -v grep | wc -l`)},
{"总连接数", tools.Exec(`echo "SELECT count(*) FROM pg_stat_activity WHERE NOT pid=pg_backend_pid();" | su - postgres -c "psql" | sed -n 3p`)},
{"空间占用", tools.Exec(`echo "select pg_size_pretty(pg_database_size('postgres'));" | su - postgres -c "psql" | sed -n 3p`)},
{"启动时间", carbon.Parse(time).ToDateTimeString()},
{"进程 PID", pid},
{"进程数", process},
{"总连接数", connections},
{"空间占用", storage},
}
return controllers.Success(ctx, data)
@@ -224,7 +219,11 @@ func (r *Postgresql16Controller) Log(ctx http.Context) http.Response {
return check
}
log := tools.Exec("tail -n 100 /www/server/postgresql/logs/postgresql-" + carbon.Now().ToDateString() + ".log")
log, err := tools.Exec("tail -n 100 /www/server/postgresql/logs/postgresql-" + carbon.Now().ToDateString() + ".log")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, log)
}
return controllers.Success(ctx, log)
}
@@ -235,7 +234,10 @@ func (r *Postgresql16Controller) ClearLog(ctx http.Context) http.Response {
return check
}
tools.Exec("echo '' > /www/server/postgresql/logs/postgresql-" + carbon.Now().ToDateString() + ".log")
if out, err := tools.Exec("echo '' > /www/server/postgresql/logs/postgresql-" + carbon.Now().ToDateString() + ".log"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}
@@ -246,9 +248,12 @@ func (r *Postgresql16Controller) DatabaseList(ctx http.Context) http.Response {
return check
}
status := tools.Exec("systemctl status postgresql | grep Active | grep -v grep | awk '{print $2}'")
if status != "active" {
return controllers.Error(ctx, http.StatusInternalServerError, "PostgreSQL 已停止运行")
status, err := tools.ServiceStatus("postgresql")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PostgreSQL状态失败")
}
if !status {
return controllers.Error(ctx, http.StatusInternalServerError, "PostgreSQL已停止运行")
}
type database struct {
@@ -257,7 +262,10 @@ func (r *Postgresql16Controller) DatabaseList(ctx http.Context) http.Response {
Encoding string `json:"encoding"`
}
raw := tools.Exec(`echo "\l" | su - postgres -c "psql"`)
raw, err := tools.Exec(`echo "\l" | su - postgres -c "psql"`)
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, raw)
}
databases := strings.Split(raw, "\n")
if len(databases) >= 4 {
databases = databases[3 : len(databases)-1]
@@ -326,13 +334,23 @@ func (r *Postgresql16Controller) AddDatabase(ctx http.Context) http.Response {
user := ctx.Request().Input("user")
password := ctx.Request().Input("password")
tools.Exec(`echo "CREATE DATABASE ` + database + `;" | su - postgres -c "psql"`)
tools.Exec(`echo "CREATE USER ` + user + ` WITH PASSWORD '` + password + `';" | su - postgres -c "psql"`)
tools.Exec(`echo "ALTER DATABASE ` + database + ` OWNER TO ` + user + `;" | su - postgres -c "psql"`)
tools.Exec(`echo "GRANT ALL PRIVILEGES ON DATABASE ` + database + ` TO ` + user + `;" | su - postgres -c "psql"`)
if out, err := tools.Exec(`echo "CREATE DATABASE ` + database + `;" | su - postgres -c "psql"`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec(`echo "CREATE USER ` + user + ` WITH PASSWORD '` + password + `';" | su - postgres -c "psql"`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec(`echo "ALTER DATABASE ` + database + ` OWNER TO ` + user + `;" | su - postgres -c "psql"`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec(`echo "GRANT ALL PRIVILEGES ON DATABASE ` + database + ` TO ` + user + `;" | su - postgres -c "psql"`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
userConfig := "host " + database + " " + user + " 127.0.0.1/32 scram-sha-256"
tools.Exec(`echo "` + userConfig + `" >> /www/server/postgresql/data/pg_hba.conf`)
if out, err := tools.Exec(`echo "` + userConfig + `" >> /www/server/postgresql/data/pg_hba.conf`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return r.Reload(ctx)
}
@@ -355,7 +373,9 @@ func (r *Postgresql16Controller) DeleteDatabase(ctx http.Context) http.Response
}
database := ctx.Request().Input("database")
tools.Exec(`echo "DROP DATABASE ` + database + `;" | su - postgres -c "psql"`)
if out, err := tools.Exec(`echo "DROP DATABASE ` + database + `;" | su - postgres -c "psql"`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}
@@ -369,7 +389,6 @@ func (r *Postgresql16Controller) BackupList(ctx http.Context) http.Response {
backupList, err := r.backup.PostgresqlList()
if err != nil {
facades.Log().Info("[PostgreSQL] 获取备份列表失败:" + err.Error())
return controllers.Error(ctx, http.StatusInternalServerError, "获取备份列表失败")
}
@@ -445,8 +464,7 @@ func (r *Postgresql16Controller) CreateBackup(ctx http.Context) http.Response {
database := ctx.Request().Input("database")
err = r.backup.PostgresqlBackup(database)
if err != nil {
facades.Log().Info("[PostgreSQL] 创建备份失败:" + err.Error())
return controllers.Error(ctx, http.StatusInternalServerError, "创建备份失败")
return controllers.Error(ctx, http.StatusInternalServerError, err.Error())
}
return controllers.Success(ctx, nil)
@@ -496,7 +514,6 @@ func (r *Postgresql16Controller) RestoreBackup(ctx http.Context) http.Response {
err = r.backup.PostgresqlRestore(ctx.Request().Input("database"), ctx.Request().Input("backup"))
if err != nil {
facades.Log().Info("[PostgreSQL] 还原失败:" + err.Error())
return controllers.Error(ctx, http.StatusInternalServerError, "还原失败: "+err.Error())
}
@@ -515,7 +532,10 @@ func (r *Postgresql16Controller) UserList(ctx http.Context) http.Response {
Role string `json:"role"`
}
raw := tools.Exec(`echo "\du" | su - postgres -c "psql"`)
raw, err := tools.Exec(`echo "\du" | su - postgres -c "psql"`)
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, raw)
}
users := strings.Split(raw, "\n")
if len(users) < 4 {
return controllers.Error(ctx, http.StatusInternalServerError, "用户列表为空")
@@ -578,11 +598,17 @@ func (r *Postgresql16Controller) AddUser(ctx http.Context) http.Response {
user := ctx.Request().Input("user")
password := ctx.Request().Input("password")
database := ctx.Request().Input("database")
tools.Exec(`echo "CREATE USER ` + user + ` WITH PASSWORD '` + password + `';" | su - postgres -c "psql"`)
tools.Exec(`echo "GRANT ALL PRIVILEGES ON DATABASE ` + database + ` TO ` + user + `;" | su - postgres -c "psql"`)
if out, err := tools.Exec(`echo "CREATE USER ` + user + ` WITH PASSWORD '` + password + `';" | su - postgres -c "psql"`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec(`echo "GRANT ALL PRIVILEGES ON DATABASE ` + database + ` TO ` + user + `;" | su - postgres -c "psql"`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
userConfig := "host " + database + " " + user + " 127.0.0.1/32 scram-sha-256"
tools.Exec(`echo "` + userConfig + `" >> /www/server/postgresql/data/pg_hba.conf`)
if out, err := tools.Exec(`echo "` + userConfig + `" >> /www/server/postgresql/data/pg_hba.conf`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return r.Reload(ctx)
}
@@ -605,8 +631,12 @@ func (r *Postgresql16Controller) DeleteUser(ctx http.Context) http.Response {
}
user := ctx.Request().Input("user")
tools.Exec(`echo "DROP USER ` + user + `;" | su - postgres -c "psql"`)
tools.Exec(`sed -i '/` + user + `/d' /www/server/postgresql/data/pg_hba.conf`)
if out, err := tools.Exec(`echo "DROP USER ` + user + `;" | su - postgres -c "psql"`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec(`sed -i '/` + user + `/d' /www/server/postgresql/data/pg_hba.conf`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return r.Reload(ctx)
}
@@ -631,7 +661,9 @@ func (r *Postgresql16Controller) SetUserPassword(ctx http.Context) http.Response
user := ctx.Request().Input("user")
password := ctx.Request().Input("password")
tools.Exec(`echo "ALTER USER ` + user + ` WITH PASSWORD '` + password + `';" | su - postgres -c "psql"`)
if out, err := tools.Exec(`echo "ALTER USER ` + user + ` WITH PASSWORD '` + password + `';" | su - postgres -c "psql"`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}

View File

@@ -30,16 +30,12 @@ func (r *PureFtpdController) Status(ctx http.Context) http.Response {
return check
}
status := tools.Exec("systemctl status pure-ftpd | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
status, err := tools.ServiceStatus("pure-ftpd")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PureFtpd状态失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, status)
}
// Restart 重启服务
@@ -49,17 +45,12 @@ func (r *PureFtpdController) Restart(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl restart pure-ftpd")
status := tools.Exec("systemctl status pure-ftpd | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PureFtpd状态失败")
err := tools.ServiceRestart("pure-ftpd")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重启PureFtpd失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
// Start 启动服务
@@ -69,17 +60,12 @@ func (r *PureFtpdController) Start(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl start pure-ftpd")
status := tools.Exec("systemctl status pure-ftpd | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PureFtpd状态失败")
err := tools.ServiceStart("pure-ftpd")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "启动PureFtpd失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
// Stop 停止服务
@@ -89,17 +75,12 @@ func (r *PureFtpdController) Stop(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl stop pure-ftpd")
status := tools.Exec("systemctl status pure-ftpd | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PureFtpd状态失败")
err := tools.ServiceStop("pure-ftpd")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "停止PureFtpd失败")
}
if status != "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
// List 获取用户列表
@@ -109,8 +90,8 @@ func (r *PureFtpdController) List(ctx http.Context) http.Response {
return check
}
listRaw := tools.Exec("pure-pw list")
if len(listRaw) == 0 {
listRaw, err := tools.Exec("pure-pw list")
if err != nil {
return controllers.Success(ctx, http.Json{
"total": 0,
"items": []User{},
@@ -188,8 +169,12 @@ func (r *PureFtpdController) Add(ctx http.Context) http.Response {
if err = tools.Chown(path, "www", "www"); err != nil {
return nil
}
tools.Exec(`yes '` + password + `' | pure-pw useradd ` + username + ` -u www -g www -d ` + path)
tools.Exec("pure-pw mkdb")
if out, err := tools.Exec(`yes '` + password + `' | pure-pw useradd ` + username + ` -u www -g www -d ` + path); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("pure-pw mkdb"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}
@@ -213,8 +198,12 @@ func (r *PureFtpdController) Delete(ctx http.Context) http.Response {
username := ctx.Request().Input("username")
tools.Exec("pure-pw userdel " + username + " -m")
tools.Exec("pure-pw mkdb")
if out, err := tools.Exec("pure-pw userdel " + username + " -m"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("pure-pw mkdb"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}
@@ -240,8 +229,12 @@ func (r *PureFtpdController) ChangePassword(ctx http.Context) http.Response {
username := ctx.Request().Input("username")
password := ctx.Request().Input("password")
tools.Exec(`yes '` + password + `' | pure-pw passwd ` + username + ` -m`)
tools.Exec("pure-pw mkdb")
if out, err := tools.Exec(`yes '` + password + `' | pure-pw passwd ` + username + ` -m`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("pure-pw mkdb"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}
@@ -253,8 +246,8 @@ func (r *PureFtpdController) GetPort(ctx http.Context) http.Response {
return check
}
port := tools.Exec(`cat /www/server/pure-ftpd/etc/pure-ftpd.conf | grep "Bind" | awk '{print $2}' | awk -F "," '{print $2}'`)
if len(port) == 0 {
port, err := tools.Exec(`cat /www/server/pure-ftpd/etc/pure-ftpd.conf | grep "Bind" | awk '{print $2}' | awk -F "," '{print $2}'`)
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取PureFtpd端口失败")
}
@@ -279,15 +272,24 @@ func (r *PureFtpdController) SetPort(ctx http.Context) http.Response {
}
port := ctx.Request().Input("port")
tools.Exec(`sed -i "s/Bind.*/Bind 0.0.0.0,` + port + `/g" /www/server/pure-ftpd/etc/pure-ftpd.conf`)
if tools.IsRHEL() {
tools.Exec("firewall-cmd --zone=public --add-port=" + port + "/tcp --permanent")
tools.Exec("firewall-cmd --reload")
} else {
tools.Exec("ufw allow " + port + "/tcp")
tools.Exec("ufw reload")
if out, err := tools.Exec(`sed -i "s/Bind.*/Bind 0.0.0.0,` + port + `/g" /www/server/pure-ftpd/etc/pure-ftpd.conf`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if tools.IsRHEL() {
if out, err := tools.Exec("firewall-cmd --zone=public --add-port=" + port + "/tcp --permanent"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("firewall-cmd --reload"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
} else {
if out, err := tools.Exec("ufw allow " + port + "/tcp"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("ufw reload"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
}
tools.Exec("systemctl restart pure-ftpd")
return controllers.Success(ctx, nil)
return r.Restart(ctx)
}

View File

@@ -23,16 +23,12 @@ func (r *RedisController) Status(ctx http.Context) http.Response {
return check
}
status := tools.Exec("systemctl status redis | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
status, err := tools.ServiceStatus("redis")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取Redis状态失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, status)
}
// Restart 重启服务
@@ -42,17 +38,11 @@ func (r *RedisController) Restart(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl restart redis")
status := tools.Exec("systemctl status redis | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取Redis状态失败")
if err := tools.ServiceRestart("redis"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重启Redis失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
// Start 启动服务
@@ -62,17 +52,11 @@ func (r *RedisController) Start(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl start redis")
status := tools.Exec("systemctl status redis | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取Redis状态失败")
if err := tools.ServiceStart("redis"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "启动Redis失败")
}
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
// Stop 停止服务
@@ -82,17 +66,11 @@ func (r *RedisController) Stop(ctx http.Context) http.Response {
return check
}
tools.Exec("systemctl stop redis")
status := tools.Exec("systemctl status redis | grep Active | grep -v grep | awk '{print $2}'")
if len(status) == 0 {
return controllers.Error(ctx, http.StatusInternalServerError, "获取Redis状态失败")
if err := tools.ServiceStop("redis"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "停止Redis失败")
}
if status != "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
}
return controllers.Success(ctx, nil)
}
// GetConfig 获取配置
@@ -137,13 +115,16 @@ func (r *RedisController) Load(ctx http.Context) http.Response {
return check
}
status := tools.Exec("systemctl status redis | grep Active | grep -v grep | awk '{print $2}'")
if status != "active" {
return controllers.Error(ctx, http.StatusInternalServerError, "Redis 已停止运行")
status, err := tools.ServiceStatus("redis")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取Redis状态失败")
}
if !status {
return controllers.Error(ctx, http.StatusInternalServerError, "Redis已停止运行")
}
raw := tools.Exec("redis-cli info")
if len(raw) == 0 {
raw, err := tools.Exec("redis-cli info")
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取Redis负载失败")
}

View File

@@ -36,7 +36,7 @@ func (r *S3fsController) List(ctx http.Context) http.Response {
var s3fsList []S3fsMount
err := json.UnmarshalString(r.setting.Get("s3fs", "[]"), &s3fsList)
if err != nil {
return controllers.Error(ctx, http.StatusUnprocessableEntity, "获取 S3fs 挂载失败")
return controllers.Error(ctx, http.StatusInternalServerError, "获取 S3fs 挂载失败")
}
startIndex := (page - 1) * limit
@@ -120,15 +120,16 @@ func (r *S3fsController) Add(ctx http.Context) http.Response {
if err = tools.Write("/etc/passwd-s3fs-"+cast.ToString(id), password, 0600); err != nil {
return nil
}
tools.Exec(`echo 's3fs#` + bucket + ` ` + path + ` fuse _netdev,allow_other,nonempty,url=` + url + `,passwd_file=/etc/passwd-s3fs-` + cast.ToString(id) + ` 0 0' >> /etc/fstab`)
mountCheck := tools.Exec("mount -a 2>&1")
if len(mountCheck) != 0 {
tools.Exec(`sed -i 's@^s3fs#` + bucket + `\s` + path + `.*$@@g' /etc/fstab`)
out, err := tools.Exec(`echo 's3fs#` + bucket + ` ` + path + ` fuse _netdev,allow_other,nonempty,url=` + url + `,passwd_file=/etc/passwd-s3fs-` + cast.ToString(id) + ` 0 0' >> /etc/fstab`)
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if mountCheck, err := tools.Exec("mount -a 2>&1"); err != nil {
_, _ = tools.Exec(`sed -i 's@^s3fs#` + bucket + `\s` + path + `.*$@@g' /etc/fstab`)
return controllers.Error(ctx, http.StatusInternalServerError, "检测到/etc/fstab有误: "+mountCheck)
}
dfCheck := tools.Exec("df -h | grep " + path + " 2>&1")
if len(dfCheck) == 0 {
tools.Exec(`sed -i 's@^s3fs#` + bucket + `\s` + path + `.*$@@g' /etc/fstab`)
if _, err := tools.Exec("df -h | grep " + path + " 2>&1"); err != nil {
_, _ = tools.Exec(`sed -i 's@^s3fs#` + bucket + `\s` + path + `.*$@@g' /etc/fstab`)
return controllers.Error(ctx, http.StatusInternalServerError, "挂载失败,请检查配置是否正确")
}
@@ -179,11 +180,16 @@ func (r *S3fsController) Delete(ctx http.Context) http.Response {
return controllers.Error(ctx, http.StatusUnprocessableEntity, "挂载ID不存在")
}
tools.Exec(`fusermount -u '` + mount.Path + `' 2>&1`)
tools.Exec(`umount '` + mount.Path + `' 2>&1`)
tools.Exec(`sed -i 's@^s3fs#` + mount.Bucket + `\s` + mount.Path + `.*$@@g' /etc/fstab`)
mountCheck := tools.Exec("mount -a 2>&1")
if len(mountCheck) != 0 {
if out, err := tools.Exec(`fusermount -u '` + mount.Path + `' 2>&1`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec(`umount '` + mount.Path + `' 2>&1`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec(`sed -i 's@^s3fs#` + mount.Bucket + `\s` + mount.Path + `.*$@@g' /etc/fstab`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if mountCheck, err := tools.Exec("mount -a 2>&1"); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "检测到/etc/fstab有误: "+mountCheck)
}
tools.Remove("/etc/passwd-s3fs-" + cast.ToString(mount.ID))

View File

@@ -34,12 +34,12 @@ func (r *SupervisorController) Status(ctx http.Context) http.Response {
return check
}
status := tools.Exec(`systemctl status ` + r.ServiceName + ` | grep Active | grep -v grep | awk '{print $2}'`)
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
status, err := tools.ServiceStatus(r.ServiceName)
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "获取Supervisor状态失败")
}
return controllers.Success(ctx, status)
}
// Start 启动
@@ -49,13 +49,11 @@ func (r *SupervisorController) Start(ctx http.Context) http.Response {
return check
}
tools.Exec(`systemctl start ` + r.ServiceName)
status := tools.Exec(`systemctl status ` + r.ServiceName + ` | grep Active | grep -v grep | awk '{print $2}'`)
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
if err := tools.ServiceStart(r.ServiceName); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "启动Supervisor失败")
}
return controllers.Success(ctx, nil)
}
// Stop 停止
@@ -65,13 +63,11 @@ func (r *SupervisorController) Stop(ctx http.Context) http.Response {
return check
}
tools.Exec(`systemctl stop ` + r.ServiceName)
status := tools.Exec(`systemctl status ` + r.ServiceName + ` | grep Active | grep -v grep | awk '{print $2}'`)
if status != "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
if err := tools.ServiceStop(r.ServiceName); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "停止Supervisor失败")
}
return controllers.Success(ctx, nil)
}
// Restart 重启
@@ -81,13 +77,11 @@ func (r *SupervisorController) Restart(ctx http.Context) http.Response {
return check
}
tools.Exec(`systemctl restart ` + r.ServiceName)
status := tools.Exec(`systemctl status ` + r.ServiceName + ` | grep Active | grep -v grep | awk '{print $2}'`)
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
if err := tools.ServiceRestart(r.ServiceName); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重启Supervisor失败")
}
return controllers.Success(ctx, nil)
}
// Reload 重载
@@ -97,13 +91,11 @@ func (r *SupervisorController) Reload(ctx http.Context) http.Response {
return check
}
tools.Exec(`systemctl reload ` + r.ServiceName)
status := tools.Exec(`systemctl status ` + r.ServiceName + ` | grep Active | grep -v grep | awk '{print $2}'`)
if status == "active" {
return controllers.Success(ctx, true)
} else {
return controllers.Success(ctx, false)
if err := tools.ServiceReload(r.ServiceName); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "重载Supervisor失败")
}
return controllers.Success(ctx, nil)
}
// Log 日志
@@ -113,7 +105,11 @@ func (r *SupervisorController) Log(ctx http.Context) http.Response {
return check
}
log := tools.Exec(`tail -n 200 /var/log/supervisor/supervisord.log`)
log, err := tools.Exec(`tail -n 200 /var/log/supervisor/supervisord.log`)
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, log)
}
return controllers.Success(ctx, log)
}
@@ -124,7 +120,10 @@ func (r *SupervisorController) ClearLog(ctx http.Context) http.Response {
return check
}
tools.Exec(`echo "" > /var/log/supervisor/supervisord.log`)
if out, err := tools.Exec(`echo "" > /var/log/supervisor/supervisord.log`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}
@@ -141,6 +140,7 @@ func (r *SupervisorController) Config(ctx http.Context) http.Response {
} else {
config = tools.Read(`/etc/supervisor/supervisord.conf`)
}
return controllers.Success(ctx, config)
}
@@ -160,7 +160,7 @@ func (r *SupervisorController) SaveConfig(ctx http.Context) http.Response {
}
if err != nil {
return controllers.Error(ctx, http.StatusUnprocessableEntity, err.Error())
return controllers.Error(ctx, http.StatusInternalServerError, err.Error())
}
return r.Restart(ctx)
@@ -183,7 +183,11 @@ func (r *SupervisorController) Processes(ctx http.Context) http.Response {
Uptime string `json:"uptime"`
}
out := tools.Exec(`supervisorctl status | awk '{print $1}'`)
out, err := tools.Exec(`supervisorctl status | awk '{print $1}'`)
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
var processList []process
for _, line := range strings.Split(out, "\n") {
if len(line) == 0 {
@@ -192,10 +196,14 @@ func (r *SupervisorController) Processes(ctx http.Context) http.Response {
var p process
p.Name = line
p.Status = tools.Exec(`supervisorctl status ` + line + ` | awk '{print $2}'`)
if status, err := tools.Exec(`supervisorctl status ` + line + ` | awk '{print $2}'`); err == nil {
p.Status = status
}
if p.Status == "RUNNING" {
p.Pid = strings.ReplaceAll(tools.Exec(`supervisorctl status `+line+` | awk '{print $4}'`), ",", "")
p.Uptime = tools.Exec(`supervisorctl status ` + line + ` | awk '{print $6}'`)
pid, _ := tools.Exec(`supervisorctl status ` + line + ` | awk '{print $4}'`)
p.Pid = strings.ReplaceAll(pid, ",", "")
uptime, _ := tools.Exec(`supervisorctl status ` + line + ` | awk '{print $6}'`)
p.Uptime = uptime
} else {
p.Pid = "-"
p.Uptime = "-"
@@ -233,7 +241,10 @@ func (r *SupervisorController) StartProcess(ctx http.Context) http.Response {
}
process := ctx.Request().Input("process")
tools.Exec(`supervisorctl start ` + process)
if out, err := tools.Exec(`supervisorctl start ` + process); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}
@@ -245,7 +256,10 @@ func (r *SupervisorController) StopProcess(ctx http.Context) http.Response {
}
process := ctx.Request().Input("process")
tools.Exec(`supervisorctl stop ` + process)
if out, err := tools.Exec(`supervisorctl stop ` + process); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}
@@ -257,7 +271,10 @@ func (r *SupervisorController) RestartProcess(ctx http.Context) http.Response {
}
process := ctx.Request().Input("process")
tools.Exec(`supervisorctl restart ` + process)
if out, err := tools.Exec(`supervisorctl restart ` + process); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}
@@ -270,13 +287,22 @@ func (r *SupervisorController) ProcessLog(ctx http.Context) http.Response {
process := ctx.Request().Input("process")
var logPath string
var err error
if tools.IsRHEL() {
logPath = tools.Exec(`cat '/etc/supervisord.d/` + process + `.conf' | grep stdout_logfile= | awk -F "=" '{print $2}'`)
logPath, err = tools.Exec(`cat '/etc/supervisord.d/` + process + `.conf' | grep stdout_logfile= | awk -F "=" '{print $2}'`)
} else {
logPath = tools.Exec(`cat '/etc/supervisor/conf.d/` + process + `.conf' | grep stdout_logfile= | awk -F "=" '{print $2}'`)
logPath, err = tools.Exec(`cat '/etc/supervisor/conf.d/` + process + `.conf' | grep stdout_logfile= | awk -F "=" '{print $2}'`)
}
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "无法从进程"+process+"的配置文件中获取日志路径")
}
log, err := tools.Exec(`tail -n 200 ` + logPath)
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, log)
}
log := tools.Exec(`tail -n 200 ` + logPath)
return controllers.Success(ctx, log)
}
@@ -289,13 +315,21 @@ func (r *SupervisorController) ClearProcessLog(ctx http.Context) http.Response {
process := ctx.Request().Input("process")
var logPath string
var err error
if tools.IsRHEL() {
logPath = tools.Exec(`cat '/etc/supervisord.d/` + process + `.conf' | grep stdout_logfile= | awk -F "=" '{print $2}'`)
logPath, err = tools.Exec(`cat '/etc/supervisord.d/` + process + `.conf' | grep stdout_logfile= | awk -F "=" '{print $2}'`)
} else {
logPath = tools.Exec(`cat '/etc/supervisor/conf.d/` + process + `.conf' | grep stdout_logfile= | awk -F "=" '{print $2}'`)
logPath, err = tools.Exec(`cat '/etc/supervisor/conf.d/` + process + `.conf' | grep stdout_logfile= | awk -F "=" '{print $2}'`)
}
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "无法从进程"+process+"的配置文件中获取日志路径")
}
if out, err := tools.Exec(`echo "" > ` + logPath); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
tools.Exec(`echo "" > ` + logPath)
return controllers.Success(ctx, nil)
}
@@ -337,9 +371,15 @@ func (r *SupervisorController) SaveProcessConfig(ctx http.Context) http.Response
return controllers.Error(ctx, http.StatusUnprocessableEntity, err.Error())
}
tools.Exec(`supervisorctl reread`)
tools.Exec(`supervisorctl update`)
tools.Exec(`supervisorctl start ` + process)
if out, err := tools.Exec(`supervisorctl reread`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec(`supervisorctl update`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec(`supervisorctl start ` + process); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}
@@ -392,9 +432,15 @@ stdout_logfile_maxbytes=2MB
return controllers.Error(ctx, http.StatusUnprocessableEntity, err.Error())
}
tools.Exec(`supervisorctl reread`)
tools.Exec(`supervisorctl update`)
tools.Exec(`supervisorctl start ` + name)
if out, err := tools.Exec(`supervisorctl reread`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec(`supervisorctl update`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec(`supervisorctl start ` + name); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}
@@ -407,18 +453,31 @@ func (r *SupervisorController) DeleteProcess(ctx http.Context) http.Response {
}
process := ctx.Request().Input("process")
tools.Exec(`supervisorctl stop ` + process)
if out, err := tools.Exec(`supervisorctl stop ` + process); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
var logPath string
var err error
if tools.IsRHEL() {
logPath = tools.Exec(`cat '/etc/supervisord.d/` + process + `.conf' | grep stdout_logfile= | awk -F "=" '{print $2}'`)
logPath, err = tools.Exec(`cat '/etc/supervisord.d/` + process + `.conf' | grep stdout_logfile= | awk -F "=" '{print $2}'`)
tools.Remove(`/etc/supervisord.d/` + process + `.conf`)
} else {
logPath = tools.Exec(`cat '/etc/supervisor/conf.d/` + process + `.conf' | grep stdout_logfile= | awk -F "=" '{print $2}'`)
logPath, err = tools.Exec(`cat '/etc/supervisor/conf.d/` + process + `.conf' | grep stdout_logfile= | awk -F "=" '{print $2}'`)
tools.Remove(`/etc/supervisor/conf.d/` + process + `.conf`)
}
if err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, "无法从进程"+process+"的配置文件中获取日志路径")
}
tools.Remove(logPath)
tools.Exec(`supervisorctl reread`)
tools.Exec(`supervisorctl update`)
if out, err := tools.Exec(`supervisorctl reread`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec(`supervisorctl update`); err != nil {
return controllers.Error(ctx, http.StatusInternalServerError, out)
}
return controllers.Success(ctx, nil)
}

View File

@@ -28,7 +28,7 @@ func (r *ToolBoxController) GetDNS(ctx http.Context) http.Response {
raw := tools.Read("/etc/resolv.conf")
match := regexp.MustCompile(`nameserver\s+(\S+)`).FindAllStringSubmatch(raw, -1)
if len(match) == 0 {
return controllers.Error(ctx, http.StatusUnprocessableEntity, "找不到 DNS 信息")
return controllers.Error(ctx, http.StatusInternalServerError, "找不到 DNS 信息")
}
var dns []string
@@ -58,7 +58,7 @@ func (r *ToolBoxController) SetDNS(ctx http.Context) http.Response {
dns += "nameserver " + dns2 + "\n"
if err := tools.Write("/etc/resolv.conf", dns, 0644); err != nil {
return controllers.Error(ctx, http.StatusUnprocessableEntity, "写入 DNS 信息失败")
return controllers.Error(ctx, http.StatusInternalServerError, "写入 DNS 信息失败")
}
return controllers.Success(ctx, nil)
@@ -86,7 +86,11 @@ func (r *ToolBoxController) GetSWAP(ctx http.Context) http.Response {
total = "0.00 B"
}
raw := tools.Exec("LC_ALL=C free | grep Swap")
raw, err := tools.Exec("free | grep Swap")
if err != nil {
return controllers.Error(ctx, http.StatusUnprocessableEntity, "获取 SWAP 信息失败")
}
match := regexp.MustCompile(`Swap:\s+(\d+)\s+(\d+)\s+(\d+)`).FindStringSubmatch(raw)
if len(match) > 0 {
used = tools.FormatBytes(cast.ToFloat64(match[2]) * 1024)
@@ -111,28 +115,48 @@ func (r *ToolBoxController) SetSWAP(ctx http.Context) http.Response {
size := ctx.Request().InputInt("size")
if tools.Exists("/www/swap") {
tools.Exec("swapoff /www/swap")
tools.Exec("rm -f /www/swap")
tools.Exec("sed -i '/www\\/swap/d' /etc/fstab")
if out, err := tools.Exec("swapoff /www/swap"); err != nil {
return controllers.Error(ctx, http.StatusUnprocessableEntity, out)
}
if out, err := tools.Exec("rm -f /www/swap"); err != nil {
return controllers.Error(ctx, http.StatusUnprocessableEntity, out)
}
if out, err := tools.Exec("sed -i '/www\\/swap/d' /etc/fstab"); err != nil {
return controllers.Error(ctx, http.StatusUnprocessableEntity, out)
}
}
if size > 1 {
free := tools.Exec("df -k /www | awk '{print $4}' | tail -n 1")
free, err := tools.Exec("df -k /www | awk '{print $4}' | tail -n 1")
if err != nil {
return controllers.Error(ctx, http.StatusUnprocessableEntity, "获取磁盘空间失败")
}
if cast.ToInt64(free)*1024 < int64(size)*1024*1024 {
return controllers.Error(ctx, http.StatusUnprocessableEntity, "磁盘空间不足,当前剩余 "+tools.FormatBytes(cast.ToFloat64(free)))
}
if strings.Contains(tools.Exec("df -T /www | awk '{print $2}' | tail -n 1"), "btrfs") {
tools.Exec("btrfs filesystem mkswapfile --size " + cast.ToString(size) + "M --uuid clear /www/swap")
btrfsCheck, _ := tools.Exec("df -T /www | awk '{print $2}' | tail -n 1")
if strings.Contains(btrfsCheck, "btrfs") {
if out, err := tools.Exec("btrfs filesystem mkswapfile --size " + cast.ToString(size) + "M --uuid clear /www/swap"); err != nil {
return controllers.Error(ctx, http.StatusUnprocessableEntity, out)
}
} else {
tools.Exec("dd if=/dev/zero of=/www/swap bs=1M count=" + cast.ToString(size))
tools.Exec("mkswap -f /www/swap")
if out, err := tools.Exec("dd if=/dev/zero of=/www/swap bs=1M count=" + cast.ToString(size)); err != nil {
return controllers.Error(ctx, http.StatusUnprocessableEntity, out)
}
if out, err := tools.Exec("mkswap -f /www/swap"); err != nil {
return controllers.Error(ctx, http.StatusUnprocessableEntity, out)
}
if err := tools.Chmod("/www/swap", 0600); err != nil {
return controllers.Error(ctx, http.StatusUnprocessableEntity, "设置 SWAP 权限失败")
}
}
tools.Exec("swapon /www/swap")
tools.Exec("echo '/www/swap swap swap defaults 0 0' >> /etc/fstab")
if out, err := tools.Exec("swapon /www/swap"); err != nil {
return controllers.Error(ctx, http.StatusUnprocessableEntity, out)
}
if out, err := tools.Exec("echo '/www/swap swap swap defaults 0 0' >> /etc/fstab"); err != nil {
return controllers.Error(ctx, http.StatusUnprocessableEntity, out)
}
}
return controllers.Success(ctx, nil)
@@ -145,7 +169,11 @@ func (r *ToolBoxController) GetTimezone(ctx http.Context) http.Response {
return check
}
raw := tools.Exec("LC_ALL=C timedatectl | grep zone")
raw, err := tools.Exec("timedatectl | grep zone")
if err != nil {
return controllers.Error(ctx, http.StatusUnprocessableEntity, "获取时区信息失败")
}
match := regexp.MustCompile(`zone:\s+(\S+)`).FindStringSubmatch(raw)
if len(match) == 0 {
return controllers.Error(ctx, http.StatusUnprocessableEntity, "找不到时区信息")
@@ -156,7 +184,10 @@ func (r *ToolBoxController) GetTimezone(ctx http.Context) http.Response {
Value string `json:"value"`
}
zonesRaw := tools.Exec("LC_ALL=C timedatectl list-timezones")
zonesRaw, err := tools.Exec("timedatectl list-timezones")
if err != nil {
return controllers.Error(ctx, http.StatusUnprocessableEntity, "获取时区列表失败")
}
zones := strings.Split(zonesRaw, "\n")
var zonesList []zone

View File

@@ -6,6 +6,7 @@ import (
"github.com/goravel/framework/contracts/http"
"github.com/spf13/cast"
commonrequests "panel/app/http/requests/common"
"panel/pkg/tools"
)
@@ -28,33 +29,47 @@ func (r *SafeController) GetFirewallStatus(ctx http.Context) http.Response {
// SetFirewallStatus 设置防火墙状态
func (r *SafeController) SetFirewallStatus(ctx http.Context) http.Response {
var out string
var err error
if ctx.Request().InputBool("status") {
if tools.IsRHEL() {
out = tools.Exec("systemctl start firewalld")
out, err = tools.Exec("systemctl start firewalld")
} else {
out = tools.Exec("echo y | ufw enable")
out, err = tools.Exec("echo y | ufw enable")
}
} else {
if tools.IsRHEL() {
out = tools.Exec("systemctl stop firewalld")
out, err = tools.Exec("systemctl stop firewalld")
} else {
out = tools.Exec("ufw disable")
out, err = tools.Exec("ufw disable")
}
}
return Success(ctx, out)
if err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
return Success(ctx, nil)
}
// GetFirewallRules 获取防火墙规则
func (r *SafeController) GetFirewallRules(ctx http.Context) http.Response {
var paginateRequest commonrequests.Paginate
sanitize := Sanitize(ctx, &paginateRequest)
if sanitize != nil {
return sanitize
}
if !r.firewallStatus() {
return Success(ctx, nil)
}
page := ctx.Request().QueryInt("page", 1)
limit := ctx.Request().QueryInt("limit", 10)
var rules []map[string]string
if tools.IsRHEL() {
out := tools.Exec("firewall-cmd --list-all 2>&1")
out, err := tools.Exec("firewall-cmd --list-all 2>&1")
if err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
match := regexp.MustCompile(`ports: (.*)`).FindStringSubmatch(out)
if len(match) == 0 {
return Success(ctx, http.Json{
@@ -63,7 +78,6 @@ func (r *SafeController) GetFirewallRules(ctx http.Context) http.Response {
})
}
ports := strings.Split(match[1], " ")
var rules []map[string]string
for _, port := range ports {
rule := strings.Split(port, "/")
rules = append(rules, map[string]string{
@@ -71,33 +85,18 @@ func (r *SafeController) GetFirewallRules(ctx http.Context) http.Response {
"protocol": rule[1],
})
}
startIndex := (page - 1) * limit
endIndex := page * limit
if startIndex > len(rules) {
return Success(ctx, http.Json{
"total": 0,
"items": []map[string]string{},
})
}
if endIndex > len(rules) {
endIndex = len(rules)
}
pagedRules := rules[startIndex:endIndex]
return Success(ctx, http.Json{
"total": len(rules),
"items": pagedRules,
})
} else {
out := tools.Exec("ufw status | grep -v '(v6)' | grep ALLOW | awk '{print $1}'")
out, err := tools.Exec("ufw status | grep -v '(v6)' | grep ALLOW | awk '{print $1}'")
if err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
if len(out) == 0 {
return Success(ctx, http.Json{
"total": 0,
"items": []map[string]string{},
})
}
var rules []map[string]string
for _, port := range strings.Split(out, "\n") {
rule := strings.Split(port, "/")
rules = append(rules, map[string]string{
@@ -105,31 +104,31 @@ func (r *SafeController) GetFirewallRules(ctx http.Context) http.Response {
"protocol": rule[1],
})
}
}
startIndex := (page - 1) * limit
endIndex := page * limit
if startIndex > len(rules) {
return Success(ctx, http.Json{
"total": 0,
"items": []map[string]string{},
})
}
if endIndex > len(rules) {
endIndex = len(rules)
}
pagedRules := rules[startIndex:endIndex]
startIndex := (paginateRequest.Page - 1) * paginateRequest.Limit
endIndex := paginateRequest.Page * paginateRequest.Limit
if startIndex > len(rules) {
return Success(ctx, http.Json{
"total": len(rules),
"items": pagedRules,
"total": 0,
"items": []map[string]string{},
})
}
if endIndex > len(rules) {
endIndex = len(rules)
}
pagedRules := rules[startIndex:endIndex]
return Success(ctx, http.Json{
"total": len(rules),
"items": pagedRules,
})
}
// AddFirewallRule 添加防火墙规则
func (r *SafeController) AddFirewallRule(ctx http.Context) http.Response {
if !r.firewallStatus() {
return Error(ctx, http.StatusUnprocessableEntity, "防火墙未启动")
return Error(ctx, http.StatusInternalServerError, "防火墙未启动")
}
port := ctx.Request().Input("port")
@@ -153,17 +152,29 @@ func (r *SafeController) AddFirewallRule(ctx http.Context) http.Response {
}
if tools.IsRHEL() {
tools.Exec("firewall-cmd --remove-port=" + cast.ToString(port) + "/" + protocol + " --permanent 2>&1")
tools.Exec("firewall-cmd --add-port=" + cast.ToString(port) + "/" + protocol + " --permanent 2>&1")
tools.Exec("firewall-cmd --reload")
if out, err := tools.Exec("firewall-cmd --remove-port=" + cast.ToString(port) + "/" + protocol + " --permanent 2>&1"); err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("firewall-cmd --add-port=" + cast.ToString(port) + "/" + protocol + " --permanent 2>&1"); err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("firewall-cmd --reload"); err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
} else {
// ufw 需要替换 - 为 : 添加
if strings.Contains(port, "-") {
port = strings.ReplaceAll(port, "-", ":")
}
tools.Exec("ufw delete allow " + cast.ToString(port) + "/" + protocol)
tools.Exec("ufw allow " + cast.ToString(port) + "/" + protocol)
tools.Exec("ufw reload")
if out, err := tools.Exec("ufw delete allow " + cast.ToString(port) + "/" + protocol); err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("ufw allow " + cast.ToString(port) + "/" + protocol); err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("ufw reload"); err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
}
return Success(ctx, nil)
@@ -182,11 +193,19 @@ func (r *SafeController) DeleteFirewallRule(ctx http.Context) http.Response {
}
if tools.IsRHEL() {
tools.Exec("firewall-cmd --remove-port=" + cast.ToString(port) + "/" + protocol + " --permanent 2>&1")
tools.Exec("firewall-cmd --reload")
if out, err := tools.Exec("firewall-cmd --remove-port=" + cast.ToString(port) + "/" + protocol + " --permanent 2>&1"); err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("firewall-cmd --reload"); err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
} else {
tools.Exec("ufw delete allow " + cast.ToString(port) + "/" + protocol)
tools.Exec("ufw reload")
if out, err := tools.Exec("ufw delete allow " + cast.ToString(port) + "/" + protocol); err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("ufw reload"); err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
}
return Success(ctx, nil)
@@ -195,16 +214,17 @@ func (r *SafeController) DeleteFirewallRule(ctx http.Context) http.Response {
// firewallStatus 获取防火墙状态
func (r *SafeController) firewallStatus() bool {
var out string
var err error
var running bool
if tools.IsRHEL() {
out = tools.Exec("systemctl status firewalld | grep Active | awk '{print $3}'")
out, err = tools.Exec("systemctl status firewalld | grep Active | awk '{print $3}'")
if out == "(running)" {
running = true
} else {
running = false
}
} else {
out = tools.Exec("ufw status | grep Status | awk '{print $2}'")
out, err = tools.Exec("ufw status | grep Status | awk '{print $2}'")
if out == "active" {
running = true
} else {
@@ -212,43 +232,63 @@ func (r *SafeController) firewallStatus() bool {
}
}
if err != nil {
return false
}
return running
}
// GetSshStatus 获取 SSH 状态
func (r *SafeController) GetSshStatus(ctx http.Context) http.Response {
var out string
var err error
if tools.IsRHEL() {
out = tools.Exec("systemctl status sshd | grep Active | awk '{print $3}'")
out, err = tools.Exec("systemctl status sshd | grep Active | awk '{print $3}'")
} else {
out = tools.Exec("systemctl status ssh | grep Active | awk '{print $3}'")
out, err = tools.Exec("systemctl status ssh | grep Active | awk '{print $3}'")
}
running := false
if out == "(running)" {
running = true
if err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
return Success(ctx, running)
return Success(ctx, out == "(running)")
}
// SetSshStatus 设置 SSH 状态
func (r *SafeController) SetSshStatus(ctx http.Context) http.Response {
if ctx.Request().InputBool("status") {
if tools.IsRHEL() {
tools.Exec("systemctl enable sshd")
tools.Exec("systemctl start sshd")
if out, err := tools.Exec("systemctl enable sshd"); err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("systemctl start sshd"); err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
} else {
tools.Exec("systemctl enable ssh")
tools.Exec("systemctl start ssh")
if out, err := tools.Exec("systemctl enable ssh"); err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("systemctl start ssh"); err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
}
} else {
if tools.IsRHEL() {
tools.Exec("systemctl stop sshd")
tools.Exec("systemctl disable sshd")
if out, err := tools.Exec("systemctl stop sshd"); err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("systemctl disable sshd"); err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
} else {
tools.Exec("systemctl stop ssh")
tools.Exec("systemctl disable ssh")
if out, err := tools.Exec("systemctl stop ssh"); err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("systemctl disable ssh"); err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
}
}
@@ -257,7 +297,11 @@ func (r *SafeController) SetSshStatus(ctx http.Context) http.Response {
// GetSshPort 获取 SSH 端口
func (r *SafeController) GetSshPort(ctx http.Context) http.Response {
out := tools.Exec("cat /etc/ssh/sshd_config | grep 'Port ' | awk '{print $2}'")
out, err := tools.Exec("cat /etc/ssh/sshd_config | grep 'Port ' | awk '{print $2}'")
if err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
return Success(ctx, out)
}
@@ -268,21 +312,30 @@ func (r *SafeController) SetSshPort(ctx http.Context) http.Response {
return Error(ctx, http.StatusUnprocessableEntity, "参数错误")
}
oldPort := tools.Exec("cat /etc/ssh/sshd_config | grep 'Port ' | awk '{print $2}'")
tools.Exec("sed -i 's/#Port " + oldPort + "/Port " + cast.ToString(port) + "/g' /etc/ssh/sshd_config")
tools.Exec("sed -i 's/Port " + oldPort + "/Port " + cast.ToString(port) + "/g' /etc/ssh/sshd_config")
oldPort, err := tools.Exec("cat /etc/ssh/sshd_config | grep 'Port ' | awk '{print $2}'")
if err != nil {
return Error(ctx, http.StatusInternalServerError, oldPort)
}
_, _ = tools.Exec("sed -i 's/#Port " + oldPort + "/Port " + cast.ToString(port) + "/g' /etc/ssh/sshd_config")
_, _ = tools.Exec("sed -i 's/Port " + oldPort + "/Port " + cast.ToString(port) + "/g' /etc/ssh/sshd_config")
if status := tools.Exec("systemctl status sshd | grep Active | awk '{print $3}'"); status == "(running)" {
tools.Exec("systemctl restart sshd")
out, err := tools.Exec("systemctl status sshd | grep Active | awk '{print $3}'")
if err != nil || out != "(running)" {
Error(ctx, http.StatusInternalServerError, out)
}
_, _ = tools.Exec("systemctl restart sshd")
return Success(ctx, nil)
}
// GetPingStatus 获取 Ping 状态
func (r *SafeController) GetPingStatus(ctx http.Context) http.Response {
if tools.IsRHEL() {
out := tools.Exec(`firewall-cmd --list-all 2>&1`)
out, err := tools.Exec(`firewall-cmd --list-all 2>&1`)
if err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
if !strings.Contains(out, `rule protocol value="icmp" drop`) {
return Success(ctx, true)
} else {
@@ -300,20 +353,34 @@ func (r *SafeController) GetPingStatus(ctx http.Context) http.Response {
// SetPingStatus 设置 Ping 状态
func (r *SafeController) SetPingStatus(ctx http.Context) http.Response {
var out string
var err error
if tools.IsRHEL() {
if ctx.Request().InputBool("status") {
tools.Exec(`firewall-cmd --permanent --remove-rich-rule='rule protocol value=icmp drop'`)
out, err = tools.Exec(`firewall-cmd --permanent --remove-rich-rule='rule protocol value=icmp drop'`)
} else {
tools.Exec(`firewall-cmd --permanent --add-rich-rule='rule protocol value=icmp drop'`)
out, err = tools.Exec(`firewall-cmd --permanent --add-rich-rule='rule protocol value=icmp drop'`)
}
tools.Exec(`firewall-cmd --reload`)
} else {
if ctx.Request().InputBool("status") {
tools.Exec(`sed -i 's/-A ufw-before-input -p icmp --icmp-type echo-request -j DROP/-A ufw-before-input -p icmp --icmp-type echo-request -j ACCEPT/g' /etc/ufw/before.rules`)
out, err = tools.Exec(`sed -i 's/-A ufw-before-input -p icmp --icmp-type echo-request -j DROP/-A ufw-before-input -p icmp --icmp-type echo-request -j ACCEPT/g' /etc/ufw/before.rules`)
} else {
tools.Exec(`sed -i 's/-A ufw-before-input -p icmp --icmp-type echo-request -j ACCEPT/-A ufw-before-input -p icmp --icmp-type echo-request -j DROP/g' /etc/ufw/before.rules`)
out, err = tools.Exec(`sed -i 's/-A ufw-before-input -p icmp --icmp-type echo-request -j ACCEPT/-A ufw-before-input -p icmp --icmp-type echo-request -j DROP/g' /etc/ufw/before.rules`)
}
tools.Exec(`ufw reload`)
}
if err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
if tools.IsRHEL() {
out, err = tools.Exec(`firewall-cmd --reload`)
} else {
out, err = tools.Exec(`ufw reload`)
}
if err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
return Success(ctx, nil)

View File

@@ -35,7 +35,9 @@ func (r *SettingController) List(ctx http.Context) http.Response {
var settings []models.Setting
err := facades.Orm().Query().Get(&settings)
if err != nil {
facades.Log().Info("[面板][SettingController] 查询设置列表失败 ", err)
facades.Log().Request(ctx.Request()).Tags("面板", "面板设置").With(map[string]any{
"error": err.Error(),
}).Info("获取面板设置列表失败")
return ErrorSystem(ctx)
}
@@ -48,13 +50,21 @@ func (r *SettingController) List(ctx http.Context) http.Response {
var user models.User
err = facades.Auth().User(ctx, &user)
if err != nil {
facades.Log().Info("[面板][SettingController] 获取用户失败 ", err)
facades.Log().Request(ctx.Request()).Tags("面板", "面板设置").With(map[string]any{
"error": err.Error(),
}).Info("获取用户信息失败")
return ErrorSystem(ctx)
}
result.Username = user.Username
result.Email = user.Email
result.Port = tools.Exec(`cat /www/panel/panel.conf | grep APP_PORT | awk -F '=' '{print $2}' | tr -d '\n'`)
result.Port, err = tools.Exec(`cat /www/panel/panel.conf | grep APP_PORT | awk -F '=' '{print $2}' | tr -d '\n'`)
if err != nil {
facades.Log().Request(ctx.Request()).Tags("面板", "面板设置").With(map[string]any{
"error": err.Error(),
}).Info("获取面板端口失败")
return ErrorSystem(ctx)
}
return Success(ctx, result)
}
@@ -79,9 +89,9 @@ func (r *SettingController) Update(ctx http.Context) http.Response {
err := r.setting.Set(models.SettingKeyName, updateRequest.Name)
if err != nil {
facades.Log().Request(ctx.Request()).With(map[string]any{
facades.Log().Request(ctx.Request()).Tags("面板", "面板设置").With(map[string]any{
"error": err.Error(),
}).Tags("面板", "面板设置").Info("保存面板名称失败")
}).Info("保存面板名称失败")
return ErrorSystem(ctx)
}
@@ -92,9 +102,9 @@ func (r *SettingController) Update(ctx http.Context) http.Response {
}
err = r.setting.Set(models.SettingKeyBackupPath, updateRequest.BackupPath)
if err != nil {
facades.Log().Request(ctx.Request()).With(map[string]any{
facades.Log().Request(ctx.Request()).Tags("面板", "面板设置").With(map[string]any{
"error": err.Error(),
}).Tags("面板", "面板设置").Info("保存备份目录失败")
}).Info("保存备份目录失败")
return ErrorSystem(ctx)
}
if !tools.Exists(updateRequest.WebsitePath) {
@@ -107,9 +117,9 @@ func (r *SettingController) Update(ctx http.Context) http.Response {
}
err = r.setting.Set(models.SettingKeyWebsitePath, updateRequest.WebsitePath)
if err != nil {
facades.Log().Request(ctx.Request()).With(map[string]any{
facades.Log().Request(ctx.Request()).Tags("面板", "面板设置").With(map[string]any{
"error": err.Error(),
}).Tags("面板", "面板设置").Info("保存建站目录失败")
}).Info("保存建站目录失败")
return ErrorSystem(ctx)
}
@@ -128,30 +138,61 @@ func (r *SettingController) Update(ctx http.Context) http.Response {
user.Password = hash
}
if err = facades.Orm().Query().Save(&user); err != nil {
facades.Log().Request(ctx.Request()).With(map[string]any{
facades.Log().Request(ctx.Request()).Tags("面板", "面板设置").With(map[string]any{
"error": err.Error(),
}).Tags("面板", "面板设置").Info("保存用户信息失败")
}).Info("保存用户信息失败")
return ErrorSystem(ctx)
}
oldPort, err := tools.Exec(`cat /www/panel/panel.conf | grep APP_PORT | awk -F '=' '{print $2}' | tr -d '\n'`)
if err != nil {
facades.Log().Request(ctx.Request()).Tags("面板", "面板设置").With(map[string]any{
"error": err.Error(),
}).Info("获取面板端口失败")
return ErrorSystem(ctx)
}
oldPort := tools.Exec(`cat /www/panel/panel.conf | grep APP_PORT | awk -F '=' '{print $2}' | tr -d '\n'`)
port := cast.ToString(updateRequest.Port)
if oldPort != port {
tools.Exec("sed -i 's/APP_PORT=" + oldPort + "/APP_PORT=" + port + "/g' /www/panel/panel.conf")
if out, err := tools.Exec("sed -i 's/APP_PORT=" + oldPort + "/APP_PORT=" + port + "/g' /www/panel/panel.conf"); err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
if tools.IsRHEL() {
tools.Exec("firewall-cmd --remove-port=" + cast.ToString(port) + "/tcp --permanent 2>&1")
tools.Exec("firewall-cmd --add-port=" + cast.ToString(port) + "/tcp --permanent 2>&1")
tools.Exec("firewall-cmd --reload")
if out, err := tools.Exec("firewall-cmd --remove-port=" + cast.ToString(port) + "/tcp --permanent 2>&1"); err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("firewall-cmd --add-port=" + cast.ToString(port) + "/tcp --permanent 2>&1"); err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("firewall-cmd --reload"); err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
} else {
tools.Exec("ufw delete allow " + cast.ToString(port) + "/tcp")
tools.Exec("ufw allow " + cast.ToString(port) + "/tcp")
tools.Exec("ufw reload")
if out, err := tools.Exec("ufw delete allow " + cast.ToString(port) + "/tcp"); err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("ufw allow " + cast.ToString(port) + "/tcp"); err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
if out, err := tools.Exec("ufw reload"); err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
}
}
oldEntrance := tools.Exec(`cat /www/panel/panel.conf | grep APP_ENTRANCE | awk -F '=' '{print $2}' | tr -d '\n'`)
oldEntrance, err := tools.Exec(`cat /www/panel/panel.conf | grep APP_ENTRANCE | awk -F '=' '{print $2}' | tr -d '\n'`)
if err != nil {
facades.Log().Request(ctx.Request()).Tags("面板", "面板设置").With(map[string]any{
"error": err.Error(),
}).Info("获取面板入口失败")
return ErrorSystem(ctx)
}
entrance := cast.ToString(updateRequest.Entrance)
if oldEntrance != entrance {
tools.Exec("sed -i 's!APP_ENTRANCE=" + oldEntrance + "!APP_ENTRANCE=" + entrance + "!g' /www/panel/panel.conf")
if out, err := tools.Exec("sed -i 's!APP_ENTRANCE=" + oldEntrance + "!APP_ENTRANCE=" + entrance + "!g' /www/panel/panel.conf"); err != nil {
return Error(ctx, http.StatusInternalServerError, out)
}
}
if oldPort != port || oldEntrance != entrance {

View File

@@ -67,25 +67,17 @@ func (r *SshController) UpdateInfo(ctx http.Context) http.Response {
port := ctx.Request().Input("port")
user := ctx.Request().Input("user")
password := ctx.Request().Input("password")
err = r.setting.Set(models.SettingKeySshHost, host)
if err != nil {
facades.Log().Info("[面板][SSH] 更新配置失败 ", err)
return ErrorSystem(ctx)
if err = r.setting.Set(models.SettingKeySshHost, host); err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
err = r.setting.Set(models.SettingKeySshPort, port)
if err != nil {
facades.Log().Info("[面板][SSH] 更新配置失败 ", err)
return ErrorSystem(ctx)
if err = r.setting.Set(models.SettingKeySshPort, port); err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
err = r.setting.Set(models.SettingKeySshUser, user)
if err != nil {
facades.Log().Info("[面板][SSH] 更新配置失败 ", err)
return ErrorSystem(ctx)
if err = r.setting.Set(models.SettingKeySshUser, user); err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
err = r.setting.Set(models.SettingKeySshPassword, password)
if err != nil {
facades.Log().Info("[面板][SSH] 更新配置失败 ", err)
return ErrorSystem(ctx)
if err = r.setting.Set(models.SettingKeySshPassword, password); err != nil {
return Error(ctx, http.StatusInternalServerError, err.Error())
}
return Success(ctx, nil)
@@ -142,21 +134,24 @@ func (r *SshController) Session(ctx http.Context) http.Response {
defer wg.Done()
err := turn.LoopRead(logBuff, ctx2)
if err != nil {
facades.Log().Info("[面板][SSH] 读取数据失败 ", err.Error())
facades.Log().Request(ctx.Request()).Tags("面板", "SSH").With(map[string]any{
"error": err.Error(),
}).Info("SSH 会话错误")
}
}()
go func() {
defer wg.Done()
err := turn.SessionWait()
if err != nil {
facades.Log().Info("[面板][SSH] 会话失败 ", err.Error())
facades.Log().Request(ctx.Request()).Tags("面板", "SSH").With(map[string]any{
"error": err.Error(),
}).Info("SSH 会话错误")
}
cancel()
}()
wg.Wait()
})
if err != nil {
facades.Log().Info("[面板][SSH] 建立连接失败 ", err)
return ErrorSystem(ctx)
}

View File

@@ -38,9 +38,9 @@ func (r *TaskController) List(ctx http.Context) http.Response {
var total int64
err := facades.Orm().Query().Order("id desc").Paginate(ctx.Request().QueryInt("page", 1), ctx.Request().QueryInt("limit", 10), &tasks, &total)
if err != nil {
facades.Log().Request(ctx.Request()).With(map[string]any{
facades.Log().Request(ctx.Request()).Tags("面板", "任务中心").With(map[string]any{
"error": err.Error(),
}).Info("[面板][TaskController] 查询任务列表失败")
}).Info("查询任务列表失败")
return ErrorSystem(ctx)
}
@@ -55,14 +55,17 @@ func (r *TaskController) Log(ctx http.Context) http.Response {
var task models.Task
err := facades.Orm().Query().Where("id", ctx.Request().QueryInt("id")).FirstOrFail(&task)
if err != nil {
facades.Log().Request(ctx.Request()).With(map[string]any{
facades.Log().Request(ctx.Request()).Tags("面板", "任务中心").With(map[string]any{
"id": ctx.Request().QueryInt("id"),
"error": err.Error(),
}).Info("[面板][TaskController] 查询任务失败")
}).Info("查询任务失败")
return ErrorSystem(ctx)
}
log := tools.Exec("tail -n 1000 " + task.Log)
log, err := tools.Exec("tail -n 1000 " + task.Log)
if err != nil {
return Error(ctx, http.StatusInternalServerError, log)
}
return Success(ctx, log)
}
@@ -72,10 +75,10 @@ func (r *TaskController) Delete(ctx http.Context) http.Response {
var task models.Task
_, err := facades.Orm().Query().Where("id", ctx.Request().Input("id")).Delete(&task)
if err != nil {
facades.Log().With(map[string]any{
facades.Log().Request(ctx.Request()).Tags("面板", "任务中心").With(map[string]any{
"id": ctx.Request().QueryInt("id"),
"error": err.Error(),
}).Info("[面板][TaskController] 删除任务失败")
}).Info("删除任务失败")
return ErrorSystem(ctx)
}

View File

@@ -41,9 +41,9 @@ func (r *UserController) Login(ctx http.Context) http.Response {
var user models.User
err := facades.Orm().Query().Where("username", loginRequest.Username).First(&user)
if err != nil {
facades.Log().Request(ctx.Request()).With(map[string]any{
facades.Log().Request(ctx.Request()).Tags("面板", "用户").With(map[string]any{
"error": err.Error(),
}).Tags("面板", "用户").Info("查询用户失败")
}).Info("查询用户失败")
return ErrorSystem(ctx)
}
@@ -54,18 +54,18 @@ func (r *UserController) Login(ctx http.Context) http.Response {
if facades.Hash().NeedsRehash(user.Password) {
user.Password, err = facades.Hash().Make(loginRequest.Password)
if err != nil {
facades.Log().Request(ctx.Request()).With(map[string]any{
facades.Log().Request(ctx.Request()).Tags("面板", "用户").With(map[string]any{
"error": err.Error(),
}).Tags("面板", "用户").Info("更新密码失败")
}).Info("更新密码失败")
return ErrorSystem(ctx)
}
}
token, loginErr := facades.Auth().LoginUsingID(ctx, user.ID)
if loginErr != nil {
facades.Log().Request(ctx.Request()).With(map[string]any{
facades.Log().Request(ctx.Request()).Tags("面板", "用户").With(map[string]any{
"error": err.Error(),
}).Tags("面板", "用户").Info("登录失败")
}).Info("登录失败")
return ErrorSystem(ctx)
}
@@ -87,9 +87,9 @@ func (r *UserController) Info(ctx http.Context) http.Response {
var user models.User
err := facades.Auth().User(ctx, &user)
if err != nil {
facades.Log().Request(ctx.Request()).With(map[string]any{
facades.Log().Request(ctx.Request()).Tags("面板", "用户").With(map[string]any{
"error": err.Error(),
}).Tags("面板", "用户").Info("获取用户信息失败")
}).Info("获取用户信息失败")
return ErrorSystem(ctx)
}

View File

@@ -40,14 +40,14 @@ func NewWebsiteController() *WebsiteController {
// @Param data body commonrequests.Paginate true "request"
// @Success 200 {object} SuccessResponse{data=responses.List}
// @Router /panel/website [get]
func (c *WebsiteController) List(ctx http.Context) http.Response {
func (r *WebsiteController) List(ctx http.Context) http.Response {
var paginateRequest commonrequests.Paginate
sanitize := Sanitize(ctx, &paginateRequest)
if sanitize != nil {
return sanitize
}
total, websites, err := c.website.List(paginateRequest.Page, paginateRequest.Limit)
total, websites, err := r.website.List(paginateRequest.Page, paginateRequest.Limit)
if err != nil {
facades.Log().Request(ctx.Request()).Tags("面板", "网站管理").With(map[string]any{
"error": err.Error(),
@@ -72,7 +72,7 @@ func (c *WebsiteController) List(ctx http.Context) http.Response {
// @Param data body requests.Add true "request"
// @Success 200 {object} SuccessResponse
// @Router /panel/website [post]
func (c *WebsiteController) Add(ctx http.Context) http.Response {
func (r *WebsiteController) Add(ctx http.Context) http.Response {
check := Check(ctx, "openresty")
if check != nil {
return check
@@ -83,11 +83,18 @@ func (c *WebsiteController) Add(ctx http.Context) http.Response {
return sanitize
}
if len(addRequest.Path) == 0 {
addRequest.Path = r.setting.Get(models.SettingKeyWebsitePath) + "/" + addRequest.Name
}
website := services.PanelWebsite{
Name: addRequest.Name,
Status: true,
Domains: addRequest.Domains,
Ports: addRequest.Ports,
Path: addRequest.Path,
Php: addRequest.Php,
Ssl: false,
Db: addRequest.Db,
DbType: addRequest.DbType,
DbName: addRequest.DbName,
@@ -95,7 +102,7 @@ func (c *WebsiteController) Add(ctx http.Context) http.Response {
DbPassword: addRequest.DbPassword,
}
_, err := c.website.Add(website)
_, err := r.website.Add(website)
if err != nil {
facades.Log().Request(ctx.Request()).Tags("面板", "网站管理").With(map[string]any{
"error": err.Error(),
@@ -117,7 +124,7 @@ func (c *WebsiteController) Add(ctx http.Context) http.Response {
// @Param id path int true "网站 ID"
// @Success 200 {object} SuccessResponse
// @Router /panel/website/{id} [delete]
func (c *WebsiteController) Delete(ctx http.Context) http.Response {
func (r *WebsiteController) Delete(ctx http.Context) http.Response {
check := Check(ctx, "openresty")
if check != nil {
return check
@@ -129,7 +136,7 @@ func (c *WebsiteController) Delete(ctx http.Context) http.Response {
return sanitize
}
err := c.website.Delete(idRequest.ID)
err := r.website.Delete(idRequest.ID)
if err != nil {
facades.Log().Request(ctx.Request()).Tags("面板", "网站管理").With(map[string]any{
"id": idRequest.ID,
@@ -150,7 +157,7 @@ func (c *WebsiteController) Delete(ctx http.Context) http.Response {
// @Security BearerToken
// @Success 200 {object} SuccessResponse{data=map[string]string}
// @Router /panel/website/defaultConfig [get]
func (c *WebsiteController) GetDefaultConfig(ctx http.Context) http.Response {
func (r *WebsiteController) GetDefaultConfig(ctx http.Context) http.Response {
check := Check(ctx, "openresty")
if check != nil {
return check
@@ -175,7 +182,7 @@ func (c *WebsiteController) GetDefaultConfig(ctx http.Context) http.Response {
// @Param data body map[string]string true "request"
// @Success 200 {object} SuccessResponse
// @Router /panel/website/defaultConfig [post]
func (c *WebsiteController) SaveDefaultConfig(ctx http.Context) http.Response {
func (r *WebsiteController) SaveDefaultConfig(ctx http.Context) http.Response {
check := Check(ctx, "openresty")
if check != nil {
return check
@@ -211,7 +218,7 @@ func (c *WebsiteController) SaveDefaultConfig(ctx http.Context) http.Response {
// @Param id path int true "网站 ID"
// @Success 200 {object} SuccessResponse{data=services.PanelWebsite}
// @Router /panel/website/config/{id} [get]
func (c *WebsiteController) GetConfig(ctx http.Context) http.Response {
func (r *WebsiteController) GetConfig(ctx http.Context) http.Response {
check := Check(ctx, "openresty")
if check != nil {
return check
@@ -223,7 +230,7 @@ func (c *WebsiteController) GetConfig(ctx http.Context) http.Response {
return sanitize
}
config, err := c.website.GetConfig(idRequest.ID)
config, err := r.website.GetConfig(idRequest.ID)
if err != nil {
facades.Log().Request(ctx.Request()).Tags("面板", "网站管理").With(map[string]any{
"id": idRequest.ID,
@@ -247,7 +254,7 @@ func (c *WebsiteController) GetConfig(ctx http.Context) http.Response {
// @Param data body requests.SaveConfig true "request"
// @Success 200 {object} SuccessResponse
// @Router /panel/website/config/{id} [post]
func (c *WebsiteController) SaveConfig(ctx http.Context) http.Response {
func (r *WebsiteController) SaveConfig(ctx http.Context) http.Response {
check := Check(ctx, "openresty")
if check != nil {
return check
@@ -259,7 +266,7 @@ func (c *WebsiteController) SaveConfig(ctx http.Context) http.Response {
return sanitize
}
err := c.website.SaveConfig(saveConfigRequest)
err := r.website.SaveConfig(saveConfigRequest)
if err != nil {
facades.Log().Request(ctx.Request()).Tags("面板", "网站管理").With(map[string]any{
"error": err.Error(),
@@ -281,7 +288,7 @@ func (c *WebsiteController) SaveConfig(ctx http.Context) http.Response {
// @Param id path int true "网站 ID"
// @Success 200 {object} SuccessResponse
// @Router /panel/website/log/{id} [delete]
func (c *WebsiteController) ClearLog(ctx http.Context) http.Response {
func (r *WebsiteController) ClearLog(ctx http.Context) http.Response {
check := Check(ctx, "openresty")
if check != nil {
return check
@@ -314,7 +321,7 @@ func (c *WebsiteController) ClearLog(ctx http.Context) http.Response {
// @Param id path int true "网站 ID"
// @Success 200 {object} SuccessResponse
// @Router /panel/website/updateRemark/{id} [post]
func (c *WebsiteController) UpdateRemark(ctx http.Context) http.Response {
func (r *WebsiteController) UpdateRemark(ctx http.Context) http.Response {
var idRequest requests.ID
sanitize := Sanitize(ctx, &idRequest)
if sanitize != nil {
@@ -348,8 +355,8 @@ func (c *WebsiteController) UpdateRemark(ctx http.Context) http.Response {
// @Security BearerToken
// @Success 200 {object} SuccessResponse{data=[]services.BackupFile}
// @Router /panel/website/backupList [get]
func (c *WebsiteController) BackupList(ctx http.Context) http.Response {
backupList, err := c.backup.WebsiteList()
func (r *WebsiteController) BackupList(ctx http.Context) http.Response {
backupList, err := r.backup.WebsiteList()
if err != nil {
facades.Log().Request(ctx.Request()).Tags("面板", "网站管理").With(map[string]any{
"error": err.Error(),
@@ -371,7 +378,7 @@ func (c *WebsiteController) BackupList(ctx http.Context) http.Response {
// @Param data body requests.ID true "request"
// @Success 200 {object} SuccessResponse
// @Router /panel/website/createBackup [post]
func (c *WebsiteController) CreateBackup(ctx http.Context) http.Response {
func (r *WebsiteController) CreateBackup(ctx http.Context) http.Response {
var idRequest requests.ID
sanitize := Sanitize(ctx, &idRequest)
if sanitize != nil {
@@ -387,7 +394,7 @@ func (c *WebsiteController) CreateBackup(ctx http.Context) http.Response {
return ErrorSystem(ctx)
}
if err := c.backup.WebSiteBackup(website); err != nil {
if err := r.backup.WebSiteBackup(website); err != nil {
facades.Log().Request(ctx.Request()).Tags("面板", "网站管理").With(map[string]any{
"id": idRequest.ID,
"error": err.Error(),
@@ -409,13 +416,13 @@ func (c *WebsiteController) CreateBackup(ctx http.Context) http.Response {
// @Param file formData file true "备份文件"
// @Success 200 {object} SuccessResponse
// @Router /panel/website/uploadBackup [post]
func (c *WebsiteController) UploadBackup(ctx http.Context) http.Response {
func (r *WebsiteController) UploadBackup(ctx http.Context) http.Response {
file, err := ctx.Request().File("file")
if err != nil {
return Error(ctx, http.StatusUnprocessableEntity, "上传文件失败")
return Error(ctx, http.StatusInternalServerError, "上传文件失败")
}
backupPath := c.setting.Get(models.SettingKeyBackupPath) + "/website"
backupPath := r.setting.Get(models.SettingKeyBackupPath) + "/website"
if !tools.Exists(backupPath) {
if err = tools.Mkdir(backupPath, 0644); err != nil {
return nil
@@ -445,7 +452,7 @@ func (c *WebsiteController) UploadBackup(ctx http.Context) http.Response {
// @Param data body requests.RestoreBackup true "request"
// @Success 200 {object} SuccessResponse
// @Router /panel/website/restoreBackup [post]
func (c *WebsiteController) RestoreBackup(ctx http.Context) http.Response {
func (r *WebsiteController) RestoreBackup(ctx http.Context) http.Response {
var restoreBackupRequest requests.RestoreBackup
sanitize := Sanitize(ctx, &restoreBackupRequest)
if sanitize != nil {
@@ -457,7 +464,7 @@ func (c *WebsiteController) RestoreBackup(ctx http.Context) http.Response {
return ErrorSystem(ctx)
}
if err := c.backup.WebsiteRestore(website, restoreBackupRequest.Name); err != nil {
if err := r.backup.WebsiteRestore(website, restoreBackupRequest.Name); err != nil {
facades.Log().Request(ctx.Request()).Tags("面板", "网站管理").With(map[string]any{
"id": restoreBackupRequest.ID,
"file": restoreBackupRequest.Name,
@@ -480,14 +487,14 @@ func (c *WebsiteController) RestoreBackup(ctx http.Context) http.Response {
// @Param data body requests.DeleteBackup true "request"
// @Success 200 {object} SuccessResponse
// @Router /panel/website/deleteBackup [delete]
func (c *WebsiteController) DeleteBackup(ctx http.Context) http.Response {
func (r *WebsiteController) DeleteBackup(ctx http.Context) http.Response {
var deleteBackupRequest requests.DeleteBackup
sanitize := Sanitize(ctx, &deleteBackupRequest)
if sanitize != nil {
return sanitize
}
backupPath := c.setting.Get(models.SettingKeyBackupPath) + "/website"
backupPath := r.setting.Get(models.SettingKeyBackupPath) + "/website"
if !tools.Exists(backupPath) {
if err := tools.Mkdir(backupPath, 0644); err != nil {
return nil
@@ -512,7 +519,7 @@ func (c *WebsiteController) DeleteBackup(ctx http.Context) http.Response {
// @Param data body requests.ID true "request"
// @Success 200 {object} SuccessResponse
// @Router /panel/website/resetConfig [post]
func (c *WebsiteController) ResetConfig(ctx http.Context) http.Response {
func (r *WebsiteController) ResetConfig(ctx http.Context) http.Response {
check := Check(ctx, "openresty")
if check != nil {
return check
@@ -603,7 +610,9 @@ server
if err := tools.Write("/www/server/vhost/rewrite"+website.Name+".conf", "", 0644); err != nil {
return nil
}
tools.Exec("systemctl reload openresty")
if exec, err := tools.Exec("systemctl reload openresty"); err != nil {
return Error(ctx, http.StatusInternalServerError, exec)
}
return Success(ctx, nil)
}
@@ -619,7 +628,7 @@ server
// @Param id path int true "网站 ID"
// @Success 200 {object} SuccessResponse
// @Router /panel/website/status/{id} [post]
func (c *WebsiteController) Status(ctx http.Context) http.Response {
func (r *WebsiteController) Status(ctx http.Context) http.Response {
check := Check(ctx, "openresty")
if check != nil {
return check
@@ -672,7 +681,9 @@ func (c *WebsiteController) Status(ctx http.Context) http.Response {
if err := tools.Write("/www/server/vhost/"+website.Name+".conf", raw, 0644); err != nil {
return ErrorSystem(ctx)
}
tools.Exec("systemctl reload openresty")
if exec, err := tools.Exec("systemctl reload openresty"); err != nil {
return Error(ctx, http.StatusInternalServerError, exec)
}
return Success(ctx, nil)
}

View File

@@ -9,6 +9,7 @@ type Add struct {
Name string `form:"name" json:"name"`
Domains []string `form:"domains" json:"domains"`
Ports []string `form:"ports" json:"ports"`
Path string `form:"path" json:"path"`
Php int `form:"php" json:"php"`
Db bool `form:"db" json:"db"`
DbType string `form:"db_type" json:"db_type"`
@@ -23,9 +24,10 @@ func (r *Add) Authorize(ctx http.Context) error {
func (r *Add) Rules(ctx http.Context) map[string]string {
return map[string]string{
"name": "required|regex:^[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)*$|not_exists:websites,name",
"name": "required|regex:^[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)*$|not_exists:websites,name|not_in:phpmyadmin,mysql,panel,ssh",
"domains": "required|slice",
"ports": "required|slice",
"path": "regex:^/[a-zA-Z0-9_-]+(\\/[a-zA-Z0-9_-]+)*$",
"php": "required",
"db": "bool",
"db_type": "required_if:db,true|in:mysql,postgresql",

View File

@@ -88,7 +88,9 @@ func (s *BackupImpl) WebSiteBackup(website models.Website) error {
}
backupFile := backupPath + "/" + website.Name + "_" + carbon.Now().ToShortDateTimeString() + ".zip"
tools.Exec(`cd '` + website.Path + `' && zip -r '` + backupFile + `' .`)
if _, err := tools.Exec(`cd '` + website.Path + `' && zip -r '` + backupFile + `' .`); err != nil {
return err
}
return nil
}
@@ -112,8 +114,12 @@ func (s *BackupImpl) WebsiteRestore(website models.Website, backupFile string) e
return errors.New("备份文件不存在")
}
tools.Exec(`rm -rf '` + website.Path + `/*'`)
tools.Exec(`unzip -o '` + backupFile + `' -d '` + website.Path + `' 2>&1`)
if _, err := tools.Exec(`rm -rf '` + website.Path + `/*'`); err != nil {
return err
}
if _, err := tools.Exec(`unzip -o '` + backupFile + `' -d '` + website.Path + `' 2>&1`); err != nil {
return err
}
if err := tools.Chmod(website.Path, 0755); err != nil {
return err
}
@@ -172,12 +178,15 @@ func (s *BackupImpl) MysqlBackup(database string) error {
return err
}
tools.Exec("/www/server/mysql/bin/mysqldump -uroot " + database + " > " + backupPath + "/" + backupFile)
tools.Exec("cd " + backupPath + " && zip -r " + backupPath + "/" + backupFile + ".zip " + backupFile)
if _, err := tools.Exec("/www/server/mysql/bin/mysqldump -uroot " + database + " > " + backupPath + "/" + backupFile); err != nil {
return err
}
if _, err := tools.Exec("cd " + backupPath + " && zip -r " + backupPath + "/" + backupFile + ".zip " + backupFile); err != nil {
return err
}
tools.Remove(backupPath + "/" + backupFile)
_ = os.Unsetenv("MYSQL_PWD")
return nil
return os.Unsetenv("MYSQL_PWD")
}
// MysqlRestore MySQL恢复
@@ -197,26 +206,38 @@ func (s *BackupImpl) MysqlRestore(database string, backupFile string) error {
switch ext {
case ".zip":
tools.Exec("unzip -o " + backupFile + " -d " + backupPath)
if _, err := tools.Exec("unzip -o " + backupFile + " -d " + backupPath); err != nil {
return err
}
backupFile = strings.TrimSuffix(backupFile, ext)
case ".gz":
if strings.HasSuffix(backupFile, ".tar.gz") {
// 解压.tar.gz文件
tools.Exec("tar -zxvf " + backupFile + " -C " + backupPath)
if _, err := tools.Exec("tar -zxvf " + backupFile + " -C " + backupPath); err != nil {
return err
}
backupFile = strings.TrimSuffix(backupFile, ".tar.gz")
} else {
// 解压.gz文件
tools.Exec("gzip -d " + backupFile)
if _, err := tools.Exec("gzip -d " + backupFile); err != nil {
return err
}
backupFile = strings.TrimSuffix(backupFile, ext)
}
case ".bz2":
tools.Exec("bzip2 -d " + backupFile)
if _, err := tools.Exec("bzip2 -d " + backupFile); err != nil {
return err
}
backupFile = strings.TrimSuffix(backupFile, ext)
case ".tar":
tools.Exec("tar -xvf " + backupFile + " -C " + backupPath)
if _, err := tools.Exec("tar -xvf " + backupFile + " -C " + backupPath); err != nil {
return err
}
backupFile = strings.TrimSuffix(backupFile, ext)
case ".rar":
tools.Exec("unrar x " + backupFile + " " + backupPath)
if _, err := tools.Exec("unrar x " + backupFile + " " + backupPath); err != nil {
return err
}
backupFile = strings.TrimSuffix(backupFile, ext)
}
@@ -224,10 +245,11 @@ func (s *BackupImpl) MysqlRestore(database string, backupFile string) error {
return errors.New("自动解压失败,请手动解压")
}
tools.Exec("/www/server/mysql/bin/mysql -uroot " + database + " < " + backupFile)
_ = os.Unsetenv("MYSQL_PWD")
if _, err := tools.Exec("/www/server/mysql/bin/mysql -uroot " + database + " < " + backupFile); err != nil {
return err
}
return nil
return os.Unsetenv("MYSQL_PWD")
}
// PostgresqlList PostgreSQL备份列表
@@ -273,10 +295,14 @@ func (s *BackupImpl) PostgresqlBackup(database string) error {
}
}
tools.Exec(`su - postgres -c "pg_dump ` + database + `" > ` + backupPath + "/" + backupFile)
tools.Exec("cd " + backupPath + " && zip -r " + backupPath + "/" + backupFile + ".zip " + backupFile)
tools.Remove(backupPath + "/" + backupFile)
if _, err := tools.Exec(`su - postgres -c "pg_dump ` + database + `" > ` + backupPath + "/" + backupFile); err != nil {
return err
}
if _, err := tools.Exec("cd " + backupPath + " && zip -r " + backupPath + "/" + backupFile + ".zip " + backupFile); err != nil {
return err
}
tools.Remove(backupPath + "/" + backupFile)
return nil
}
@@ -291,26 +317,38 @@ func (s *BackupImpl) PostgresqlRestore(database string, backupFile string) error
switch ext {
case ".zip":
tools.Exec("unzip -o " + backupFile + " -d " + backupPath)
if _, err := tools.Exec("unzip -o " + backupFile + " -d " + backupPath); err != nil {
return err
}
backupFile = strings.TrimSuffix(backupFile, ext)
case ".gz":
if strings.HasSuffix(backupFile, ".tar.gz") {
// 解压.tar.gz文件
tools.Exec("tar -zxvf " + backupFile + " -C " + backupPath)
if _, err := tools.Exec("tar -zxvf " + backupFile + " -C " + backupPath); err != nil {
return err
}
backupFile = strings.TrimSuffix(backupFile, ".tar.gz")
} else {
// 解压.gz文件
tools.Exec("gzip -d " + backupFile)
if _, err := tools.Exec("gzip -d " + backupFile); err != nil {
return err
}
backupFile = strings.TrimSuffix(backupFile, ext)
}
case ".bz2":
tools.Exec("bzip2 -d " + backupFile)
if _, err := tools.Exec("bzip2 -d " + backupFile); err != nil {
return err
}
backupFile = strings.TrimSuffix(backupFile, ext)
case ".tar":
tools.Exec("tar -xvf " + backupFile + " -C " + backupPath)
if _, err := tools.Exec("tar -xvf " + backupFile + " -C " + backupPath); err != nil {
return err
}
backupFile = strings.TrimSuffix(backupFile, ext)
case ".rar":
tools.Exec("unrar x " + backupFile + " " + backupPath)
if _, err := tools.Exec("unrar x " + backupFile + " " + backupPath); err != nil {
return err
}
backupFile = strings.TrimSuffix(backupFile, ext)
}
@@ -318,7 +356,9 @@ func (s *BackupImpl) PostgresqlRestore(database string, backupFile string) error
return errors.New("自动解压失败,请手动解压")
}
tools.Exec(`su - postgres -c "psql ` + database + `" < ` + backupFile)
if _, err := tools.Exec(`su - postgres -c "psql ` + database + `" < ` + backupFile); err != nil {
return err
}
return nil
}

View File

@@ -316,7 +316,9 @@ func (s *CertImpl) ObtainAuto(ID uint) (certificate.Resource, error) {
if err := tools.Write("/www/server/vhost/ssl/"+cert.Website.Name+".key", string(ssl.PrivateKey), 0644); err != nil {
return certificate.Resource{}, err
}
tools.Exec("systemctl reload openresty")
if _, err := tools.Exec("systemctl reload openresty"); err != nil {
return certificate.Resource{}, err
}
}
return ssl, nil
@@ -374,7 +376,9 @@ func (s *CertImpl) ObtainManual(ID uint) (certificate.Resource, error) {
if err := tools.Write("/www/server/vhost/ssl/"+cert.Website.Name+".key", string(ssl.PrivateKey), 0644); err != nil {
return certificate.Resource{}, err
}
tools.Exec("systemctl reload openresty")
if _, err := tools.Exec("systemctl reload openresty"); err != nil {
return certificate.Resource{}, err
}
}
return ssl, nil
@@ -479,7 +483,9 @@ func (s *CertImpl) Renew(ID uint) (certificate.Resource, error) {
if err := tools.Write("/www/server/vhost/ssl/"+cert.Website.Name+".key", string(ssl.PrivateKey), 0644); err != nil {
return certificate.Resource{}, err
}
tools.Exec("systemctl reload openresty")
if _, err := tools.Exec("systemctl reload openresty"); err != nil {
return certificate.Resource{}, err
}
}
return ssl, nil

View File

@@ -8,8 +8,8 @@ import (
)
type Cron interface {
AddToSystem(cron models.Cron)
DeleteFromSystem(cron models.Cron)
AddToSystem(cron models.Cron) error
DeleteFromSystem(cron models.Cron) error
}
type CronImpl struct {
@@ -20,25 +20,45 @@ func NewCronImpl() *CronImpl {
}
// AddToSystem 添加到系统
func (r *CronImpl) AddToSystem(cron models.Cron) {
func (r *CronImpl) AddToSystem(cron models.Cron) error {
if tools.IsRHEL() {
tools.Exec("echo \"" + cron.Time + " " + cron.Shell + " >> " + cron.Log + " 2>&1\" >> /var/spool/cron/root")
tools.Exec("systemctl restart crond")
if _, err := tools.Exec("echo \"" + cron.Time + " " + cron.Shell + " >> " + cron.Log + " 2>&1\" >> /var/spool/cron/root"); err != nil {
return err
}
if _, err := tools.Exec("systemctl restart crond"); err != nil {
return err
}
} else {
tools.Exec("echo \"" + cron.Time + " " + cron.Shell + " >> " + cron.Log + " 2>&1\" >> /var/spool/cron/crontabs/root")
tools.Exec("systemctl restart cron")
if _, err := tools.Exec("echo \"" + cron.Time + " " + cron.Shell + " >> " + cron.Log + " 2>&1\" >> /var/spool/cron/crontabs/root"); err != nil {
return err
}
if _, err := tools.Exec("systemctl restart cron"); err != nil {
return err
}
}
return nil
}
// DeleteFromSystem 从系统中删除
func (r *CronImpl) DeleteFromSystem(cron models.Cron) {
func (r *CronImpl) DeleteFromSystem(cron models.Cron) error {
// 需要转义Shell路径的/为\/
cron.Shell = strings.ReplaceAll(cron.Shell, "/", "\\/")
if tools.IsRHEL() {
tools.Exec("sed -i '/" + cron.Shell + "/d' /var/spool/cron/root")
tools.Exec("systemctl restart crond")
if _, err := tools.Exec("sed -i '/" + cron.Shell + "/d' /var/spool/cron/root"); err != nil {
return err
}
if _, err := tools.Exec("systemctl restart crond"); err != nil {
return err
}
} else {
tools.Exec("sed -i '/" + cron.Shell + "/d' /var/spool/cron/crontabs/root")
tools.Exec("systemctl restart cron")
if _, err := tools.Exec("sed -i '/" + cron.Shell + "/d' /var/spool/cron/crontabs/root"); err != nil {
return err
}
if _, err := tools.Exec("systemctl restart cron"); err != nil {
return err
}
}
return nil
}

View File

@@ -11,7 +11,6 @@ import (
"strings"
"github.com/goravel/framework/facades"
"golang.org/x/exp/slices"
requests "panel/app/http/requests/website"
"panel/app/models"
@@ -95,24 +94,6 @@ func (r *WebsiteImpl) List(page, limit int) (int64, []models.Website, error) {
// Add 添加网站
func (r *WebsiteImpl) Add(website PanelWebsite) (models.Website, error) {
// 禁止部分保留名称
nameSlices := []string{"phpmyadmin", "mysql", "panel", "ssh"}
if slices.Contains(nameSlices, website.Name) {
return models.Website{}, errors.New("网站名称" + website.Name + "为保留名称,请更换")
}
// path为空时设置默认值
if len(website.Path) == 0 {
website.Path = r.setting.Get(models.SettingKeyWebsitePath) + "/" + website.Name
}
// path不为/开头时,返回错误
if website.Path[0] != '/' {
return models.Website{}, errors.New("网站路径" + website.Path + "必须以/开头")
}
website.Ssl = false
website.Status = true
w := models.Website{
Name: website.Name,
Status: website.Status,
@@ -295,20 +276,38 @@ server
return models.Website{}, err
}
tools.Exec("systemctl reload openresty")
if _, err := tools.Exec("systemctl reload openresty"); err != nil {
return models.Website{}, err
}
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
if website.Db && website.DbType == "mysql" {
tools.Exec(`/www/server/mysql/bin/mysql -uroot -p` + rootPassword + ` -e "CREATE DATABASE IF NOT EXISTS ` + website.DbName + ` DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci;"`)
tools.Exec(`/www/server/mysql/bin/mysql -uroot -p` + rootPassword + ` -e "CREATE USER '` + website.DbUser + `'@'localhost' IDENTIFIED BY '` + website.DbPassword + `';"`)
tools.Exec(`/www/server/mysql/bin/mysql -uroot -p` + rootPassword + ` -e "GRANT ALL PRIVILEGES ON ` + website.DbName + `.* TO '` + website.DbUser + `'@'localhost';"`)
tools.Exec(`/www/server/mysql/bin/mysql -uroot -p` + rootPassword + ` -e "FLUSH PRIVILEGES;"`)
if _, err := tools.Exec(`/www/server/mysql/bin/mysql -uroot -p` + rootPassword + ` -e "CREATE DATABASE IF NOT EXISTS ` + website.DbName + ` DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci;"`); err != nil {
return models.Website{}, err
}
if _, err := tools.Exec(`/www/server/mysql/bin/mysql -uroot -p` + rootPassword + ` -e "CREATE USER '` + website.DbUser + `'@'localhost' IDENTIFIED BY '` + website.DbPassword + `';"`); err != nil {
return models.Website{}, err
}
if _, err := tools.Exec(`/www/server/mysql/bin/mysql -uroot -p` + rootPassword + ` -e "GRANT ALL PRIVILEGES ON ` + website.DbName + `.* TO '` + website.DbUser + `'@'localhost';"`); err != nil {
return models.Website{}, err
}
if _, err := tools.Exec(`/www/server/mysql/bin/mysql -uroot -p` + rootPassword + ` -e "FLUSH PRIVILEGES;"`); err != nil {
return models.Website{}, err
}
}
if website.Db && website.DbType == "postgresql" {
tools.Exec(`echo "CREATE DATABASE ` + website.DbName + `;" | su - postgres -c "psql"`)
tools.Exec(`echo "CREATE USER ` + website.DbUser + ` WITH PASSWORD '` + website.DbPassword + `';" | su - postgres -c "psql"`)
tools.Exec(`echo "ALTER DATABASE ` + website.DbName + ` OWNER TO ` + website.DbUser + `;" | su - postgres -c "psql"`)
tools.Exec(`echo "GRANT ALL PRIVILEGES ON DATABASE ` + website.DbName + ` TO ` + website.DbUser + `;" | su - postgres -c "psql"`)
if _, err := tools.Exec(`echo "CREATE DATABASE ` + website.DbName + `;" | su - postgres -c "psql"`); err != nil {
return models.Website{}, err
}
if _, err := tools.Exec(`echo "CREATE USER ` + website.DbUser + ` WITH PASSWORD '` + website.DbPassword + `';" | su - postgres -c "psql"`); err != nil {
return models.Website{}, err
}
if _, err := tools.Exec(`echo "ALTER DATABASE ` + website.DbName + ` OWNER TO ` + website.DbUser + `;" | su - postgres -c "psql"`); err != nil {
return models.Website{}, err
}
if _, err := tools.Exec(`echo "GRANT ALL PRIVILEGES ON DATABASE ` + website.DbName + ` TO ` + website.DbUser + `;" | su - postgres -c "psql"`); err != nil {
return models.Website{}, err
}
}
return w, nil
@@ -331,7 +330,10 @@ func (r *WebsiteImpl) SaveConfig(config requests.SaveConfig) error {
if err := tools.Write("/www/server/vhost/"+website.Name+".conf", config.Raw, 0644); err != nil {
return err
}
tools.Exec("systemctl reload openresty")
if _, err := tools.Exec("systemctl reload openresty"); err != nil {
return err
}
return nil
}
@@ -509,8 +511,9 @@ func (r *WebsiteImpl) SaveConfig(config requests.SaveConfig) error {
if err := tools.Write("/www/server/vhost/rewrite/"+website.Name+".conf", config.Rewrite, 0644); err != nil {
return err
}
tools.Exec("systemctl reload openresty")
return nil
_, err := tools.Exec("systemctl reload openresty")
return err
}
// Delete 删除网站
@@ -534,9 +537,8 @@ func (r *WebsiteImpl) Delete(id uint) error {
tools.Remove("/www/server/vhost/ssl/" + website.Name + ".key")
tools.Remove(website.Path)
tools.Exec("systemctl reload openresty")
return nil
_, err := tools.Exec("systemctl reload openresty")
return err
}
// GetConfig 获取网站配置
@@ -630,9 +632,10 @@ func (r *WebsiteImpl) GetConfig(id uint) (WebsiteSetting, error) {
}
setting.Rewrite = tools.Read("/www/server/vhost/rewrite/" + website.Name + ".conf")
setting.Log = tools.Escape(tools.Exec(`tail -n 100 '/www/wwwlogs/` + website.Name + `.log'`))
log, err := tools.Exec(`tail -n 100 '/www/wwwlogs/` + website.Name + `.log'`)
setting.Log = log
return setting, nil
return setting, err
}
// GetConfigByName 根据网站名称获取网站配置

12
go.mod
View File

@@ -8,8 +8,8 @@ require (
github.com/go-acme/lego/v4 v4.14.2
github.com/gookit/color v1.5.4
github.com/gookit/validate v1.5.1
github.com/goravel/fiber v1.1.11-0.20231108081345-36e967f101d0
github.com/goravel/framework v1.13.1-0.20231110075143-376f1d9f92e1
github.com/goravel/fiber v1.1.11-0.20231113090419-d5dad0a0021b
github.com/goravel/framework v1.13.1-0.20231113084434-6b10569a75f5
github.com/iancoleman/strcase v0.3.0
github.com/imroc/req/v3 v3.42.1
github.com/mojocn/base64Captcha v1.3.5
@@ -19,8 +19,7 @@ require (
github.com/swaggo/files/v2 v2.0.0
github.com/swaggo/swag v1.16.2
github.com/valyala/fasthttp v1.50.0
golang.org/x/crypto v0.14.0
golang.org/x/exp v0.0.0-20231006140011-7918f672742d
golang.org/x/crypto v0.15.0
)
require (
@@ -81,9 +80,9 @@ require (
github.com/gofiber/utils v1.1.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang-jwt/jwt/v5 v5.0.0 // indirect
github.com/golang-jwt/jwt/v5 v5.1.0 // indirect
github.com/golang-migrate/migrate/v4 v4.16.2 // indirect
github.com/golang-module/carbon/v2 v2.2.12 // indirect
github.com/golang-module/carbon/v2 v2.2.13 // indirect
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
github.com/golang-sql/sqlexp v0.1.0 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
@@ -190,6 +189,7 @@ require (
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/arch v0.6.0 // indirect
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
golang.org/x/image v0.11.0 // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/net v0.17.0 // indirect

21
go.sum
View File

@@ -269,12 +269,13 @@ github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzw
github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE=
github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang-jwt/jwt/v5 v5.1.0 h1:UGKbA/IPjtS6zLcdB7i5TyACMgSbOTiR8qzXgw8HWQU=
github.com/golang-jwt/jwt/v5 v5.1.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang-migrate/migrate/v4 v4.16.2 h1:8coYbMKUyInrFk1lfGfRovTLAW7PhWp8qQDT2iKfuoA=
github.com/golang-migrate/migrate/v4 v4.16.2/go.mod h1:pfcJX4nPHaVdc5nmdCikFBWtm+UBpiZjRNNsyBbp0/o=
github.com/golang-module/carbon/v2 v2.2.12 h1:qydcu64b5+29dOnMNVS27V3JaphyA2eLrUvKv8CNPMI=
github.com/golang-module/carbon/v2 v2.2.12/go.mod h1:XDALX7KgqmHk95xyLeaqX9/LJGbfLATyruTziq68SZ8=
github.com/golang-module/carbon/v2 v2.2.13 h1:8BzSrasTFP4sIXA78i4I4LxxlIxetwGOUGu/+WfjdVg=
github.com/golang-module/carbon/v2 v2.2.13/go.mod h1:XDALX7KgqmHk95xyLeaqX9/LJGbfLATyruTziq68SZ8=
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
@@ -379,14 +380,14 @@ github.com/gookit/goutil v0.6.14 h1:96elyOG4BvVoDaiT7vx1vHPrVyEtFfYlPPBODR0/FGQ=
github.com/gookit/goutil v0.6.14/go.mod h1:YyDBddefmjS+mU2PDPgCcjVzTDM5WgExiDv5ZA/b8I8=
github.com/gookit/validate v1.5.1 h1:rPp64QZQJM+fysGFAhKpvekQAav4Ok6sjfTs9ZtxcpA=
github.com/gookit/validate v1.5.1/go.mod h1:SskOHUQokzMNt6T3r7N+N/4me/6fxDx+tmoXf/3ZQog=
github.com/goravel/fiber v1.1.11-0.20231108081345-36e967f101d0 h1:mEuJdUWmNXIrg5njcbOS+GucmOM2QrqAHL+ODTgDHPo=
github.com/goravel/fiber v1.1.11-0.20231108081345-36e967f101d0/go.mod h1:IOvZ0G1bojUU/Kv9DZl+/8cwGhcNr0YRhwElz0hpjTg=
github.com/goravel/fiber v1.1.11-0.20231113090419-d5dad0a0021b h1:RPUhnDbyVmyl7CJhIyqxQMX7KlQfmxkiJ8BT5vgh2q4=
github.com/goravel/fiber v1.1.11-0.20231113090419-d5dad0a0021b/go.mod h1:oWPUDnztciFw4cSAk5CskLXYE0Joe9fWQanLNR39tIA=
github.com/goravel/file-rotatelogs v0.0.0-20211215053220-2ab31dd9575c h1:obhFK91JAhcf7s6h5sggZishm1VyGW/gBCreo+7/SwQ=
github.com/goravel/file-rotatelogs v0.0.0-20211215053220-2ab31dd9575c/go.mod h1:YSWsLXlG16u5CWFaXNZHhEQD10+NwF3xfgDV816OwLE=
github.com/goravel/file-rotatelogs/v2 v2.4.1 h1:ogkeIFcTHSBRUBpZYiyJbpul8hkVXxHPuDbOaP78O1M=
github.com/goravel/file-rotatelogs/v2 v2.4.1/go.mod h1:euk9qr52WrzM8ICs1hecFcR4CZ/ZZOPdacHfvHgbOf0=
github.com/goravel/framework v1.13.1-0.20231110075143-376f1d9f92e1 h1:J0FjRp0EGsyno2XNfUHIz2ghuE0dyg2/VUlR10/KRZA=
github.com/goravel/framework v1.13.1-0.20231110075143-376f1d9f92e1/go.mod h1:9vNb8pNm1HBF/1I4SOD88F5rP+/SvzrniJDx9t15OzU=
github.com/goravel/framework v1.13.1-0.20231113084434-6b10569a75f5 h1:Vh3xNLjnFyeJ+xecIE/FeISIV3ti+tuiKcntN0bKP5Y=
github.com/goravel/framework v1.13.1-0.20231113084434-6b10569a75f5/go.mod h1:EOMHWx6zpEgu12vIVglYuq1zNH/SXo+zeWsumY0esgo=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI=
@@ -744,8 +745,8 @@ golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -937,7 +938,7 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

33
pkg/tools/service.go Normal file
View File

@@ -0,0 +1,33 @@
package tools
import "fmt"
// ServiceStatus 获取服务状态
func ServiceStatus(name string) (bool, error) {
output, err := Exec(fmt.Sprintf("systemctl status %s | grep Active | grep -v grep | awk '{print $2}'", name))
return output == "active", err
}
// ServiceStart 启动服务
func ServiceStart(name string) error {
_, err := Exec(fmt.Sprintf("systemctl start %s", name))
return err
}
// ServiceStop 停止服务
func ServiceStop(name string) error {
_, err := Exec(fmt.Sprintf("systemctl stop %s", name))
return err
}
// ServiceRestart 重启服务
func ServiceRestart(name string) error {
_, err := Exec(fmt.Sprintf("systemctl restart %s", name))
return err
}
// ServiceReload 重载服务
func ServiceReload(name string) error {
_, err := Exec(fmt.Sprintf("systemctl reload %s", name))
return err
}

View File

@@ -7,7 +7,6 @@ import (
"path/filepath"
"strings"
"github.com/goravel/framework/facades"
"github.com/goravel/framework/support"
)
@@ -26,13 +25,10 @@ func Write(path string, data string, permission os.FileMode) error {
}
// Read 读取文件
// TODO 重构带 error 返回
func Read(path string) string {
data, err := os.ReadFile(path)
if err != nil {
facades.Log().With(map[string]any{
"path": path,
"error": err.Error(),
}).Tags("面板", "工具函数").Info("读取文件失败")
return ""
}
@@ -40,12 +36,9 @@ func Read(path string) string {
}
// Remove 删除文件/目录
// TODO 重构带 error 返回
func Remove(path string) bool {
if err := os.RemoveAll(path); err != nil {
facades.Log().With(map[string]any{
"path": path,
"error": err.Error(),
}).Tags("面板", "工具函数").Info("删除文件/目录失败")
return false
}
@@ -53,25 +46,11 @@ func Remove(path string) bool {
}
// Exec 执行 shell 命令
func Exec(shell string) string {
cmd := exec.Command("bash", "-c", shell)
func Exec(shell string) (string, error) {
cmd := exec.Command("bash", "-c", "LC_ALL=C "+shell)
output, err := cmd.CombinedOutput()
if err != nil {
if support.Env == support.EnvTest {
fmt.Println(string(output))
fmt.Println(err.Error())
panic(err)
} else {
facades.Log().With(map[string]any{
"shell": shell,
"error": err.Error(),
}).Tags("面板", "工具函数").Info("执行命令失败")
}
return ""
}
return strings.TrimSpace(string(output))
return strings.TrimSpace(string(output)), err
}
// ExecAsync 异步执行 shell 命令
@@ -88,11 +67,6 @@ func ExecAsync(shell string) error {
if support.Env == support.EnvTest {
fmt.Println(err.Error())
panic(err)
} else {
facades.Log().With(map[string]any{
"shell": shell,
"error": err.Error(),
}).Tags("面板", "工具函数").Info("异步执行命令失败")
}
}
}()

View File

@@ -48,7 +48,9 @@ func (s *SystemHelperTestSuite) TestRemove() {
}
func (s *SystemHelperTestSuite) TestExec() {
s.Equal("test", Exec("echo 'test'"))
output, err := Exec("echo 'test'")
s.Equal("test", output)
s.Nil(err)
}
func (s *SystemHelperTestSuite) TestExecAsync() {

View File

@@ -165,15 +165,16 @@ type PanelInfo struct {
func GetLatestPanelVersion() (PanelInfo, error) {
var info PanelInfo
var output string
var err error
isChina := IsChina()
if isChina {
output = Exec(`curl -sSL "https://jihulab.com/api/v4/projects/haozi-team%2Fpanel/releases/permalink/latest"`)
output, err = Exec(`curl -sSL "https://jihulab.com/api/v4/projects/haozi-team%2Fpanel/releases/permalink/latest"`)
} else {
output = Exec(`curl -sSL "https://api.github.com/repos/haozi-team/panel/releases/latest"`)
output, err = Exec(`curl -sSL "https://api.github.com/repos/haozi-team/panel/releases/latest"`)
}
if len(output) == 0 {
if len(output) == 0 || err != nil {
return info, errors.New("获取最新版本失败")
}
@@ -194,32 +195,72 @@ func GetLatestPanelVersion() (PanelInfo, error) {
var name, version, body, date, downloadName, downloadUrl, checksums, checksumsUrl string
if isChina {
name = Exec("jq -r '.name' " + fileName)
version = Exec("jq -r '.tag_name' " + fileName)
body = Exec("jq -r '.description' " + fileName)
date = Exec("jq -r '.created_at' " + fileName)
checksums = Exec("jq -r '.assets.links[] | select(.name | contains(\"checksums\")) | .name' " + fileName)
checksumsUrl = Exec("jq -r '.assets.links[] | select(.name | contains(\"checksums\")) | .direct_asset_url' " + fileName)
if name, err = Exec("jq -r '.name' " + fileName); err != nil {
return info, errors.New("获取最新版本失败")
}
if version, err = Exec("jq -r '.tag_name' " + fileName); err != nil {
return info, errors.New("获取最新版本失败")
}
if body, err = Exec("jq -r '.description' " + fileName); err != nil {
return info, errors.New("获取最新版本失败")
}
if date, err = Exec("jq -r '.created_at' " + fileName); err != nil {
return info, errors.New("获取最新版本失败")
}
if checksums, err = Exec("jq -r '.assets.links[] | select(.name | contains(\"checksums\")) | .name' " + fileName); err != nil {
return info, errors.New("获取最新版本失败")
}
if checksumsUrl, err = Exec("jq -r '.assets.links[] | select(.name | contains(\"checksums\")) | .direct_asset_url' " + fileName); err != nil {
return info, errors.New("获取最新版本失败")
}
if IsArm() {
downloadName = Exec("jq -r '.assets.links[] | select(.name | contains(\"arm64\")) | .name' " + fileName)
downloadUrl = Exec("jq -r '.assets.links[] | select(.name | contains(\"arm64\")) | .direct_asset_url' " + fileName)
if downloadName, err = Exec("jq -r '.assets.links[] | select(.name | contains(\"arm64\")) | .name' " + fileName); err != nil {
return info, errors.New("获取最新版本失败")
}
if downloadUrl, err = Exec("jq -r '.assets.links[] | select(.name | contains(\"arm64\")) | .direct_asset_url' " + fileName); err != nil {
return info, errors.New("获取最新版本失败")
}
} else {
downloadName = Exec("jq -r '.assets.links[] | select(.name | contains(\"amd64v2\")) | .name' " + fileName)
downloadUrl = Exec("jq -r '.assets.links[] | select(.name | contains(\"amd64v2\")) | .direct_asset_url' " + fileName)
if downloadName, err = Exec("jq -r '.assets.links[] | select(.name | contains(\"amd64v2\")) | .name' " + fileName); err != nil {
return info, errors.New("获取最新版本失败")
}
if downloadUrl, err = Exec("jq -r '.assets.links[] | select(.name | contains(\"amd64v2\")) | .direct_asset_url' " + fileName); err != nil {
return info, errors.New("获取最新版本失败")
}
}
} else {
name = Exec("jq -r '.name' " + fileName)
version = Exec("jq -r '.tag_name' " + fileName)
body = Exec("jq -r '.body' " + fileName)
date = Exec("jq -r '.published_at' " + fileName)
checksums = Exec("jq -r '.assets[] | select(.name | contains(\"checksums\")) | .name' " + fileName)
checksumsUrl = Exec("jq -r '.assets[] | select(.name | contains(\"checksums\")) | .browser_download_url' " + fileName)
if name, err = Exec("jq -r '.name' " + fileName); err != nil {
return info, errors.New("获取最新版本失败")
}
if version, err = Exec("jq -r '.tag_name' " + fileName); err != nil {
return info, errors.New("获取最新版本失败")
}
if body, err = Exec("jq -r '.body' " + fileName); err != nil {
return info, errors.New("获取最新版本失败")
}
if date, err = Exec("jq -r '.published_at' " + fileName); err != nil {
return info, errors.New("获取最新版本失败")
}
if checksums, err = Exec("jq -r '.assets[] | select(.name | contains(\"checksums\")) | .name' " + fileName); err != nil {
return info, errors.New("获取最新版本失败")
}
if checksumsUrl, err = Exec("jq -r '.assets[] | select(.name | contains(\"checksums\")) | .browser_download_url' " + fileName); err != nil {
return info, errors.New("获取最新版本失败")
}
if IsArm() {
downloadName = Exec("jq -r '.assets[] | select(.name | contains(\"arm64\")) | .name' " + fileName)
downloadUrl = Exec("jq -r '.assets[] | select(.name | contains(\"arm64\")) | .browser_download_url' " + fileName)
if downloadName, err = Exec("jq -r '.assets[] | select(.name | contains(\"arm64\")) | .name' " + fileName); err != nil {
return info, errors.New("获取最新版本失败")
}
if downloadUrl, err = Exec("jq -r '.assets[] | select(.name | contains(\"arm64\")) | .browser_download_url' " + fileName); err != nil {
return info, errors.New("获取最新版本失败")
}
} else {
downloadName = Exec("jq -r '.assets[] | select(.name | contains(\"amd64v2\")) | .name' " + fileName)
downloadUrl = Exec("jq -r '.assets[] | select(.name | contains(\"amd64v2\")) | .browser_download_url' " + fileName)
if downloadName, err = Exec("jq -r '.assets[] | select(.name | contains(\"amd64v2\")) | .name' " + fileName); err != nil {
return info, errors.New("获取最新版本失败")
}
if downloadUrl, err = Exec("jq -r '.assets[] | select(.name | contains(\"amd64v2\")) | .browser_download_url' " + fileName); err != nil {
return info, errors.New("获取最新版本失败")
}
}
}
@@ -239,6 +280,7 @@ func GetLatestPanelVersion() (PanelInfo, error) {
func GetPanelVersion(version string) (PanelInfo, error) {
var info PanelInfo
var output string
var err error
isChina := IsChina()
if !strings.HasPrefix(version, "v") {
@@ -246,12 +288,12 @@ func GetPanelVersion(version string) (PanelInfo, error) {
}
if isChina {
output = Exec(`curl -sSL "https://jihulab.com/api/v4/projects/haozi-team%2Fpanel/releases/` + version + `"`)
output, err = Exec(`curl -sSL "https://jihulab.com/api/v4/projects/haozi-team%2Fpanel/releases/` + version + `"`)
} else {
output = Exec(`curl -sSL "https://api.github.com/repos/haozi-team/panel/releases/tags/` + version + `"`)
output, err = Exec(`curl -sSL "https://api.github.com/repos/haozi-team/panel/releases/tags/` + version + `"`)
}
if len(output) == 0 {
if len(output) == 0 || err != nil {
return info, errors.New("获取面板版本失败")
}
@@ -272,32 +314,72 @@ func GetPanelVersion(version string) (PanelInfo, error) {
var name, version2, body, date, downloadName, downloadUrl, checksums, checksumsUrl string
if isChina {
name = Exec("jq -r '.name' " + fileName)
version2 = Exec("jq -r '.tag_name' " + fileName)
body = Exec("jq -r '.description' " + fileName)
date = Exec("jq -r '.created_at' " + fileName)
checksums = Exec("jq -r '.assets.links[] | select(.name | contains(\"checksums\")) | .name' " + fileName)
checksumsUrl = Exec("jq -r '.assets.links[] | select(.name | contains(\"checksums\")) | .direct_asset_url' " + fileName)
if name, err = Exec("jq -r '.name' " + fileName); err != nil {
return info, errors.New("获取面板版本失败")
}
if version2, err = Exec("jq -r '.tag_name' " + fileName); err != nil {
return info, errors.New("获取面板版本失败")
}
if body, err = Exec("jq -r '.description' " + fileName); err != nil {
return info, errors.New("获取面板版本失败")
}
if date, err = Exec("jq -r '.created_at' " + fileName); err != nil {
return info, errors.New("获取面板版本失败")
}
if checksums, err = Exec("jq -r '.assets.links[] | select(.name | contains(\"checksums\")) | .name' " + fileName); err != nil {
return info, errors.New("获取面板版本失败")
}
if checksumsUrl, err = Exec("jq -r '.assets.links[] | select(.name | contains(\"checksums\")) | .direct_asset_url' " + fileName); err != nil {
return info, errors.New("获取面板版本失败")
}
if IsArm() {
downloadName = Exec("jq -r '.assets.links[] | select(.name | contains(\"arm64\")) | .name' " + fileName)
downloadUrl = Exec("jq -r '.assets.links[] | select(.name | contains(\"arm64\")) | .direct_asset_url' " + fileName)
if downloadName, err = Exec("jq -r '.assets.links[] | select(.name | contains(\"arm64\")) | .name' " + fileName); err != nil {
return info, errors.New("获取面板版本失败")
}
if downloadUrl, err = Exec("jq -r '.assets.links[] | select(.name | contains(\"arm64\")) | .direct_asset_url' " + fileName); err != nil {
return info, errors.New("获取面板版本失败")
}
} else {
downloadName = Exec("jq -r '.assets.links[] | select(.name | contains(\"amd64v2\")) | .name' " + fileName)
downloadUrl = Exec("jq -r '.assets.links[] | select(.name | contains(\"amd64v2\")) | .direct_asset_url' " + fileName)
if downloadName, err = Exec("jq -r '.assets.links[] | select(.name | contains(\"amd64v2\")) | .name' " + fileName); err != nil {
return info, errors.New("获取面板版本失败")
}
if downloadUrl, err = Exec("jq -r '.assets.links[] | select(.name | contains(\"amd64v2\")) | .direct_asset_url' " + fileName); err != nil {
return info, errors.New("获取面板版本失败")
}
}
} else {
name = Exec("jq -r '.name' " + fileName)
version2 = Exec("jq -r '.tag_name' " + fileName)
body = Exec("jq -r '.body' " + fileName)
date = Exec("jq -r '.published_at' " + fileName)
checksums = Exec("jq -r '.assets[] | select(.name | contains(\"checksums\")) | .name' " + fileName)
checksumsUrl = Exec("jq -r '.assets[] | select(.name | contains(\"checksums\")) | .browser_download_url' " + fileName)
if name, err = Exec("jq -r '.name' " + fileName); err != nil {
return info, errors.New("获取面板版本失败")
}
if version2, err = Exec("jq -r '.tag_name' " + fileName); err != nil {
return info, errors.New("获取面板版本失败")
}
if body, err = Exec("jq -r '.body' " + fileName); err != nil {
return info, errors.New("获取面板版本失败")
}
if date, err = Exec("jq -r '.published_at' " + fileName); err != nil {
return info, errors.New("获取面板版本失败")
}
if checksums, err = Exec("jq -r '.assets[] | select(.name | contains(\"checksums\")) | .name' " + fileName); err != nil {
return info, errors.New("获取面板版本失败")
}
if checksumsUrl, err = Exec("jq -r '.assets[] | select(.name | contains(\"checksums\")) | .browser_download_url' " + fileName); err != nil {
return info, errors.New("获取面板版本失败")
}
if IsArm() {
downloadName = Exec("jq -r '.assets[] | select(.name | contains(\"arm64\")) | .name' " + fileName)
downloadUrl = Exec("jq -r '.assets[] | select(.name | contains(\"arm64\")) | .browser_download_url' " + fileName)
if downloadName, err = Exec("jq -r '.assets[] | select(.name | contains(\"arm64\")) | .name' " + fileName); err != nil {
return info, errors.New("获取面板版本失败")
}
if downloadUrl, err = Exec("jq -r '.assets[] | select(.name | contains(\"arm64\")) | .browser_download_url' " + fileName); err != nil {
return info, errors.New("获取面板版本失败")
}
} else {
downloadName = Exec("jq -r '.assets[] | select(.name | contains(\"amd64v2\")) | .name' " + fileName)
downloadUrl = Exec("jq -r '.assets[] | select(.name | contains(\"amd64v2\")) | .browser_download_url' " + fileName)
if downloadName, err = Exec("jq -r '.assets[] | select(.name | contains(\"amd64v2\")) | .name' " + fileName); err != nil {
return info, errors.New("获取面板版本失败")
}
if downloadUrl, err = Exec("jq -r '.assets[] | select(.name | contains(\"amd64v2\")) | .browser_download_url' " + fileName); err != nil {
return info, errors.New("获取面板版本失败")
}
}
}
@@ -319,58 +401,100 @@ func UpdatePanel(panelInfo PanelInfo) error {
color.Greenln("下载链接: " + panelInfo.DownloadUrl)
color.Greenln("备份面板配置...")
Exec("cp -f /www/panel/database/panel.db /tmp/panel.db.bak")
Exec("cp -f /www/panel/panel.conf /tmp/panel.conf.bak")
if _, err := Exec("cp -f /www/panel/database/panel.db /tmp/panel.db.bak"); err != nil {
color.Redln("备份面板数据库失败")
return err
}
if _, err := Exec("cp -f /www/panel/panel.conf /tmp/panel.conf.bak"); err != nil {
color.Redln("备份面板配置失败")
return err
}
if !Exists("/tmp/panel.db.bak") || !Exists("/tmp/panel.conf.bak") {
return errors.New("备份面板配置失败")
}
color.Greenln("备份完成")
color.Greenln("清理旧版本...")
Exec("rm -rf /www/panel/*")
if _, err := Exec("rm -rf /www/panel/*"); err != nil {
color.Redln("清理旧版本失败")
return err
}
color.Greenln("清理完成")
color.Greenln("正在下载...")
Exec("wget -T 120 -t 3 -O /www/panel/" + panelInfo.DownloadName + " " + panelInfo.DownloadUrl)
Exec("wget -T 20 -t 3 -O /www/panel/" + panelInfo.Checksums + " " + panelInfo.ChecksumsUrl)
if _, err := Exec("wget -T 120 -t 3 -O /www/panel/" + panelInfo.DownloadName + " " + panelInfo.DownloadUrl); err != nil {
color.Redln("下载失败")
return err
}
if _, err := Exec("wget -T 20 -t 3 -O /www/panel/" + panelInfo.Checksums + " " + panelInfo.ChecksumsUrl); err != nil {
color.Redln("下载失败")
return err
}
if !Exists("/www/panel/"+panelInfo.DownloadName) || !Exists("/www/panel/"+panelInfo.Checksums) {
return errors.New("下载失败")
}
color.Greenln("下载完成")
color.Greenln("校验下载文件...")
check := Exec("cd /www/panel && sha256sum -c " + panelInfo.Checksums + " --ignore-missing")
if check != panelInfo.DownloadName+": OK" {
check, err := Exec("cd /www/panel && sha256sum -c " + panelInfo.Checksums + " --ignore-missing")
if check != panelInfo.DownloadName+": OK" || err != nil {
return errors.New("下载文件校验失败")
}
Remove("/www/panel/" + panelInfo.Checksums)
color.Greenln("文件校验完成")
color.Greenln("更新新版本...")
Exec("cd /www/panel && unzip -o " + panelInfo.DownloadName + " && rm -rf " + panelInfo.DownloadName)
if _, err = Exec("cd /www/panel && unzip -o " + panelInfo.DownloadName + " && rm -rf " + panelInfo.DownloadName); err != nil {
color.Redln("更新失败")
return err
}
if !Exists("/www/panel/panel") {
return errors.New("更新失败,可能是下载过程中出现了问题")
}
color.Greenln("更新完成")
color.Greenln("恢复面板配置...")
Exec("cp -f /tmp/panel.db.bak /www/panel/database/panel.db")
Exec("cp -f /tmp/panel.conf.bak /www/panel/panel.conf")
if _, err = Exec("cp -f /tmp/panel.db.bak /www/panel/database/panel.db"); err != nil {
color.Redln("恢复面板数据库失败")
return err
}
if _, err = Exec("cp -f /tmp/panel.conf.bak /www/panel/panel.conf"); err != nil {
color.Redln("恢复面板配置失败")
return err
}
if !Exists("/www/panel/database/panel.db") || !Exists("/www/panel/panel.conf") {
return errors.New("恢复面板配置失败")
}
Exec("/www/panel/panel --env=panel.conf artisan migrate")
if _, err = Exec("/www/panel/panel --env=panel.conf artisan migrate"); err != nil {
color.Redln("运行面板数据库迁移失败")
return err
}
color.Greenln("恢复完成")
color.Greenln("设置面板文件权限...")
Exec("chmod -R 700 /www/panel")
if _, err = Exec("chmod -R 700 /www/panel"); err != nil {
color.Redln("设置面板文件权限失败")
return err
}
color.Greenln("设置完成")
Exec("bash /www/panel/scripts/update_panel.sh")
Exec("panel writeSetting version " + panelInfo.Version)
if _, err = Exec("bash /www/panel/scripts/update_panel.sh"); err != nil {
color.Redln("执行面板升级后脚本失败")
return err
}
if _, err = Exec("panel writeSetting version " + panelInfo.Version); err != nil {
color.Redln("写入面板版本号失败")
return err
}
Exec("rm -rf /tmp/panel.db.bak")
Exec("rm -rf /tmp/panel.conf.bak")
if _, err = Exec("rm -rf /tmp/panel.db.bak"); err != nil {
color.Redln("清理临时文件失败")
return err
}
if _, err = Exec("rm -rf /tmp/panel.conf.bak"); err != nil {
color.Redln("清理临时文件失败")
return err
}
return nil
}