diff --git a/backend/app/api/v1/container.go b/backend/app/api/v1/container.go index cdcc3e534..ee7952ff3 100644 --- a/backend/app/api/v1/container.go +++ b/backend/app/api/v1/container.go @@ -355,6 +355,28 @@ func (b *BaseApi) CleanContainerLog(c *gin.Context) { helper.SuccessWithData(c, nil) } +// @Tags Container +// @Summary Load container log +// @Description 获取容器操作日志 +// @Accept json +// @Param request body dto.OperationWithNameAndType true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /containers/load/log [post] +func (b *BaseApi) LoadContainerLog(c *gin.Context) { + var req dto.OperationWithNameAndType + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + content, err := containerService.LoadContainerLogs(req) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, content) +} + // @Tags Container // @Summary Operate Container // @Description 容器操作 diff --git a/backend/app/api/v1/cronjob.go b/backend/app/api/v1/cronjob.go index 5ba8a2cf4..c75e6f338 100644 --- a/backend/app/api/v1/cronjob.go +++ b/backend/app/api/v1/cronjob.go @@ -94,6 +94,28 @@ func (b *BaseApi) SearchJobRecords(c *gin.Context) { }) } +// @Tags Cronjob +// @Summary Load Cronjob record log +// @Description 获取计划任务记录日志 +// @Accept json +// @Param request body dto.OperateByID true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /cronjob/record/log [post] +func (b *BaseApi) LoadRecordLog(c *gin.Context) { + var req dto.OperateByID + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + content, err := cronjobService.LoadRecordLog(req) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, content) +} + // @Tags Cronjob // @Summary Clean job records // @Description 清空计划任务记录 diff --git a/backend/app/api/v1/database_mysql.go b/backend/app/api/v1/database_mysql.go index 4f455213a..ff7a8379d 100644 --- a/backend/app/api/v1/database_mysql.go +++ b/backend/app/api/v1/database_mysql.go @@ -321,6 +321,28 @@ func (b *BaseApi) LoadBaseinfo(c *gin.Context) { helper.SuccessWithData(c, data) } +// @Tags Database +// @Summary Load Database file +// @Description 获取数据库文件 +// @Accept json +// @Param request body dto.OperationWithNameAndType true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /databases/load/file [post] +func (b *BaseApi) LoadDatabaseFile(c *gin.Context) { + var req dto.OperationWithNameAndType + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + content, err := mysqlService.LoadDatabaseFile(req) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, content) +} + // @Tags Database Mysql // @Summary Load mysql remote access // @Description 获取 mysql 远程访问权限 diff --git a/backend/app/api/v1/file.go b/backend/app/api/v1/file.go index 10f3736af..1542a2c7b 100644 --- a/backend/app/api/v1/file.go +++ b/backend/app/api/v1/file.go @@ -589,33 +589,6 @@ func (b *BaseApi) Size(c *gin.Context) { helper.SuccessWithData(c, res) } -// @Tags File -// @Summary Read file -// @Description 读取文件 -// @Accept json -// @Param request body dto.FilePath true "request" -// @Success 200 {string} content -// @Security ApiKeyAuth -// @Router /files/loadfile [post] -func (b *BaseApi) LoadFromFile(c *gin.Context) { - var req dto.FilePath - if err := c.ShouldBindJSON(&req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - if err := global.VALID.Struct(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - - content, err := os.ReadFile(req.Path) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, string(content)) -} - func mergeChunks(fileName string, fileDir string, dstDir string, chunkCount int) error { if _, err := os.Stat(path.Dir(dstDir)); err != nil && os.IsNotExist(err) { if err = os.MkdirAll(path.Dir(dstDir), os.ModePerm); err != nil { diff --git a/backend/app/api/v1/logs.go b/backend/app/api/v1/logs.go index e723a0721..7a1c28bad 100644 --- a/backend/app/api/v1/logs.go +++ b/backend/app/api/v1/logs.go @@ -89,3 +89,19 @@ func (b *BaseApi) CleanLogs(c *gin.Context) { helper.SuccessWithData(c, nil) } + +// @Tags Logs +// @Summary Load system logs +// @Description 获取系统日志 +// @Success 200 +// @Security ApiKeyAuth +// @Router /logs/system [get] +func (b *BaseApi) GetSystemLogs(c *gin.Context) { + data, err := logService.LoadSystemLog() + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + + helper.SuccessWithData(c, data) +} diff --git a/backend/app/api/v1/ssh.go b/backend/app/api/v1/ssh.go index 67bfebc40..644216dd2 100644 --- a/backend/app/api/v1/ssh.go +++ b/backend/app/api/v1/ssh.go @@ -183,3 +183,18 @@ func (b *BaseApi) LoadSSHLogs(c *gin.Context) { } helper.SuccessWithData(c, data) } + +// @Tags SSH +// @Summary Load host ssh conf +// @Description 获取 ssh 配置文件 +// @Success 200 +// @Security ApiKeyAuth +// @Router /host/ssh/conf [get] +func (b *BaseApi) LoadSSHConf(c *gin.Context) { + data, err := sshService.LoadSSHConf() + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, data) +} diff --git a/backend/app/service/container.go b/backend/app/service/container.go index 1b4712153..5cd64a6ed 100644 --- a/backend/app/service/container.go +++ b/backend/app/service/container.go @@ -7,6 +7,7 @@ import ( "io" "os" "os/exec" + "path" "path/filepath" "sort" "strconv" @@ -63,6 +64,8 @@ type IContainerService interface { TestCompose(req dto.ComposeCreate) (bool, error) ComposeUpdate(req dto.ComposeUpdate) error Prune(req dto.ContainerPrune) (dto.ContainerPruneReport, error) + + LoadContainerLogs(req dto.OperationWithNameAndType) (string, error) } func NewIContainerService() IContainerService { @@ -182,7 +185,7 @@ func (u *ContainerService) List() ([]string, error) { for _, container := range containers { for _, name := range container.Names { if len(name) != 0 { - datas = append(datas, strings.TrimLeft(name, "/")) + datas = append(datas, strings.TrimPrefix(name, "/")) } } } @@ -625,6 +628,48 @@ func (u *ContainerService) ContainerStats(id string) (*dto.ContainerStats, error return &data, nil } +func (u *ContainerService) LoadContainerLogs(req dto.OperationWithNameAndType) (string, error) { + filePath := "" + switch req.Type { + case "image-pull", "image-push", "image-build": + filePath = path.Join(global.CONF.System.TmpDir, fmt.Sprintf("docker_logs/%s", req.Name)) + case "compose-detail", "compose-create": + client, err := docker.NewDockerClient() + if err != nil { + return "", err + } + options := types.ContainerListOptions{All: true} + options.Filters = filters.NewArgs() + options.Filters.Add("label", fmt.Sprintf("%s=%s", composeProjectLabel, req.Name)) + containers, err := client.ContainerList(context.Background(), options) + if err != nil { + return "", err + } + for _, container := range containers { + config := container.Labels[composeConfigLabel] + workdir := container.Labels[composeWorkdirLabel] + if len(config) != 0 && len(workdir) != 0 && strings.Contains(config, workdir) { + filePath = config + break + } else { + filePath = workdir + break + } + } + if req.Type == "compose-create" { + filePath = path.Join(path.Dir(filePath), "/compose.log") + } + } + if _, err := os.Stat(filePath); err != nil { + return "", buserr.New("ErrHttpReqNotFound") + } + content, err := os.ReadFile(filePath) + if err != nil { + return "", err + } + return string(content), nil +} + func stringsToMap(list []string) map[string]string { var lableMap = make(map[string]string) for _, label := range list { diff --git a/backend/app/service/container_compose.go b/backend/app/service/container_compose.go index c092bd117..007575fb6 100644 --- a/backend/app/service/container_compose.go +++ b/backend/app/service/container_compose.go @@ -157,7 +157,7 @@ func (u *ContainerService) CreateCompose(req dto.ComposeCreate) (string, error) global.LOG.Infof("docker-compose.yml %s create successful, start to docker-compose up", req.Name) if req.From == "path" { - req.Name = path.Base(strings.ReplaceAll(req.Path, "/"+path.Base(req.Path), "")) + req.Name = path.Base(path.Dir(req.Path)) } logName := path.Dir(req.Path) + "/compose.log" file, err := os.OpenFile(logName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) @@ -181,7 +181,7 @@ func (u *ContainerService) CreateCompose(req dto.ComposeCreate) (string, error) _, _ = file.WriteString("docker-compose up successful!") }() - return logName, nil + return req.Name, nil } func (u *ContainerService) ComposeOperation(req dto.ComposeOperation) error { diff --git a/backend/app/service/cornjob.go b/backend/app/service/cornjob.go index 52ecc2dc5..a0200f7d6 100644 --- a/backend/app/service/cornjob.go +++ b/backend/app/service/cornjob.go @@ -9,6 +9,7 @@ import ( "github.com/1Panel-dev/1Panel/backend/app/dto" "github.com/1Panel-dev/1Panel/backend/app/model" + "github.com/1Panel-dev/1Panel/backend/buserr" "github.com/1Panel-dev/1Panel/backend/constant" "github.com/1Panel-dev/1Panel/backend/global" "github.com/jinzhu/copier" @@ -29,6 +30,8 @@ type ICronjobService interface { Download(down dto.CronjobDownload) (string, error) StartJob(cronjob *model.Cronjob) (int, error) CleanRecord(req dto.CronjobClean) error + + LoadRecordLog(req dto.OperateByID) (string, error) } func NewICronjobService() ICronjobService { @@ -80,6 +83,21 @@ func (u *CronjobService) SearchRecords(search dto.SearchRecord) (int64, interfac return total, dtoCronjobs, err } +func (u *CronjobService) LoadRecordLog(req dto.OperateByID) (string, error) { + record, err := cronjobRepo.GetRecord(commonRepo.WithByID(req.ID)) + if err != nil { + return "", err + } + if _, err := os.Stat(record.Records); err != nil { + return "", buserr.New("ErrHttpReqNotFound") + } + content, err := os.ReadFile(record.Records) + if err != nil { + return "", err + } + return string(content), nil +} + func (u *CronjobService) CleanRecord(req dto.CronjobClean) error { cronjob, err := cronjobRepo.Get(commonRepo.WithByID(req.CronjobID)) if err != nil { diff --git a/backend/app/service/database_mysql.go b/backend/app/service/database_mysql.go index e2beb9e0b..76ed08f0a 100644 --- a/backend/app/service/database_mysql.go +++ b/backend/app/service/database_mysql.go @@ -46,6 +46,8 @@ type IMysqlService interface { LoadVariables() (*dto.MysqlVariables, error) LoadBaseInfo() (*dto.DBBaseInfo, error) LoadRemoteAccess() (bool, error) + + LoadDatabaseFile(req dto.OperationWithNameAndType) (string, error) } func NewIMysqlService() IMysqlService { @@ -514,6 +516,26 @@ func (u *MysqlService) LoadStatus() (*dto.MysqlStatus, error) { return &info, nil } +func (u *MysqlService) LoadDatabaseFile(req dto.OperationWithNameAndType) (string, error) { + filePath := "" + switch req.Type { + case "mysql-conf": + filePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/mysql/%s/conf/my.cnf", req.Name)) + case "redis-conf": + filePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/redis/%s/conf/redis.conf", req.Name)) + case "slow-logs": + filePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/mysql/%s/data/1Panel-slow.log", req.Name)) + } + if _, err := os.Stat(filePath); err != nil { + return "", buserr.New("ErrHttpReqNotFound") + } + content, err := os.ReadFile(filePath) + if err != nil { + return "", err + } + return string(content), nil +} + func excuteSqlForMaps(containerName, password, command string) (map[string]string, error) { cmd := exec.Command("docker", "exec", containerName, "mysql", "-uroot", "-p"+password, "-e", command) stdout, err := cmd.CombinedOutput() diff --git a/backend/app/service/docker.go b/backend/app/service/docker.go index a56748363..a73337705 100644 --- a/backend/app/service/docker.go +++ b/backend/app/service/docker.go @@ -136,14 +136,14 @@ func (u *DockerService) UpdateConf(req dto.SettingUpdate) error { switch req.Key { case "Registries": - req.Value = strings.TrimRight(req.Value, ",") + req.Value = strings.TrimSuffix(req.Value, ",") if len(req.Value) == 0 { delete(daemonMap, "insecure-registries") } else { daemonMap["insecure-registries"] = strings.Split(req.Value, ",") } case "Mirrors": - req.Value = strings.TrimRight(req.Value, ",") + req.Value = strings.TrimSuffix(req.Value, ",") if len(req.Value) == 0 { delete(daemonMap, "registry-mirrors") } else { diff --git a/backend/app/service/image.go b/backend/app/service/image.go index 58c5c198e..e49826ad1 100644 --- a/backend/app/service/image.go +++ b/backend/app/service/image.go @@ -123,6 +123,7 @@ func (u *ImageService) ImageBuild(req dto.ImageBuild) (string, error) { return "", err } fileName := "Dockerfile" + dockerLogDir := path.Join(global.CONF.System.TmpDir, "/docker_logs") if req.From == "edit" { dir := fmt.Sprintf("%s/docker/build/%s", constant.DataDir, strings.ReplaceAll(req.Name, ":", "_")) if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) { @@ -156,10 +157,9 @@ func (u *ImageService) ImageBuild(req dto.ImageBuild) (string, error) { Remove: true, Labels: stringsToMap(req.Tags), } - logName := fmt.Sprintf("%s/build.log", req.Dockerfile) - pathItem := logName - file, err := os.OpenFile(pathItem, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) + logItem := fmt.Sprintf("%s/image_build_%s_%s.log", dockerLogDir, strings.ReplaceAll(req.Name, ":", "_"), time.Now().Format("20060102150405")) + file, err := os.OpenFile(logItem, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) if err != nil { return "", err } @@ -192,7 +192,7 @@ func (u *ImageService) ImageBuild(req dto.ImageBuild) (string, error) { _, _ = file.WriteString("image build successful!") }() - return logName, nil + return path.Base(logItem), nil } func (u *ImageService) ImagePull(req dto.ImagePull) (string, error) { @@ -200,15 +200,15 @@ func (u *ImageService) ImagePull(req dto.ImagePull) (string, error) { if err != nil { return "", err } - dockerLogDir := global.CONF.System.TmpDir + "/docker_logs" + dockerLogDir := path.Join(global.CONF.System.TmpDir, "/docker_logs") if _, err := os.Stat(dockerLogDir); err != nil && os.IsNotExist(err) { if err = os.MkdirAll(dockerLogDir, os.ModePerm); err != nil { return "", err } } imageItemName := strings.ReplaceAll(path.Base(req.ImageName), ":", "_") - pathItem := fmt.Sprintf("%s/image_pull_%s_%s.log", dockerLogDir, imageItemName, time.Now().Format("20060102150405")) - file, err := os.OpenFile(pathItem, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) + logItem := fmt.Sprintf("%s/image_pull_%s_%s.log", dockerLogDir, imageItemName, time.Now().Format("20060102150405")) + file, err := os.OpenFile(logItem, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) if err != nil { return "", err } @@ -224,7 +224,7 @@ func (u *ImageService) ImagePull(req dto.ImagePull) (string, error) { global.LOG.Infof("pull image %s successful!", req.ImageName) _, _ = io.Copy(file, out) }() - return pathItem, nil + return path.Base(logItem), nil } repo, err := imageRepoRepo.Get(commonRepo.WithByID(req.RepoID)) if err != nil { @@ -257,7 +257,7 @@ func (u *ImageService) ImagePull(req dto.ImagePull) (string, error) { _, _ = io.Copy(file, out) _, _ = file.WriteString("image pull successful!") }() - return pathItem, nil + return path.Base(logItem), nil } func (u *ImageService) ImageLoad(req dto.ImageLoad) error { @@ -354,8 +354,8 @@ func (u *ImageService) ImagePush(req dto.ImagePush) (string, error) { } } imageItemName := strings.ReplaceAll(path.Base(req.Name), ":", "_") - pathItem := fmt.Sprintf("%s/image_push_%s_%s.log", dockerLogDir, imageItemName, time.Now().Format("20060102150405")) - file, err := os.OpenFile(pathItem, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) + logItem := fmt.Sprintf("%s/image_push_%s_%s.log", dockerLogDir, imageItemName, time.Now().Format("20060102150405")) + file, err := os.OpenFile(logItem, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) if err != nil { return "", err } @@ -373,7 +373,7 @@ func (u *ImageService) ImagePush(req dto.ImagePush) (string, error) { _, _ = file.WriteString("image push successful!") }() - return pathItem, nil + return path.Base(logItem), nil } func (u *ImageService) ImageRemove(req dto.BatchDelete) error { diff --git a/backend/app/service/logs.go b/backend/app/service/logs.go index 60ab99fa2..f73cadf9b 100644 --- a/backend/app/service/logs.go +++ b/backend/app/service/logs.go @@ -1,9 +1,14 @@ package service import ( + "os" + "path" + "github.com/1Panel-dev/1Panel/backend/app/dto" "github.com/1Panel-dev/1Panel/backend/app/model" + "github.com/1Panel-dev/1Panel/backend/buserr" "github.com/1Panel-dev/1Panel/backend/constant" + "github.com/1Panel-dev/1Panel/backend/global" "github.com/1Panel-dev/1Panel/backend/utils/cmd" "github.com/jinzhu/copier" "github.com/pkg/errors" @@ -20,6 +25,8 @@ type ILogService interface { CreateOperationLog(operation model.OperationLog) error PageOperationLog(search dto.SearchOpLogWithPage) (int64, interface{}, error) + LoadSystemLog() (string, error) + CleanLogs(logtype string) error } @@ -74,6 +81,18 @@ func (u *LogService) PageOperationLog(req dto.SearchOpLogWithPage) (int64, inter return total, dtoOps, err } +func (u *LogService) LoadSystemLog() (string, error) { + filePath := path.Join(global.CONF.System.DataDir, "log/1Panel.log") + if _, err := os.Stat(filePath); err != nil { + return "", buserr.New("ErrHttpReqNotFound") + } + content, err := os.ReadFile(filePath) + if err != nil { + return "", err + } + return string(content), nil +} + func (u *LogService) CleanLogs(logtype string) error { if logtype == "operation" { return logRepo.CleanOperation() diff --git a/backend/app/service/snapshot.go b/backend/app/service/snapshot.go index ad6326b53..d175e986c 100644 --- a/backend/app/service/snapshot.go +++ b/backend/app/service/snapshot.go @@ -205,8 +205,8 @@ func (u *SnapshotService) SnapshotCreate(req dto.SnapshotCreate) error { global.LOG.Infof("start to upload snapshot to %s, please wait", backup.Type) _ = snapshotRepo.Update(snap.ID, map[string]interface{}{"status": constant.StatusUploading}) localPath := path.Join(localDir, fmt.Sprintf("system/1panel_%s_%s.tar.gz", versionItem.Value, timeNow)) - itemBackupPath := strings.TrimLeft(backup.BackupPath, "/") - itemBackupPath = strings.TrimRight(itemBackupPath, "/") + itemBackupPath := strings.TrimPrefix(backup.BackupPath, "/") + itemBackupPath = strings.TrimSuffix(itemBackupPath, "/") if ok, err := backupAccount.Upload(localPath, fmt.Sprintf("%s/system_snapshot/1panel_%s_%s.tar.gz", itemBackupPath, versionItem.Value, timeNow)); err != nil || !ok { _ = snapshotRepo.Update(snap.ID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()}) global.LOG.Errorf("upload snapshot to %s failed, err: %v", backup.Type, err) @@ -259,8 +259,8 @@ func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error { operation = "re-recover" } if !isReTry || snap.InterruptStep == "Download" || (isReTry && req.ReDownload) { - itemBackupPath := strings.TrimLeft(backup.BackupPath, "/") - itemBackupPath = strings.TrimRight(itemBackupPath, "/") + itemBackupPath := strings.TrimPrefix(backup.BackupPath, "/") + itemBackupPath = strings.TrimSuffix(itemBackupPath, "/") ok, err := client.Download(fmt.Sprintf("%s/system_snapshot/%s.tar.gz", itemBackupPath, snap.Name), fmt.Sprintf("%s/%s.tar.gz", baseDir, snap.Name)) if err != nil || !ok { if req.ReDownload { @@ -947,7 +947,10 @@ func (u *SnapshotService) handleTar(sourceDir, targetDir, name, exclusionRules s global.LOG.Debug(commands) stdout, err := cmd.ExecWithTimeOut(commands, 30*time.Minute) if err != nil { - global.LOG.Errorf("do handle tar failed, stdout: %s, err: %v", stdout, err) + if len(stdout) != 0 { + global.LOG.Errorf("do handle tar failed, stdout: %s, err: %v", stdout, err) + return fmt.Errorf("do handle tar failed, stdout: %s, err: %v", stdout, err) + } } return nil } @@ -963,7 +966,10 @@ func (u *SnapshotService) handleUnTar(sourceDir, targetDir string) error { global.LOG.Debug(commands) stdout, err := cmd.ExecWithTimeOut(commands, 30*time.Minute) if err != nil { - global.LOG.Errorf("do handle untar failed, stdout: %s, err: %v", stdout, err) + if len(stdout) != 0 { + global.LOG.Errorf("do handle untar failed, stdout: %s, err: %v", stdout, err) + return fmt.Errorf("do handle untar failed, stdout: %s, err: %v", stdout, err) + } } return nil } diff --git a/backend/app/service/ssh.go b/backend/app/service/ssh.go index 03c7e1f18..8cc2f9840 100644 --- a/backend/app/service/ssh.go +++ b/backend/app/service/ssh.go @@ -32,6 +32,8 @@ type ISSHService interface { GenerateSSH(req dto.GenerateSSH) error LoadSSHSecret(mode string) (string, error) LoadLog(req dto.SearchSSHLog) (*dto.SSHLog, error) + + LoadSSHConf() (string, error) } func NewISSHService() ISSHService { @@ -283,6 +285,17 @@ func (u *SSHService) LoadLog(req dto.SearchSSHLog) (*dto.SSHLog, error) { return &data, nil } +func (u *SSHService) LoadSSHConf() (string, error) { + if _, err := os.Stat("/etc/ssh/sshd_config"); err != nil { + return "", buserr.New("ErrHttpReqNotFound") + } + content, err := os.ReadFile("/etc/ssh/sshd_config") + if err != nil { + return "", err + } + return string(content), nil +} + func sortFileList(fileNames []sshFileItem) []sshFileItem { if len(fileNames) < 2 { return fileNames diff --git a/backend/init/migration/migrations/init.go b/backend/init/migration/migrations/init.go index 9f1c148ad..08bcad21a 100644 --- a/backend/init/migration/migrations/init.go +++ b/backend/init/migration/migrations/init.go @@ -493,7 +493,7 @@ var AddRemoteDB = &gormigrate.Migration{ appInstall model.AppInstall ) if err := global.DB.Where("key = ?", "mysql").First(&app).Error; err != nil { - return err + return nil } if err := global.DB.Where("app_id = ?", app.ID).First(&appInstall).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { diff --git a/backend/router/ro_container.go b/backend/router/ro_container.go index 1c8129ca1..62dce9ed7 100644 --- a/backend/router/ro_container.go +++ b/backend/router/ro_container.go @@ -28,6 +28,7 @@ func (s *ContainerRouter) InitContainerRouter(Router *gin.RouterGroup) { baRouter.GET("/search/log", baseApi.ContainerLogs) baRouter.GET("/limit", baseApi.LoadResouceLimit) baRouter.POST("/clean/log", baseApi.CleanContainerLog) + baRouter.POST("/load/log", baseApi.LoadContainerLog) baRouter.POST("/inspect", baseApi.Inspect) baRouter.POST("/operate", baseApi.ContainerOperation) baRouter.POST("/prune", baseApi.ContainerPrune) diff --git a/backend/router/ro_cronjob.go b/backend/router/ro_cronjob.go index a56ea390b..5dea0a45e 100644 --- a/backend/router/ro_cronjob.go +++ b/backend/router/ro_cronjob.go @@ -24,6 +24,7 @@ func (s *CronjobRouter) InitCronjobRouter(Router *gin.RouterGroup) { cmdRouter.POST("/download", baseApi.TargetDownload) cmdRouter.POST("/search", baseApi.SearchCronjob) cmdRouter.POST("/search/records", baseApi.SearchJobRecords) + cmdRouter.POST("/records/log", baseApi.LoadRecordLog) cmdRouter.POST("/records/clean", baseApi.CleanRecord) } } diff --git a/backend/router/ro_database.go b/backend/router/ro_database.go index 639bad3b0..cc56e5024 100644 --- a/backend/router/ro_database.go +++ b/backend/router/ro_database.go @@ -26,6 +26,7 @@ func (s *DatabaseRouter) InitDatabaseRouter(Router *gin.RouterGroup) { cmdRouter.POST("/variables/update", baseApi.UpdateMysqlVariables) cmdRouter.POST("/conffile/update", baseApi.UpdateMysqlConfByFile) cmdRouter.POST("/search", baseApi.SearchMysql) + cmdRouter.POST("/load/file", baseApi.LoadDatabaseFile) cmdRouter.GET("/variables", baseApi.LoadVariables) cmdRouter.GET("/status", baseApi.LoadStatus) cmdRouter.GET("/baseinfo", baseApi.LoadBaseinfo) diff --git a/backend/router/ro_file.go b/backend/router/ro_file.go index 60acbd713..fafa0fbc5 100644 --- a/backend/router/ro_file.go +++ b/backend/router/ro_file.go @@ -38,7 +38,5 @@ func (f *FileRouter) InitFileRouter(Router *gin.RouterGroup) { fileRouter.POST("/size", baseApi.Size) fileRouter.GET("/ws", baseApi.Ws) fileRouter.GET("/keys", baseApi.Keys) - fileRouter.POST("/loadfile", baseApi.LoadFromFile) } - } diff --git a/backend/router/ro_host.go b/backend/router/ro_host.go index 1fc329235..69b485f7f 100644 --- a/backend/router/ro_host.go +++ b/backend/router/ro_host.go @@ -34,6 +34,7 @@ func (s *HostRouter) InitHostRouter(Router *gin.RouterGroup) { hostRouter.POST("/firewall/update/port", baseApi.UpdatePortRule) hostRouter.POST("/firewall/update/addr", baseApi.UpdateAddrRule) + hostRouter.GET("/ssh/conf", baseApi.LoadSSHConf) hostRouter.POST("/ssh/search", baseApi.GetSSHInfo) hostRouter.POST("/ssh/update", baseApi.UpdateSSH) hostRouter.POST("/ssh/generate", baseApi.GenerateSSH) diff --git a/backend/router/ro_log.go b/backend/router/ro_log.go index b24b32d8b..2294748cb 100644 --- a/backend/router/ro_log.go +++ b/backend/router/ro_log.go @@ -17,5 +17,7 @@ func (s *LogRouter) InitLogRouter(Router *gin.RouterGroup) { operationRouter.POST("/login", baseApi.GetLoginLogs) operationRouter.POST("/operation", baseApi.GetOperationLogs) operationRouter.POST("/clean", baseApi.CleanLogs) + operationRouter.GET("/system", baseApi.GetSystemLogs) + } } diff --git a/backend/utils/mysql/client/local.go b/backend/utils/mysql/client/local.go index ead53ce51..28d5b574f 100644 --- a/backend/utils/mysql/client/local.go +++ b/backend/utils/mysql/client/local.go @@ -7,6 +7,7 @@ import ( "fmt" "os" "os/exec" + "path" "strings" "time" @@ -214,7 +215,7 @@ func (r *Local) Backup(info BackupInfo) error { return fmt.Errorf("mkdir %s failed, err: %v", info.TargetDir, err) } } - outfile, _ := os.OpenFile(info.FileName, os.O_RDWR|os.O_CREATE, 0755) + outfile, _ := os.OpenFile(path.Join(info.TargetDir, info.FileName), os.O_RDWR|os.O_CREATE, 0755) global.LOG.Infof("start to mysqldump | gzip > %s.gzip", info.TargetDir+"/"+info.FileName) cmd := exec.Command("docker", "exec", r.ContainerName, "mysqldump", "-uroot", "-p"+r.Password, info.Name) gzipCmd := exec.Command("gzip", "-cf") diff --git a/cmd/server/docs/docs.go b/cmd/server/docs/docs.go index 4c7bbbc98..b21f95181 100644 --- a/cmd/server/docs/docs.go +++ b/cmd/server/docs/docs.go @@ -1,5 +1,5 @@ -// Package docs GENERATED BY SWAG; DO NOT EDIT -// This file was generated by swaggo/swag +// Code generated by swaggo/swag. DO NOT EDIT. + package docs import "github.com/swaggo/swag" @@ -2005,6 +2005,39 @@ const docTemplate = `{ } } }, + "/containers/load/log": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取容器操作日志", + "consumes": [ + "application/json" + ], + "tags": [ + "Container" + ], + "summary": "Load container log", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.OperationWithNameAndType" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/containers/network": { "get": { "security": [ @@ -3058,6 +3091,39 @@ const docTemplate = `{ } } }, + "/cronjob/record/log": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取计划任务记录日志", + "consumes": [ + "application/json" + ], + "tags": [ + "Cronjob" + ], + "summary": "Load Cronjob record log", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.OperateByID" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/cronjobs": { "post": { "security": [ @@ -3925,6 +3991,39 @@ const docTemplate = `{ "responses": {} } }, + "/databases/load/file": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取数据库文件", + "consumes": [ + "application/json" + ], + "tags": [ + "Database" + ], + "summary": "Load Database file", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.OperationWithNameAndType" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/databases/options": { "get": { "security": [ @@ -5036,42 +5135,6 @@ const docTemplate = `{ } } }, - "/files/loadfile": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "读取文件", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Read file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.FilePath" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, "/files/mode": { "post": { "security": [ @@ -5748,6 +5811,25 @@ const docTemplate = `{ } } }, + "/host/ssh/conf": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取 ssh 配置文件", + "tags": [ + "SSH" + ], + "summary": "Load host ssh conf", + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/host/ssh/generate": { "post": { "security": [ @@ -6251,7 +6333,7 @@ const docTemplate = `{ "bodyKeys": [ "operate" ], - "formatEN": "[operate] [operate] Supervisor 进程文件", + "formatEN": "[operate] Supervisor Process Config file", "formatZH": "[operate] Supervisor 进程文件 ", "paramKeys": [] } @@ -7188,6 +7270,25 @@ const docTemplate = `{ } } }, + "/logs/system": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取系统日志", + "tags": [ + "Logs" + ], + "summary": "Load system logs", + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/openResty": { "get": { "security": [ @@ -13291,6 +13392,21 @@ const docTemplate = `{ } } }, + "dto.OperationWithNameAndType": { + "type": "object", + "required": [ + "name", + "type" + ], + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + } + } + }, "dto.Options": { "type": "object", "properties": { @@ -15773,7 +15889,8 @@ const docTemplate = `{ "type": "string", "enum": [ "out.log", - "err.log" + "err.log", + "config" ] }, "name": { diff --git a/cmd/server/docs/swagger.json b/cmd/server/docs/swagger.json index c21a9bea9..011aaccd7 100644 --- a/cmd/server/docs/swagger.json +++ b/cmd/server/docs/swagger.json @@ -1998,6 +1998,39 @@ } } }, + "/containers/load/log": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取容器操作日志", + "consumes": [ + "application/json" + ], + "tags": [ + "Container" + ], + "summary": "Load container log", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.OperationWithNameAndType" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/containers/network": { "get": { "security": [ @@ -3051,6 +3084,39 @@ } } }, + "/cronjob/record/log": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取计划任务记录日志", + "consumes": [ + "application/json" + ], + "tags": [ + "Cronjob" + ], + "summary": "Load Cronjob record log", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.OperateByID" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/cronjobs": { "post": { "security": [ @@ -3918,6 +3984,39 @@ "responses": {} } }, + "/databases/load/file": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取数据库文件", + "consumes": [ + "application/json" + ], + "tags": [ + "Database" + ], + "summary": "Load Database file", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.OperationWithNameAndType" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/databases/options": { "get": { "security": [ @@ -5029,42 +5128,6 @@ } } }, - "/files/loadfile": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "读取文件", - "consumes": [ - "application/json" - ], - "tags": [ - "File" - ], - "summary": "Read file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.FilePath" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, "/files/mode": { "post": { "security": [ @@ -5741,6 +5804,25 @@ } } }, + "/host/ssh/conf": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取 ssh 配置文件", + "tags": [ + "SSH" + ], + "summary": "Load host ssh conf", + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/host/ssh/generate": { "post": { "security": [ @@ -6244,7 +6326,7 @@ "bodyKeys": [ "operate" ], - "formatEN": "[operate] [operate] Supervisor 进程文件", + "formatEN": "[operate] Supervisor Process Config file", "formatZH": "[operate] Supervisor 进程文件 ", "paramKeys": [] } @@ -7181,6 +7263,25 @@ } } }, + "/logs/system": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取系统日志", + "tags": [ + "Logs" + ], + "summary": "Load system logs", + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/openResty": { "get": { "security": [ @@ -13284,6 +13385,21 @@ } } }, + "dto.OperationWithNameAndType": { + "type": "object", + "required": [ + "name", + "type" + ], + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + } + } + }, "dto.Options": { "type": "object", "properties": { @@ -15766,7 +15882,8 @@ "type": "string", "enum": [ "out.log", - "err.log" + "err.log", + "config" ] }, "name": { diff --git a/cmd/server/docs/swagger.yaml b/cmd/server/docs/swagger.yaml index 43e57b94d..6589381e9 100644 --- a/cmd/server/docs/swagger.yaml +++ b/cmd/server/docs/swagger.yaml @@ -1332,6 +1332,16 @@ definitions: required: - name type: object + dto.OperationWithNameAndType: + properties: + name: + type: string + type: + type: string + required: + - name + - type + type: object dto.Options: properties: option: @@ -2986,6 +2996,7 @@ definitions: enum: - out.log - err.log + - config type: string name: type: string @@ -5112,6 +5123,26 @@ paths: security: - ApiKeyAuth: [] summary: Load container stats + /containers/load/log: + post: + consumes: + - application/json + description: 获取容器操作日志 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.OperationWithNameAndType' + responses: + "200": + description: OK + security: + - ApiKeyAuth: [] + summary: Load container log + tags: + - Container /containers/network: get: consumes: @@ -5781,6 +5812,26 @@ paths: summary: Page volumes tags: - Container Volume + /cronjob/record/log: + post: + consumes: + - application/json + description: 获取计划任务记录日志 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.OperateByID' + responses: + "200": + description: OK + security: + - ApiKeyAuth: [] + summary: Load Cronjob record log + tags: + - Cronjob /cronjobs: post: consumes: @@ -6336,6 +6387,26 @@ paths: summary: Load mysql database from remote tags: - Database Mysql + /databases/load/file: + post: + consumes: + - application/json + description: 获取数据库文件 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.OperationWithNameAndType' + responses: + "200": + description: OK + security: + - ApiKeyAuth: [] + summary: Load Database file + tags: + - Database /databases/options: get: consumes: @@ -7038,28 +7109,6 @@ paths: formatEN: Download file [path] formatZH: 下载文件 [path] paramKeys: [] - /files/loadfile: - post: - consumes: - - application/json - description: 读取文件 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.FilePath' - responses: - "200": - description: OK - schema: - type: string - security: - - ApiKeyAuth: [] - summary: Read file - tags: - - File /files/mode: post: consumes: @@ -7495,6 +7544,17 @@ paths: formatEN: update SSH conf formatZH: 修改 SSH 配置文件 paramKeys: [] + /host/ssh/conf: + get: + description: 获取 ssh 配置文件 + responses: + "200": + description: OK + security: + - ApiKeyAuth: [] + summary: Load host ssh conf + tags: + - SSH /host/ssh/generate: post: consumes: @@ -7814,7 +7874,7 @@ paths: BeforeFuntions: [] bodyKeys: - operate - formatEN: '[operate] [operate] Supervisor 进程文件' + formatEN: '[operate] Supervisor Process Config file' formatZH: '[operate] Supervisor 进程文件 ' paramKeys: [] /hosts: @@ -8404,6 +8464,17 @@ paths: summary: Page operation logs tags: - Logs + /logs/system: + get: + description: 获取系统日志 + responses: + "200": + description: OK + security: + - ApiKeyAuth: [] + summary: Load system logs + tags: + - Logs /openResty: get: description: 获取 OpenResty 配置信息 diff --git a/frontend/src/api/modules/container.ts b/frontend/src/api/modules/container.ts index bd5700b5b..4e0798219 100644 --- a/frontend/src/api/modules/container.ts +++ b/frontend/src/api/modules/container.ts @@ -26,6 +26,9 @@ export const loadContainerInfo = (name: string) => { export const cleanContainerLog = (containerName: string) => { return http.post(`/containers/clean/log`, { name: containerName }); }; +export const loadContainerLog = (type: string, name: string) => { + return http.post(`/containers/load/log`, { type: type, name: name }); +}; export const containerListStats = () => { return http.get>(`/containers/list/stats`); }; diff --git a/frontend/src/api/modules/cronjob.ts b/frontend/src/api/modules/cronjob.ts index 29303ec02..da99dc4ba 100644 --- a/frontend/src/api/modules/cronjob.ts +++ b/frontend/src/api/modules/cronjob.ts @@ -6,6 +6,10 @@ export const getCronjobPage = (params: SearchWithPage) => { return http.post>(`/cronjobs/search`, params); }; +export const getRecordLog = (id: number) => { + return http.post(`/cronjobs/records/log`, { id: id }); +}; + export const addCronjob = (params: Cronjob.CronjobCreate) => { return http.post(`/cronjobs`, params); }; diff --git a/frontend/src/api/modules/database.ts b/frontend/src/api/modules/database.ts index 16b875682..6070968d5 100644 --- a/frontend/src/api/modules/database.ts +++ b/frontend/src/api/modules/database.ts @@ -7,6 +7,9 @@ import { Database } from '../interface/database'; export const searchMysqlDBs = (params: Database.SearchDBWithPage) => { return http.post>(`/databases/search`, params); }; +export const loadDatabaseFile = (type: string, name: string) => { + return http.post(`/databases/load/file`, { type: type, name: name }); +}; export const addMysqlDB = (params: Database.MysqlDBCreate) => { let reqest = deepCopy(params) as Database.MysqlDBCreate; diff --git a/frontend/src/api/modules/files.ts b/frontend/src/api/modules/files.ts index 3aed29fe7..81a5baa17 100644 --- a/frontend/src/api/modules/files.ts +++ b/frontend/src/api/modules/files.ts @@ -31,10 +31,6 @@ export const ChangeFileMode = (form: File.FileCreate) => { return http.post('files/mode', form); }; -export const LoadFile = (form: File.FilePath) => { - return http.post('files/loadfile', form); -}; - export const CompressFile = (form: File.FileCompress) => { return http.post('files/compress', form); }; diff --git a/frontend/src/api/modules/host.ts b/frontend/src/api/modules/host.ts index 6dfa0a0b2..3a9dbd73a 100644 --- a/frontend/src/api/modules/host.ts +++ b/frontend/src/api/modules/host.ts @@ -98,6 +98,9 @@ export const batchOperateRule = (params: Host.BatchRule) => { export const getSSHInfo = () => { return http.post(`/hosts/ssh/search`); }; +export const getSSHConf = () => { + return http.get(`/hosts/ssh/conf`); +}; export const operateSSH = (operation: string) => { return http.post(`/hosts/ssh/operate`, { operation: operation }); }; diff --git a/frontend/src/api/modules/log.ts b/frontend/src/api/modules/log.ts index 8cc8a9998..16ec77055 100644 --- a/frontend/src/api/modules/log.ts +++ b/frontend/src/api/modules/log.ts @@ -10,6 +10,10 @@ export const getLoginLogs = (info: Log.SearchLgLog) => { return http.post>(`/logs/login`, info); }; +export const getSystemLogs = () => { + return http.get(`/logs/system`); +}; + export const cleanLogs = (param: Log.CleanLog) => { return http.post(`/logs/clean`, param); }; diff --git a/frontend/src/components/backup/index.vue b/frontend/src/components/backup/index.vue index 657a7c706..06728b235 100644 --- a/frontend/src/components/backup/index.vue +++ b/frontend/src/components/backup/index.vue @@ -57,7 +57,6 @@ import DrawerHeader from '@/components/drawer-header/index.vue'; import { deleteBackupRecord, downloadBackupRecord, searchBackupRecords } from '@/api/modules/setting'; import { Backup } from '@/api/interface/backup'; import { MsgSuccess } from '@/utils/message'; -// import { DownloadByPath } from '@/api/modules/files'; const selects = ref([]); const loading = ref(); diff --git a/frontend/src/views/container/compose/create/index.vue b/frontend/src/views/container/compose/create/index.vue index 7aedbb9e5..7ef3b8286 100644 --- a/frontend/src/views/container/compose/create/index.vue +++ b/frontend/src/views/container/compose/create/index.vue @@ -122,9 +122,8 @@ import { Rules } from '@/global/form-rules'; import i18n from '@/lang'; import { ElForm, ElMessageBox } from 'element-plus'; import DrawerHeader from '@/components/drawer-header/index.vue'; -import { listComposeTemplate, testCompose, upCompose } from '@/api/modules/container'; +import { listComposeTemplate, loadContainerLog, testCompose, upCompose } from '@/api/modules/container'; import { loadBaseDir } from '@/api/modules/setting'; -import { LoadFile } from '@/api/modules/files'; import { formatImageStdout } from '@/utils/docker'; import { MsgError } from '@/utils/message'; @@ -268,9 +267,9 @@ const onSubmit = async (formEl: FormInstance | undefined) => { }); }; -const loadLogs = async (path: string) => { +const loadLogs = async (name: string) => { timer = setInterval(async () => { - const res = await LoadFile({ path: path }); + const res = await loadContainerLog('compose-create', name); logInfo.value = formatImageStdout(res.data); nextTick(() => { const state = view.value.state; diff --git a/frontend/src/views/container/compose/index.vue b/frontend/src/views/container/compose/index.vue index b86dc41ca..ce4300f6a 100644 --- a/frontend/src/views/container/compose/index.vue +++ b/frontend/src/views/container/compose/index.vue @@ -98,10 +98,9 @@ import EditDialog from '@/views/container/compose/edit/index.vue'; import CreateDialog from '@/views/container/compose/create/index.vue'; import DeleteDialog from '@/views/container/compose/delete/index.vue'; import ComposeDetial from '@/views/container/compose/detail/index.vue'; -import { loadDockerStatus, searchCompose } from '@/api/modules/container'; +import { loadContainerLog, loadDockerStatus, searchCompose } from '@/api/modules/container'; import i18n from '@/lang'; import { Container } from '@/api/interface/container'; -import { LoadFile } from '@/api/modules/files'; import { loadBaseDir } from '@/api/modules/setting'; import router from '@/routers'; @@ -198,7 +197,7 @@ const onDelete = async (row: Container.ComposeInfo) => { const dialogEditRef = ref(); const onEdit = async (row: Container.ComposeInfo) => { - const res = await LoadFile({ path: row.path }); + const res = await loadContainerLog('compose-detail', row.name); let params = { name: row.name, path: row.path, diff --git a/frontend/src/views/container/image/build/index.vue b/frontend/src/views/container/image/build/index.vue index ad9219b90..cc49bedb0 100644 --- a/frontend/src/views/container/image/build/index.vue +++ b/frontend/src/views/container/image/build/index.vue @@ -93,8 +93,7 @@ import { nextTick, onBeforeUnmount, reactive, ref, shallowRef } from 'vue'; import { Rules } from '@/global/form-rules'; import i18n from '@/lang'; import { ElForm, ElMessage } from 'element-plus'; -import { imageBuild } from '@/api/modules/container'; -import { LoadFile } from '@/api/modules/files'; +import { imageBuild, loadContainerLog } from '@/api/modules/container'; import { formatImageStdout } from '@/utils/docker'; import DrawerHeader from '@/components/drawer-header/index.vue'; @@ -163,7 +162,7 @@ const onSubmit = async (formEl: FormInstance | undefined) => { const loadLogs = async (path: string) => { timer = setInterval(async () => { if (logVisiable.value) { - const res = await LoadFile({ path: path }); + const res = await loadContainerLog('image-build', path); logInfo.value = formatImageStdout(res.data); nextTick(() => { const state = view.value.state; diff --git a/frontend/src/views/container/image/pull/index.vue b/frontend/src/views/container/image/pull/index.vue index 479fb5eae..cb3060e4c 100644 --- a/frontend/src/views/container/image/pull/index.vue +++ b/frontend/src/views/container/image/pull/index.vue @@ -68,12 +68,11 @@ import { nextTick, onBeforeUnmount, reactive, ref, shallowRef } from 'vue'; import { Rules } from '@/global/form-rules'; import i18n from '@/lang'; import { ElForm } from 'element-plus'; -import { imagePull } from '@/api/modules/container'; +import { imagePull, loadContainerLog } from '@/api/modules/container'; import { Container } from '@/api/interface/container'; import { Codemirror } from 'vue-codemirror'; import { javascript } from '@codemirror/lang-javascript'; import { oneDark } from '@codemirror/theme-one-dark'; -import { LoadFile } from '@/api/modules/files'; import DrawerHeader from '@/components/drawer-header/index.vue'; import { formatImageStdout } from '@/utils/docker'; import { MsgSuccess } from '@/utils/message'; @@ -133,7 +132,7 @@ const onSubmit = async (formEl: FormInstance | undefined) => { const loadLogs = async (path: string) => { timer = setInterval(async () => { if (logVisiable.value) { - const res = await LoadFile({ path: path }); + const res = await loadContainerLog('image-pull', path); logInfo.value = formatImageStdout(res.data); nextTick(() => { const state = view.value.state; diff --git a/frontend/src/views/container/image/push/index.vue b/frontend/src/views/container/image/push/index.vue index 042395439..327c10b5b 100644 --- a/frontend/src/views/container/image/push/index.vue +++ b/frontend/src/views/container/image/push/index.vue @@ -71,12 +71,11 @@ import { nextTick, onBeforeUnmount, reactive, ref, shallowRef } from 'vue'; import { Rules } from '@/global/form-rules'; import i18n from '@/lang'; import { ElForm } from 'element-plus'; -import { imagePush } from '@/api/modules/container'; +import { imagePush, loadContainerLog } from '@/api/modules/container'; import { Container } from '@/api/interface/container'; import { Codemirror } from 'vue-codemirror'; import { javascript } from '@codemirror/lang-javascript'; import { oneDark } from '@codemirror/theme-one-dark'; -import { LoadFile } from '@/api/modules/files'; import DrawerHeader from '@/components/drawer-header/index.vue'; import { formatImageStdout } from '@/utils/docker'; import { MsgSuccess } from '@/utils/message'; @@ -138,7 +137,7 @@ const onSubmit = async (formEl: FormInstance | undefined) => { const loadLogs = async (path: string) => { timer = setInterval(async () => { if (logVisiable.value) { - const res = await LoadFile({ path: path }); + const res = await loadContainerLog('image-push', path); logInfo.value = formatImageStdout(res.data); nextTick(() => { const state = view.value.state; diff --git a/frontend/src/views/cronjob/record/index.vue b/frontend/src/views/cronjob/record/index.vue index 2c9732e2b..75cec26ee 100644 --- a/frontend/src/views/cronjob/record/index.vue +++ b/frontend/src/views/cronjob/record/index.vue @@ -358,11 +358,11 @@ import { onBeforeUnmount, reactive, ref } from 'vue'; import { Cronjob } from '@/api/interface/cronjob'; import { loadZero } from '@/utils/util'; -import { searchRecords, download, handleOnce, updateStatus, cleanRecords } from '@/api/modules/cronjob'; +import { searchRecords, download, handleOnce, updateStatus, cleanRecords, getRecordLog } from '@/api/modules/cronjob'; import { dateFormat } from '@/utils/util'; import i18n from '@/lang'; import { ElMessageBox } from 'element-plus'; -import { DownloadByPath, LoadFile } from '@/api/modules/files'; +import { DownloadByPath } from '@/api/modules/files'; import { Codemirror } from 'vue-codemirror'; import { javascript } from '@codemirror/lang-javascript'; import { oneDark } from '@codemirror/theme-one-dark'; @@ -587,7 +587,7 @@ const loadRecord = async (row: Cronjob.Record) => { return; } if (row.records) { - const res = await LoadFile({ path: row.records }); + const res = await getRecordLog(row.id); currentRecordDetail.value = res.data; } }; diff --git a/frontend/src/views/database/mysql/setting/index.vue b/frontend/src/views/database/mysql/setting/index.vue index 8314fb4f5..e844717fa 100644 --- a/frontend/src/views/database/mysql/setting/index.vue +++ b/frontend/src/views/database/mysql/setting/index.vue @@ -119,17 +119,14 @@ import { reactive, ref } from 'vue'; import { Codemirror } from 'vue-codemirror'; import { javascript } from '@codemirror/lang-javascript'; import { oneDark } from '@codemirror/theme-one-dark'; -import { LoadFile } from '@/api/modules/files'; -import { loadMysqlBaseInfo, loadMysqlVariables, updateMysqlConfByFile } from '@/api/modules/database'; +import { loadDatabaseFile, loadMysqlBaseInfo, loadMysqlVariables, updateMysqlConfByFile } from '@/api/modules/database'; import { ChangePort, GetAppDefaultConfig } from '@/api/modules/app'; import { Rules } from '@/global/form-rules'; import i18n from '@/lang'; -import { loadBaseDir } from '@/api/modules/setting'; import { MsgSuccess } from '@/utils/message'; const loading = ref(false); -const baseDir = ref(); const extensions = [javascript(), oneDark]; const activeName = ref('conf'); @@ -179,8 +176,7 @@ const onClose = (): void => { const jumpToConf = async () => { activeName.value = 'conf'; - const pathRes = await loadBaseDir(); - loadMysqlConf(`${pathRes.data}/apps/mysql/${mysqlName.value}/conf/my.cnf`); + loadMysqlConf(); }; const jumpToSlowlog = async () => { @@ -271,9 +267,7 @@ const loadBaseInfo = async () => { mysqlName.value = res.data?.name; baseInfo.port = res.data?.port; baseInfo.containerID = res.data?.containerName; - const pathRes = await loadBaseDir(); - baseDir.value = pathRes.data; - loadMysqlConf(`${pathRes.data}/apps/mysql/${mysqlName.value}/conf/my.cnf`); + loadMysqlConf(); loadContainerLog(baseInfo.containerID); }; @@ -302,9 +296,9 @@ const loadSlowLogs = async () => { slowLogRef.value!.acceptParams(param); }; -const loadMysqlConf = async (path: string) => { +const loadMysqlConf = async () => { useOld.value = false; - const res = await LoadFile({ path: path }); + const res = await loadDatabaseFile('mysql-conf', mysqlName.value); loading.value = false; mysqlConf.value = res.data; }; diff --git a/frontend/src/views/database/mysql/setting/slow-log/index.vue b/frontend/src/views/database/mysql/setting/slow-log/index.vue index 578794347..ae39c7b56 100644 --- a/frontend/src/views/database/mysql/setting/slow-log/index.vue +++ b/frontend/src/views/database/mysql/setting/slow-log/index.vue @@ -51,12 +51,10 @@ import { javascript } from '@codemirror/lang-javascript'; import { oneDark } from '@codemirror/theme-one-dark'; import { nextTick, onBeforeUnmount, reactive, ref, shallowRef } from 'vue'; import { Database } from '@/api/interface/database'; -import { LoadFile } from '@/api/modules/files'; import ConfirmDialog from '@/components/confirm-dialog/index.vue'; -import { updateMysqlVariables } from '@/api/modules/database'; +import { loadDatabaseFile, updateMysqlVariables } from '@/api/modules/database'; import { dateFormatForName, downloadWithContent } from '@/utils/util'; import i18n from '@/lang'; -import { loadBaseDir } from '@/api/modules/setting'; import { MsgError, MsgInfo, MsgSuccess } from '@/utils/message'; const extensions = [javascript(), oneDark]; @@ -91,12 +89,10 @@ const acceptParams = async (params: DialogProps): Promise => { if (variables.slow_query_log === 'ON') { currentStatus.value = true; detailShow.value = true; - const pathRes = await loadBaseDir(); - let path = `${pathRes.data}/apps/mysql/${mysqlName.value}/data/1Panel-slow.log`; - loadMysqlSlowlogs(path); + loadMysqlSlowlogs(); timer = setInterval(() => { if (variables.slow_query_log === 'ON' && isWatch.value) { - loadMysqlSlowlogs(path); + loadMysqlSlowlogs(); } }, 1000 * 5); } else { @@ -168,8 +164,8 @@ const onDownload = async () => { downloadWithContent(slowLogs.value, mysqlName.value + '-slowlogs-' + dateFormatForName(new Date()) + '.log'); }; -const loadMysqlSlowlogs = async (path: string) => { - const res = await LoadFile({ path: path }); +const loadMysqlSlowlogs = async () => { + const res = await loadDatabaseFile('slow-logs', mysqlName.value); slowLogs.value = res.data || ''; nextTick(() => { const state = view.value.state; diff --git a/frontend/src/views/database/redis/setting/index.vue b/frontend/src/views/database/redis/setting/index.vue index e608e40fb..39aebded3 100644 --- a/frontend/src/views/database/redis/setting/index.vue +++ b/frontend/src/views/database/redis/setting/index.vue @@ -132,15 +132,13 @@ import { nextTick, reactive, ref, shallowRef } from 'vue'; import { Codemirror } from 'vue-codemirror'; import { javascript } from '@codemirror/lang-javascript'; import { oneDark } from '@codemirror/theme-one-dark'; -import { LoadFile } from '@/api/modules/files'; import ConfirmDialog from '@/components/confirm-dialog/index.vue'; import Status from '@/views/database/redis/setting/status/index.vue'; import Persistence from '@/views/database/redis/setting/persistence/index.vue'; -import { loadRedisConf, updateRedisConf, updateRedisConfByFile } from '@/api/modules/database'; +import { loadDatabaseFile, loadRedisConf, updateRedisConf, updateRedisConfByFile } from '@/api/modules/database'; import i18n from '@/lang'; import { checkNumberRange, Rules } from '@/global/form-rules'; import { ChangePort, GetAppDefaultConfig } from '@/api/modules/app'; -import { loadBaseDir } from '@/api/modules/setting'; import { MsgSuccess } from '@/utils/message'; const extensions = [javascript(), oneDark]; @@ -335,11 +333,9 @@ const loadform = async () => { }; const loadConfFile = async () => { - const pathRes = await loadBaseDir(); - let path = `${pathRes.data}/apps/redis/${redisName.value}/conf/redis.conf`; useOld.value = false; loading.value = true; - await LoadFile({ path: path }) + await loadDatabaseFile('redis-conf', redisName.value) .then((res) => { loading.value = false; redisConf.value = res.data; diff --git a/frontend/src/views/host/ssh/ssh/index.vue b/frontend/src/views/host/ssh/ssh/index.vue index fdf12a196..c0d4e5631 100644 --- a/frontend/src/views/host/ssh/ssh/index.vue +++ b/frontend/src/views/host/ssh/ssh/index.vue @@ -158,8 +158,7 @@ import Port from '@/views/host/ssh/ssh/port/index.vue'; import Address from '@/views/host/ssh/ssh/address/index.vue'; import i18n from '@/lang'; import { MsgSuccess } from '@/utils/message'; -import { getSSHInfo, operateSSH, updateSSH, updateSSHByfile } from '@/api/modules/host'; -import { LoadFile } from '@/api/modules/files'; +import { getSSHConf, getSSHInfo, operateSSH, updateSSH, updateSSHByfile } from '@/api/modules/host'; import { ElMessageBox, FormInstance } from 'element-plus'; const loading = ref(false); @@ -289,7 +288,7 @@ const changei18n = (value: string) => { }; const loadSSHConf = async () => { - const res = await LoadFile({ path: '/etc/ssh/sshd_config' }); + const res = await getSSHConf(); sshConf.value = res.data || ''; }; diff --git a/frontend/src/views/log/system/index.vue b/frontend/src/views/log/system/index.vue index b8b2e5fb0..6e2961cc0 100644 --- a/frontend/src/views/log/system/index.vue +++ b/frontend/src/views/log/system/index.vue @@ -42,9 +42,8 @@ import { Codemirror } from 'vue-codemirror'; import { javascript } from '@codemirror/lang-javascript'; import { oneDark } from '@codemirror/theme-one-dark'; import { nextTick, onMounted, ref, shallowRef } from 'vue'; -import { LoadFile } from '@/api/modules/files'; -import { loadBaseDir } from '@/api/modules/setting'; import { useRouter } from 'vue-router'; +import { getSystemLogs } from '@/api/modules/log'; const router = useRouter(); const loading = ref(); @@ -56,9 +55,7 @@ const handleReady = (payload) => { }; const loadSystemlogs = async () => { - const pathRes = await loadBaseDir(); - let logPath = pathRes.data + '/log'; - await LoadFile({ path: `${logPath}/1Panel.log` }) + await getSystemLogs() .then((res) => { loading.value = false; logs.value = res.data;