mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-31 14:08:06 +08:00
fix: 解决打开越权读取文件的问题 (#1810)
This commit is contained in:
parent
01d5bd047f
commit
6f6c836d9a
@ -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 容器操作
|
||||
|
@ -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 清空计划任务记录
|
||||
|
@ -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 远程访问权限
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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()
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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": {
|
||||
|
@ -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": {
|
||||
|
@ -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 配置信息
|
||||
|
@ -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<string>(`/containers/load/log`, { type: type, name: name });
|
||||
};
|
||||
export const containerListStats = () => {
|
||||
return http.get<Array<Container.ContainerListStats>>(`/containers/list/stats`);
|
||||
};
|
||||
|
@ -6,6 +6,10 @@ export const getCronjobPage = (params: SearchWithPage) => {
|
||||
return http.post<ResPage<Cronjob.CronjobInfo>>(`/cronjobs/search`, params);
|
||||
};
|
||||
|
||||
export const getRecordLog = (id: number) => {
|
||||
return http.post<string>(`/cronjobs/records/log`, { id: id });
|
||||
};
|
||||
|
||||
export const addCronjob = (params: Cronjob.CronjobCreate) => {
|
||||
return http.post<Cronjob.CronjobCreate>(`/cronjobs`, params);
|
||||
};
|
||||
|
@ -7,6 +7,9 @@ import { Database } from '../interface/database';
|
||||
export const searchMysqlDBs = (params: Database.SearchDBWithPage) => {
|
||||
return http.post<ResPage<Database.MysqlDBInfo>>(`/databases/search`, params);
|
||||
};
|
||||
export const loadDatabaseFile = (type: string, name: string) => {
|
||||
return http.post<string>(`/databases/load/file`, { type: type, name: name });
|
||||
};
|
||||
|
||||
export const addMysqlDB = (params: Database.MysqlDBCreate) => {
|
||||
let reqest = deepCopy(params) as Database.MysqlDBCreate;
|
||||
|
@ -31,10 +31,6 @@ export const ChangeFileMode = (form: File.FileCreate) => {
|
||||
return http.post<File.File>('files/mode', form);
|
||||
};
|
||||
|
||||
export const LoadFile = (form: File.FilePath) => {
|
||||
return http.post<string>('files/loadfile', form);
|
||||
};
|
||||
|
||||
export const CompressFile = (form: File.FileCompress) => {
|
||||
return http.post<File.File>('files/compress', form);
|
||||
};
|
||||
|
@ -98,6 +98,9 @@ export const batchOperateRule = (params: Host.BatchRule) => {
|
||||
export const getSSHInfo = () => {
|
||||
return http.post<Host.SSHInfo>(`/hosts/ssh/search`);
|
||||
};
|
||||
export const getSSHConf = () => {
|
||||
return http.get<string>(`/hosts/ssh/conf`);
|
||||
};
|
||||
export const operateSSH = (operation: string) => {
|
||||
return http.post(`/hosts/ssh/operate`, { operation: operation });
|
||||
};
|
||||
|
@ -10,6 +10,10 @@ export const getLoginLogs = (info: Log.SearchLgLog) => {
|
||||
return http.post<ResPage<Log.OperationLog>>(`/logs/login`, info);
|
||||
};
|
||||
|
||||
export const getSystemLogs = () => {
|
||||
return http.get<string>(`/logs/system`);
|
||||
};
|
||||
|
||||
export const cleanLogs = (param: Log.CleanLog) => {
|
||||
return http.post(`/logs/clean`, param);
|
||||
};
|
||||
|
@ -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<any>([]);
|
||||
const loading = ref();
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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<void> => {
|
||||
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;
|
||||
|
@ -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;
|
||||
|
@ -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 || '';
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user