From e1635aa39d2c50234bd5bb29ba3ce180862c6169 Mon Sep 17 00:00:00 2001 From: ssongliu <73214554+ssongliu@users.noreply.github.com> Date: Fri, 9 May 2025 15:55:48 +0800 Subject: [PATCH] fix: Modify the execution mode of the planned tasks (#8580) --- agent/app/api/v2/snapshot.go | 2 +- agent/app/repo/cronjob.go | 4 +- agent/app/service/backup_app.go | 78 +++---- agent/app/service/backup_mysql.go | 56 ++--- agent/app/service/backup_postgresql.go | 46 ++-- agent/app/service/backup_website.go | 141 ++++++------ agent/app/service/cronjob.go | 22 -- agent/app/service/cronjob_backup.go | 294 ++++++++++++++----------- agent/app/service/cronjob_helper.go | 221 ++++++++----------- agent/app/service/device_clean.go | 8 +- agent/app/service/snapshot.go | 3 +- agent/app/service/snapshot_create.go | 60 ++--- agent/app/task/task.go | 7 + agent/i18n/lang/en.yaml | 4 +- agent/i18n/lang/ja.yaml | 4 +- agent/i18n/lang/ko.yaml | 4 +- agent/i18n/lang/ms.yaml | 4 +- agent/i18n/lang/pt-BR.yaml | 4 +- agent/i18n/lang/ru.yaml | 4 +- agent/i18n/lang/zh-Hant.yaml | 4 +- agent/i18n/lang/zh.yaml | 4 +- agent/utils/files/file_op.go | 2 +- 22 files changed, 484 insertions(+), 492 deletions(-) diff --git a/agent/app/api/v2/snapshot.go b/agent/app/api/v2/snapshot.go index ae9a78f58..83b90b41e 100644 --- a/agent/app/api/v2/snapshot.go +++ b/agent/app/api/v2/snapshot.go @@ -36,7 +36,7 @@ func (b *BaseApi) CreateSnapshot(c *gin.Context) { return } - if err := snapshotService.SnapshotCreate(req, 0); err != nil { + if err := snapshotService.SnapshotCreate(nil, req, 0, 0, 0); err != nil { helper.InternalServer(c, err) return } diff --git a/agent/app/repo/cronjob.go b/agent/app/repo/cronjob.go index 06aaa8bcf..58405b282 100644 --- a/agent/app/repo/cronjob.go +++ b/agent/app/repo/cronjob.go @@ -147,9 +147,7 @@ func (u *CronjobRepo) StartRecords(cronjobID uint, targetPath, cronjobType strin var record model.JobRecords record.StartTime = time.Now() record.CronjobID = cronjobID - if cronjobType != "directory" && cronjobType != "log" && cronjobType != "cutWebsiteLog" { - record.TaskID = uuid.New().String() - } + record.TaskID = uuid.New().String() record.Status = constant.StatusWaiting if err := global.DB.Create(&record).Error; err != nil { global.LOG.Errorf("create record status failed, err: %v", err) diff --git a/agent/app/service/backup_app.go b/agent/app/service/backup_app.go index 8d5e3d15f..026e806e7 100644 --- a/agent/app/service/backup_app.go +++ b/agent/app/service/backup_app.go @@ -143,45 +143,10 @@ func handleAppBackup(install *model.AppInstall, parentTask *task.Task, backupDir } } - backupApp := func(t *task.Task) error { - fileOp := files.NewFileOp() - tmpDir := fmt.Sprintf("%s/%s", backupDir, strings.ReplaceAll(fileName, ".tar.gz", "")) - if !fileOp.Stat(tmpDir) { - if err := os.MkdirAll(tmpDir, os.ModePerm); err != nil { - return fmt.Errorf("mkdir %s failed, err: %v", backupDir, err) - } - } - defer func() { - _ = os.RemoveAll(tmpDir) - }() - - remarkInfo, _ := json.Marshal(install) - remarkInfoPath := fmt.Sprintf("%s/app.json", tmpDir) - if err := fileOp.SaveFile(remarkInfoPath, string(remarkInfo), fs.ModePerm); err != nil { - return err - } - - appPath := install.GetPath() - if err := fileOp.TarGzCompressPro(true, appPath, path.Join(tmpDir, "app.tar.gz"), "", excludes); err != nil { - return err - } - - resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithAppInstallId(install.ID)) - for _, resource := range resources { - if err = backupDatabaseWithTask(t, resource.Key, tmpDir, install.Name, resource.ResourceId); err != nil { - return err - } - } - t.LogStart(i18n.GetMsgByKey("CompressDir")) - if err := fileOp.TarGzCompressPro(true, tmpDir, path.Join(backupDir, fileName), secret, ""); err != nil { - return err - } - t.Log(i18n.GetWithName("CompressFileSuccess", fileName)) - return nil - } - backupTask.AddSubTask(task.GetTaskName(install.Name, task.TaskBackup, task.TaskScopeApp), backupApp, nil) + itemHandler := doAppBackup(install, backupTask, backupDir, fileName, excludes, secret) + backupTask.AddSubTask(task.GetTaskName(install.Name, task.TaskBackup, task.TaskScopeApp), func(t *task.Task) error { return itemHandler }, nil) if parentTask != nil { - return backupApp(parentTask) + return itemHandler } return backupTask.Execute() } @@ -367,6 +332,43 @@ func handleAppRecover(install *model.AppInstall, parentTask *task.Task, recoverF return recoverTask.Execute() } +func doAppBackup(install *model.AppInstall, parentTask *task.Task, backupDir, fileName, excludes, secret string) error { + fileOp := files.NewFileOp() + tmpDir := fmt.Sprintf("%s/%s", backupDir, strings.ReplaceAll(fileName, ".tar.gz", "")) + if !fileOp.Stat(tmpDir) { + if err := os.MkdirAll(tmpDir, os.ModePerm); err != nil { + return fmt.Errorf("mkdir %s failed, err: %v", backupDir, err) + } + } + defer func() { + _ = os.RemoveAll(tmpDir) + }() + + remarkInfo, _ := json.Marshal(install) + remarkInfoPath := fmt.Sprintf("%s/app.json", tmpDir) + if err := fileOp.SaveFile(remarkInfoPath, string(remarkInfo), fs.ModePerm); err != nil { + return err + } + + appPath := install.GetPath() + if err := fileOp.TarGzCompressPro(true, appPath, path.Join(tmpDir, "app.tar.gz"), "", excludes); err != nil { + return err + } + + resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithAppInstallId(install.ID)) + for _, resource := range resources { + if err := backupDatabaseWithTask(parentTask, resource.Key, tmpDir, install.Name, resource.ResourceId); err != nil { + return err + } + } + parentTask.LogStart(i18n.GetMsgByKey("CompressDir")) + if err := fileOp.TarGzCompressPro(true, tmpDir, path.Join(backupDir, fileName), secret, ""); err != nil { + return err + } + parentTask.Log(i18n.GetWithName("CompressFileSuccess", fileName)) + return nil +} + func reCreateDB(dbID uint, database model.Database, oldEnv string) (*model.DatabaseMysql, map[string]interface{}, error) { mysqlService := NewIMysqlService() ctx := context.Background() diff --git a/agent/app/service/backup_mysql.go b/agent/app/service/backup_mysql.go index b17526253..6a504e2a7 100644 --- a/agent/app/service/backup_mysql.go +++ b/agent/app/service/backup_mysql.go @@ -106,46 +106,28 @@ func (u *BackupService) MysqlRecoverByUpload(req dto.CommonRecover) error { func handleMysqlBackup(db DatabaseHelper, parentTask *task.Task, targetDir, fileName, taskID string) error { var ( - err error - itemTask *task.Task + err error + backupTask *task.Task ) - itemTask = parentTask + backupTask = parentTask dbInfo, err := mysqlRepo.Get(repo.WithByName(db.Name), mysqlRepo.WithByMysqlName(db.Database)) if err != nil { return err } itemName := fmt.Sprintf("%s[%s] - %s", db.Database, db.DBType, db.Name) if parentTask == nil { - itemTask, err = task.NewTaskWithOps(itemName, task.TaskBackup, task.TaskScopeDatabase, taskID, dbInfo.ID) + backupTask, err = task.NewTaskWithOps(itemName, task.TaskBackup, task.TaskScopeDatabase, taskID, dbInfo.ID) if err != nil { return err } } - backupDatabase := func(t *task.Task) error { - cli, version, err := LoadMysqlClientByFrom(db.Database) - if err != nil { - return err - } - backupInfo := client.BackupInfo{ - Name: db.Name, - Type: db.DBType, - Version: version, - Format: dbInfo.Format, - TargetDir: targetDir, - FileName: fileName, - - Timeout: 300, - } - return cli.Backup(backupInfo) - } - - itemTask.AddSubTask(i18n.GetMsgByKey("TaskBackup"), backupDatabase, nil) + itemHandler := doMysqlBackup(db, targetDir, fileName) + backupTask.AddSubTask(task.GetTaskName(itemName, task.TaskBackup, task.TaskScopeApp), func(t *task.Task) error { return itemHandler }, nil) if parentTask != nil { - return backupDatabase(parentTask) + return itemHandler } - - return itemTask.Execute() + return backupTask.Execute() } func handleMysqlRecover(req dto.CommonRecover, parentTask *task.Task, isRollback bool, taskID string) error { @@ -239,3 +221,25 @@ func handleMysqlRecover(req dto.CommonRecover, parentTask *task.Task, isRollback return itemTask.Execute() } + +func doMysqlBackup(db DatabaseHelper, targetDir, fileName string) error { + dbInfo, err := mysqlRepo.Get(repo.WithByName(db.Name), mysqlRepo.WithByMysqlName(db.Database)) + if err != nil { + return err + } + cli, version, err := LoadMysqlClientByFrom(db.Database) + if err != nil { + return err + } + backupInfo := client.BackupInfo{ + Name: db.Name, + Type: db.DBType, + Version: version, + Format: dbInfo.Format, + TargetDir: targetDir, + FileName: fileName, + + Timeout: 300, + } + return cli.Backup(backupInfo) +} diff --git a/agent/app/service/backup_postgresql.go b/agent/app/service/backup_postgresql.go index a18734b1b..d74c70a9a 100644 --- a/agent/app/service/backup_postgresql.go +++ b/agent/app/service/backup_postgresql.go @@ -106,38 +106,24 @@ func (u *BackupService) PostgresqlRecoverByUpload(req dto.CommonRecover) error { func handlePostgresqlBackup(db DatabaseHelper, parentTask *task.Task, targetDir, fileName, taskID string) error { var ( - err error - itemTask *task.Task + err error + backupTask *task.Task ) - itemTask = parentTask + backupTask = parentTask itemName := fmt.Sprintf("%s - %s", db.Database, db.Name) if parentTask == nil { - itemTask, err = task.NewTaskWithOps(itemName, task.TaskBackup, task.TaskScopeDatabase, taskID, db.ID) + backupTask, err = task.NewTaskWithOps(itemName, task.TaskBackup, task.TaskScopeDatabase, taskID, db.ID) if err != nil { return err } } - backupDatabase := func(t *task.Task) error { - cli, err := LoadPostgresqlClientByFrom(db.Database) - if err != nil { - return err - } - defer cli.Close() - backupInfo := pgclient.BackupInfo{ - Name: db.Name, - TargetDir: targetDir, - FileName: fileName, - Timeout: 300, - } - return cli.Backup(backupInfo) - } - itemTask.AddSubTask(i18n.GetMsgByKey("TaskBackup"), backupDatabase, nil) + itemHandler := doPostgresqlgBackup(db, targetDir, fileName) + backupTask.AddSubTask(task.GetTaskName(itemName, task.TaskBackup, task.TaskScopeApp), func(task *task.Task) error { return itemHandler }, nil) if parentTask != nil { - return backupDatabase(parentTask) + return itemHandler } - - return itemTask.Execute() + return backupTask.Execute() } func handlePostgresqlRecover(req dto.CommonRecover, parentTask *task.Task, isRollback bool) error { @@ -219,3 +205,19 @@ func handlePostgresqlRecover(req dto.CommonRecover, parentTask *task.Task, isRol return itemTask.Execute() } + +func doPostgresqlgBackup(db DatabaseHelper, targetDir, fileName string) error { + cli, err := LoadPostgresqlClientByFrom(db.Database) + if err != nil { + return err + } + defer cli.Close() + backupInfo := pgclient.BackupInfo{ + Name: db.Name, + TargetDir: targetDir, + FileName: fileName, + + Timeout: 300, + } + return cli.Backup(backupInfo) +} diff --git a/agent/app/service/backup_website.go b/agent/app/service/backup_website.go index fc1945dee..e9e936fbd 100644 --- a/agent/app/service/backup_website.go +++ b/agent/app/service/backup_website.go @@ -215,81 +215,82 @@ func handleWebsiteBackup(website *model.Website, parentTask *task.Task, backupDi return err } } - - backupWebsite := func(t *task.Task) error { - fileOp := files.NewFileOp() - tmpDir := fmt.Sprintf("%s/%s", backupDir, strings.ReplaceAll(fileName, ".tar.gz", "")) - if !fileOp.Stat(tmpDir) { - if err := os.MkdirAll(tmpDir, os.ModePerm); err != nil { - return fmt.Errorf("mkdir %s failed, err: %v", backupDir, err) - } - } - defer func() { - _ = os.RemoveAll(tmpDir) - }() - - remarkInfo, _ := json.Marshal(website) - if err = fileOp.SaveFile(tmpDir+"/website.json", string(remarkInfo), fs.ModePerm); err != nil { - return err - } - nginxConfFile := GetSitePath(*website, SiteConf) - if err = fileOp.CopyFile(nginxConfFile, tmpDir); err != nil { - return err - } - t.Log(i18n.GetMsgByKey("BackupNginxConfig")) - - switch website.Type { - case constant.Deployment: - app, err := appInstallRepo.GetFirst(repo.WithByID(website.AppInstallID)) - if err != nil { - return err - } - t.LogStart(task.GetTaskName(app.Name, task.TaskBackup, task.TaskScopeApp)) - if err = handleAppBackup(&app, backupTask, tmpDir, fmt.Sprintf("%s.app.tar.gz", website.Alias), excludes, "", ""); err != nil { - return err - } - t.LogSuccess(task.GetTaskName(app.Name, task.TaskBackup, task.TaskScopeApp)) - case constant.Runtime: - runtime, err := runtimeRepo.GetFirst(context.Background(), repo.WithByID(website.RuntimeID)) - if err != nil { - return err - } - t.LogStart(task.GetTaskName(runtime.Name, task.TaskBackup, task.TaskScopeRuntime)) - if err = handleRuntimeBackup(runtime, tmpDir, fmt.Sprintf("%s.runtime.tar.gz", website.Alias), excludes, ""); err != nil { - return err - } - t.LogSuccess(task.GetTaskName(runtime.Name, task.TaskBackup, task.TaskScopeRuntime)) - if website.DbID > 0 { - if err = backupDatabaseWithTask(t, website.DbType, tmpDir, website.Alias, website.DbID); err != nil { - return err - } - } - case constant.Static: - if website.DbID > 0 { - if err = backupDatabaseWithTask(t, website.DbType, tmpDir, website.Alias, website.DbID); err != nil { - return err - } - } - } - - websiteDir := GetSitePath(*website, SiteDir) - t.LogStart(i18n.GetMsgByKey("CompressDir")) - if err = fileOp.TarGzCompressPro(true, websiteDir, path.Join(tmpDir, fmt.Sprintf("%s.web.tar.gz", website.Alias)), "", excludes); err != nil { - return err - } - if err = fileOp.TarGzCompressPro(true, tmpDir, path.Join(backupDir, fileName), secret, ""); err != nil { - return err - } - t.Log(i18n.GetWithName("CompressFileSuccess", fileName)) - return nil - } - backupTask.AddSubTask(task.GetTaskName(website.Alias, task.TaskBackup, task.TaskScopeApp), backupWebsite, nil) + itemHandler := doWebsiteBackup(website, backupTask, backupDir, fileName, excludes, secret) + backupTask.AddSubTask(task.GetTaskName(website.Alias, task.TaskBackup, task.TaskScopeApp), func(task *task.Task) error { return itemHandler }, nil) if parentTask != nil { - return backupWebsite(parentTask) + return itemHandler } return backupTask.Execute() } +func doWebsiteBackup(website *model.Website, parentTask *task.Task, backupDir, fileName, excludes, secret string) error { + fileOp := files.NewFileOp() + tmpDir := fmt.Sprintf("%s/%s", backupDir, strings.ReplaceAll(fileName, ".tar.gz", "")) + if !fileOp.Stat(tmpDir) { + if err := os.MkdirAll(tmpDir, os.ModePerm); err != nil { + return fmt.Errorf("mkdir %s failed, err: %v", backupDir, err) + } + } + defer func() { + _ = os.RemoveAll(tmpDir) + }() + + remarkInfo, _ := json.Marshal(website) + if err := fileOp.SaveFile(tmpDir+"/website.json", string(remarkInfo), fs.ModePerm); err != nil { + return err + } + nginxConfFile := GetSitePath(*website, SiteConf) + if err := fileOp.CopyFile(nginxConfFile, tmpDir); err != nil { + return err + } + parentTask.Log(i18n.GetMsgByKey("BackupNginxConfig")) + + switch website.Type { + case constant.Deployment: + app, err := appInstallRepo.GetFirst(repo.WithByID(website.AppInstallID)) + if err != nil { + return err + } + parentTask.LogStart(task.GetTaskName(app.Name, task.TaskBackup, task.TaskScopeApp)) + if err = handleAppBackup(&app, parentTask, tmpDir, fmt.Sprintf("%s.app.tar.gz", website.Alias), excludes, "", ""); err != nil { + return err + } + parentTask.LogSuccess(task.GetTaskName(app.Name, task.TaskBackup, task.TaskScopeApp)) + case constant.Runtime: + runtime, err := runtimeRepo.GetFirst(context.Background(), repo.WithByID(website.RuntimeID)) + if err != nil { + return err + } + parentTask.LogStart(task.GetTaskName(runtime.Name, task.TaskBackup, task.TaskScopeRuntime)) + if err = handleRuntimeBackup(runtime, tmpDir, fmt.Sprintf("%s.runtime.tar.gz", website.Alias), excludes, ""); err != nil { + return err + } + parentTask.LogSuccess(task.GetTaskName(runtime.Name, task.TaskBackup, task.TaskScopeRuntime)) + if website.DbID > 0 { + if err = backupDatabaseWithTask(parentTask, website.DbType, tmpDir, website.Alias, website.DbID); err != nil { + return err + } + } + case constant.Static: + if website.DbID > 0 { + if err := backupDatabaseWithTask(parentTask, website.DbType, tmpDir, website.Alias, website.DbID); err != nil { + return err + } + } + } + + websiteDir := GetSitePath(*website, SiteDir) + parentTask.LogStart(i18n.GetMsgByKey("CompressDir")) + if err := fileOp.TarGzCompressPro(true, websiteDir, path.Join(tmpDir, fmt.Sprintf("%s.web.tar.gz", website.Alias)), "", excludes); err != nil { + return err + } + if err := fileOp.TarGzCompressPro(true, tmpDir, path.Join(backupDir, fileName), secret, ""); err != nil { + return err + } + parentTask.Log(i18n.GetWithName("CompressFileSuccess", fileName)) + return nil +} + func checkValidOfWebsite(oldWebsite, website *model.Website) error { if oldWebsite.Alias != website.Alias || oldWebsite.Type != website.Type { return buserr.WithDetail("ErrBackupMatch", fmt.Sprintf("oldName: %s, oldType: %v", oldWebsite.Alias, oldWebsite.Type), nil) diff --git a/agent/app/service/cronjob.go b/agent/app/service/cronjob.go index 41f02bbf0..bb407554e 100644 --- a/agent/app/service/cronjob.go +++ b/agent/app/service/cronjob.go @@ -1,7 +1,6 @@ package service import ( - "bufio" "encoding/json" "fmt" "os" @@ -461,24 +460,3 @@ func (u *CronjobService) AddCronJob(cronjob *model.Cronjob) (int, error) { global.LOG.Infof("start cronjob entryID: %d", entryID) return int(entryID), nil } - -func mkdirAndWriteFile(cronjob *model.Cronjob, startTime time.Time, msg []byte) (string, error) { - dir := fmt.Sprintf("%s/task/%s/%s", global.Dir.DataDir, cronjob.Type, cronjob.Name) - if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) { - if err = os.MkdirAll(dir, os.ModePerm); err != nil { - return "", err - } - } - - path := fmt.Sprintf("%s/%s.log", dir, startTime.Format(constant.DateTimeSlimLayout)) - global.LOG.Infof("cronjob %s has generated some logs %s", cronjob.Name, path) - file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, constant.FilePerm) - if err != nil { - return "", err - } - defer file.Close() - write := bufio.NewWriter(file) - _, _ = write.WriteString(string(msg)) - write.Flush() - return path, nil -} diff --git a/agent/app/service/cronjob_backup.go b/agent/app/service/cronjob_backup.go index ccb9321c1..f627a5394 100644 --- a/agent/app/service/cronjob_backup.go +++ b/agent/app/service/cronjob_backup.go @@ -10,6 +10,8 @@ import ( "time" "github.com/1Panel-dev/1Panel/agent/app/repo" + "github.com/1Panel-dev/1Panel/agent/app/task" + "github.com/1Panel-dev/1Panel/agent/i18n" "github.com/1Panel-dev/1Panel/agent/app/dto" "github.com/1Panel-dev/1Panel/agent/app/model" @@ -20,7 +22,7 @@ import ( "github.com/pkg/errors" ) -func (u *CronjobService) handleApp(cronjob model.Cronjob, startTime time.Time, taskID string) error { +func (u *CronjobService) handleApp(cronjob model.Cronjob, startTime time.Time, taskItem *task.Task) error { var apps []model.AppInstall if cronjob.AppID == "all" { apps, _ = appInstallRepo.ListBy(context.Background()) @@ -40,33 +42,36 @@ func (u *CronjobService) handleApp(cronjob model.Cronjob, startTime time.Time, t return err } for _, app := range apps { - var record model.BackupRecord - record.From = "cronjob" - record.Type = "app" - record.CronjobID = cronjob.ID - record.Name = app.App.Key - record.DetailName = app.Name - record.DownloadAccountID, record.SourceAccountIDs = cronjob.DownloadAccountID, cronjob.SourceAccountIDs - backupDir := path.Join(global.Dir.TmpDir, fmt.Sprintf("app/%s/%s", app.App.Key, app.Name)) - record.FileName = fmt.Sprintf("app_%s_%s.tar.gz", app.Name, startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5)) - if err := handleAppBackup(&app, nil, backupDir, record.FileName, cronjob.ExclusionRules, cronjob.Secret, taskID); err != nil { - return err - } - downloadPath, err := u.uploadCronjobBackFile(cronjob, accountMap, path.Join(backupDir, record.FileName)) - if err != nil { - return err - } - record.FileDir = path.Dir(downloadPath) - if err := backupRepo.CreateRecord(&record); err != nil { - global.LOG.Errorf("save backup record failed, err: %v", err) - return err - } - u.removeExpiredBackup(cronjob, accountMap, record) + taskItem.AddSubTaskWithOps(task.GetTaskName(app.Name, task.TaskBackup, task.TaskScopeCronjob), func(task *task.Task) error { + var record model.BackupRecord + record.From = "cronjob" + record.Type = "app" + record.CronjobID = cronjob.ID + record.Name = app.App.Key + record.DetailName = app.Name + record.DownloadAccountID, record.SourceAccountIDs = cronjob.DownloadAccountID, cronjob.SourceAccountIDs + backupDir := path.Join(global.Dir.TmpDir, fmt.Sprintf("app/%s/%s", app.App.Key, app.Name)) + record.FileName = fmt.Sprintf("app_%s_%s.tar.gz", app.Name, startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5)) + if err := doAppBackup(&app, task, backupDir, record.FileName, cronjob.ExclusionRules, cronjob.Secret); err != nil { + return err + } + downloadPath, err := u.uploadCronjobBackFile(cronjob, accountMap, path.Join(backupDir, record.FileName)) + if err != nil { + return err + } + record.FileDir = path.Dir(downloadPath) + if err := backupRepo.CreateRecord(&record); err != nil { + global.LOG.Errorf("save backup record failed, err: %v", err) + return err + } + u.removeExpiredBackup(cronjob, accountMap, record) + return nil + }, nil, int(cronjob.RetryTimes), time.Duration(cronjob.Timeout)*time.Second) } return nil } -func (u *CronjobService) handleWebsite(cronjob model.Cronjob, startTime time.Time, taskID string) error { +func (u *CronjobService) handleWebsite(cronjob model.Cronjob, startTime time.Time, taskItem *task.Task) error { webs := loadWebsForJob(cronjob) if len(webs) == 0 { return errors.New("no such website in database!") @@ -76,33 +81,39 @@ func (u *CronjobService) handleWebsite(cronjob model.Cronjob, startTime time.Tim return err } for _, web := range webs { - var record model.BackupRecord - record.From = "cronjob" - record.Type = "website" - record.CronjobID = cronjob.ID - record.Name = web.Alias - record.DetailName = web.Alias - record.DownloadAccountID, record.SourceAccountIDs = cronjob.DownloadAccountID, cronjob.SourceAccountIDs - backupDir := path.Join(global.Dir.TmpDir, fmt.Sprintf("website/%s", web.Alias)) - record.FileName = fmt.Sprintf("website_%s_%s.tar.gz", web.Alias, startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5)) - if err := handleWebsiteBackup(&web, nil, backupDir, record.FileName, cronjob.ExclusionRules, cronjob.Secret, taskID); err != nil { - return err - } - downloadPath, err := u.uploadCronjobBackFile(cronjob, accountMap, path.Join(backupDir, record.FileName)) - if err != nil { - return err - } - record.FileDir = path.Dir(downloadPath) - if err := backupRepo.CreateRecord(&record); err != nil { - global.LOG.Errorf("save backup record failed, err: %v", err) - return err - } - u.removeExpiredBackup(cronjob, accountMap, record) + taskItem.AddSubTaskWithOps(task.GetTaskName(web.Alias, task.TaskBackup, task.TaskScopeCronjob), func(task *task.Task) error { + var record model.BackupRecord + record.From = "cronjob" + record.Type = "website" + record.CronjobID = cronjob.ID + record.Name = web.Alias + record.DetailName = web.Alias + record.DownloadAccountID, record.SourceAccountIDs = cronjob.DownloadAccountID, cronjob.SourceAccountIDs + backupDir := path.Join(global.Dir.TmpDir, fmt.Sprintf("website/%s", web.Alias)) + record.FileName = fmt.Sprintf("website_%s_%s.tar.gz", web.Alias, startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5)) + + if err := doWebsiteBackup(&web, taskItem, backupDir, record.FileName, cronjob.ExclusionRules, cronjob.Secret); err != nil { + return err + } + + downloadPath, err := u.uploadCronjobBackFile(cronjob, accountMap, path.Join(backupDir, record.FileName)) + if err != nil { + return err + } + record.FileDir = path.Dir(downloadPath) + if err := backupRepo.CreateRecord(&record); err != nil { + global.LOG.Errorf("save backup record failed, err: %v", err) + return err + } + u.removeExpiredBackup(cronjob, accountMap, record) + return nil + }, nil, int(cronjob.RetryTimes), time.Duration(cronjob.Timeout)*time.Second) + return nil } return nil } -func (u *CronjobService) handleDatabase(cronjob model.Cronjob, startTime time.Time, taskID string) error { +func (u *CronjobService) handleDatabase(cronjob model.Cronjob, startTime time.Time, taskItem *task.Task) error { dbs := loadDbsForJob(cronjob) if len(dbs) == 0 { return errors.New("no such db in database!") @@ -112,110 +123,125 @@ func (u *CronjobService) handleDatabase(cronjob model.Cronjob, startTime time.Ti return err } for _, dbInfo := range dbs { - var record model.BackupRecord - record.From = "cronjob" - record.Type = dbInfo.DBType - record.CronjobID = cronjob.ID - record.Name = dbInfo.Database - record.DetailName = dbInfo.Name - record.DownloadAccountID, record.SourceAccountIDs = cronjob.DownloadAccountID, cronjob.SourceAccountIDs + itemName := fmt.Sprintf("%s[%s] - %s", dbInfo.Database, dbInfo.DBType, dbInfo.Name) + taskItem.AddSubTaskWithOps(task.GetTaskName(itemName, task.TaskBackup, task.TaskScopeCronjob), func(task *task.Task) error { + var record model.BackupRecord + record.From = "cronjob" + record.Type = dbInfo.DBType + record.CronjobID = cronjob.ID + record.Name = dbInfo.Database + record.DetailName = dbInfo.Name + record.DownloadAccountID, record.SourceAccountIDs = cronjob.DownloadAccountID, cronjob.SourceAccountIDs - backupDir := path.Join(global.Dir.TmpDir, fmt.Sprintf("database/%s/%s/%s", dbInfo.DBType, record.Name, dbInfo.Name)) - record.FileName = fmt.Sprintf("db_%s_%s.sql.gz", dbInfo.Name, startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5)) - if cronjob.DBType == "mysql" || cronjob.DBType == "mariadb" { - if err := handleMysqlBackup(dbInfo, nil, backupDir, record.FileName, taskID); err != nil { + backupDir := path.Join(global.Dir.TmpDir, fmt.Sprintf("database/%s/%s/%s", dbInfo.DBType, record.Name, dbInfo.Name)) + record.FileName = fmt.Sprintf("db_%s_%s.sql.gz", dbInfo.Name, startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5)) + if cronjob.DBType == "mysql" || cronjob.DBType == "mariadb" { + if err := doMysqlBackup(dbInfo, backupDir, record.FileName); err != nil { + return err + } + } else { + if err := doPostgresqlgBackup(dbInfo, backupDir, record.FileName); err != nil { + return err + } + } + + downloadPath, err := u.uploadCronjobBackFile(cronjob, accountMap, path.Join(backupDir, record.FileName)) + if err != nil { return err } - } else { - if err := handlePostgresqlBackup(dbInfo, nil, backupDir, record.FileName, taskID); err != nil { + record.FileDir = path.Dir(downloadPath) + if err := backupRepo.CreateRecord(&record); err != nil { + global.LOG.Errorf("save backup record failed, err: %v", err) return err } - } - downloadPath, err := u.uploadCronjobBackFile(cronjob, accountMap, path.Join(backupDir, record.FileName)) + u.removeExpiredBackup(cronjob, accountMap, record) + return nil + }, nil, int(cronjob.RetryTimes), time.Duration(cronjob.Timeout)*time.Second) + } + return nil +} + +func (u *CronjobService) handleDirectory(cronjob model.Cronjob, startTime time.Time, taskItem *task.Task) error { + taskItem.AddSubTaskWithOps(task.GetTaskName(i18n.GetMsgByKey("BackupFileOrDir"), task.TaskBackup, task.TaskScopeCronjob), func(task *task.Task) error { + accountMap, err := NewBackupClientMap(strings.Split(cronjob.SourceAccountIDs, ",")) if err != nil { return err } + fileName := fmt.Sprintf("%s.tar.gz", startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5)) + backupDir := path.Join(global.Dir.TmpDir, fmt.Sprintf("%s/%s", cronjob.Type, cronjob.Name)) + + fileOp := files.NewFileOp() + if cronjob.IsDir { + taskItem.Logf("Dir: %s, Excludes: %s", cronjob.SourceDir, cronjob.ExclusionRules) + if err := fileOp.TarGzCompressPro(true, cronjob.SourceDir, path.Join(backupDir, fileName), cronjob.Secret, cronjob.ExclusionRules); err != nil { + return err + } + } else { + taskItem.Logf("Files: %s", cronjob.SourceDir) + fileLists := strings.Split(cronjob.SourceDir, ",") + if err := fileOp.TarGzFilesWithCompressPro(fileLists, path.Join(backupDir, fileName), cronjob.Secret); err != nil { + return err + } + } + var record model.BackupRecord + record.From = "cronjob" + record.Type = "directory" + record.CronjobID = cronjob.ID + record.Name = cronjob.Name + record.DownloadAccountID, record.SourceAccountIDs = cronjob.DownloadAccountID, cronjob.SourceAccountIDs + downloadPath, err := u.uploadCronjobBackFile(cronjob, accountMap, path.Join(backupDir, fileName)) + if err != nil { + taskItem.LogFailedWithErr("Upload backup file", err) + return err + } record.FileDir = path.Dir(downloadPath) + record.FileName = fileName if err := backupRepo.CreateRecord(&record); err != nil { - global.LOG.Errorf("save backup record failed, err: %v", err) + taskItem.LogFailedWithErr("Save record", err) return err } u.removeExpiredBackup(cronjob, accountMap, record) - } + return nil + }, nil, int(cronjob.RetryTimes), time.Duration(cronjob.Timeout)*time.Second) return nil } -func (u *CronjobService) handleDirectory(cronjob model.Cronjob, startTime time.Time) error { - accountMap, err := NewBackupClientMap(strings.Split(cronjob.SourceAccountIDs, ",")) - if err != nil { - return err - } - fileName := fmt.Sprintf("%s.tar.gz", startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5)) - backupDir := path.Join(global.Dir.TmpDir, fmt.Sprintf("%s/%s", cronjob.Type, cronjob.Name)) - - fileOp := files.NewFileOp() - if cronjob.IsDir { - if err := fileOp.TarGzCompressPro(true, cronjob.SourceDir, path.Join(backupDir, fileName), cronjob.Secret, cronjob.ExclusionRules); err != nil { +func (u *CronjobService) handleSystemLog(cronjob model.Cronjob, startTime time.Time, taskItem *task.Task) error { + taskItem.AddSubTaskWithOps(task.GetTaskName(i18n.GetMsgByKey("BackupSystemLog"), task.TaskBackup, task.TaskScopeCronjob), func(task *task.Task) error { + accountMap, err := NewBackupClientMap(strings.Split(cronjob.SourceAccountIDs, ",")) + if err != nil { return err } - } else { - fileLists := strings.Split(cronjob.SourceDir, ",") - if err := fileOp.TarGzFilesWithCompressPro(fileLists, path.Join(backupDir, fileName), cronjob.Secret); err != nil { + nameItem := startTime.Format(constant.DateTimeSlimLayout) + common.RandStrAndNum(5) + fileName := fmt.Sprintf("system_log_%s.tar.gz", nameItem) + backupDir := path.Join(global.Dir.TmpDir, "log", nameItem) + if err := handleBackupLogs(taskItem, backupDir, fileName, cronjob.Secret); err != nil { return err } - } - var record model.BackupRecord - record.From = "cronjob" - record.Type = "directory" - record.CronjobID = cronjob.ID - record.Name = cronjob.Name - record.DownloadAccountID, record.SourceAccountIDs = cronjob.DownloadAccountID, cronjob.SourceAccountIDs - downloadPath, err := u.uploadCronjobBackFile(cronjob, accountMap, path.Join(backupDir, fileName)) - if err != nil { - return err - } - record.FileDir = path.Dir(downloadPath) - record.FileName = fileName - if err := backupRepo.CreateRecord(&record); err != nil { - global.LOG.Errorf("save backup record failed, err: %v", err) - return err - } - u.removeExpiredBackup(cronjob, accountMap, record) + var record model.BackupRecord + record.From = "cronjob" + record.Type = "log" + record.CronjobID = cronjob.ID + record.Name = cronjob.Name + record.DownloadAccountID, record.SourceAccountIDs = cronjob.DownloadAccountID, cronjob.SourceAccountIDs + downloadPath, err := u.uploadCronjobBackFile(cronjob, accountMap, path.Join(path.Dir(backupDir), fileName)) + if err != nil { + taskItem.LogFailedWithErr("Upload backup file", err) + return err + } + record.FileDir = path.Dir(downloadPath) + record.FileName = fileName + if err := backupRepo.CreateRecord(&record); err != nil { + taskItem.LogFailedWithErr("Save record", err) + return err + } + u.removeExpiredBackup(cronjob, accountMap, record) + return nil + }, nil, int(cronjob.RetryTimes), time.Duration(cronjob.Timeout)*time.Second) return nil } -func (u *CronjobService) handleSystemLog(cronjob model.Cronjob, startTime time.Time) error { - accountMap, err := NewBackupClientMap(strings.Split(cronjob.SourceAccountIDs, ",")) - if err != nil { - return err - } - nameItem := startTime.Format(constant.DateTimeSlimLayout) + common.RandStrAndNum(5) - fileName := fmt.Sprintf("system_log_%s.tar.gz", nameItem) - backupDir := path.Join(global.Dir.TmpDir, "log", nameItem) - if err := handleBackupLogs(backupDir, fileName, cronjob.Secret); err != nil { - return err - } - var record model.BackupRecord - record.From = "cronjob" - record.Type = "log" - record.CronjobID = cronjob.ID - record.Name = cronjob.Name - record.DownloadAccountID, record.SourceAccountIDs = cronjob.DownloadAccountID, cronjob.SourceAccountIDs - downloadPath, err := u.uploadCronjobBackFile(cronjob, accountMap, path.Join(path.Dir(backupDir), fileName)) - if err != nil { - return err - } - record.FileDir = path.Dir(downloadPath) - record.FileName = fileName - if err := backupRepo.CreateRecord(&record); err != nil { - global.LOG.Errorf("save backup record failed, err: %v", err) - return err - } - u.removeExpiredBackup(cronjob, accountMap, record) - return nil -} - -func (u *CronjobService) handleSnapshot(cronjob model.Cronjob, jobRecord model.JobRecords) error { +func (u *CronjobService) handleSnapshot(cronjob model.Cronjob, jobRecord model.JobRecords, taskItem *task.Task) error { accountMap, err := NewBackupClientMap(strings.Split(cronjob.SourceAccountIDs, ",")) if err != nil { return err @@ -255,7 +281,7 @@ func (u *CronjobService) handleSnapshot(cronjob model.Cronjob, jobRecord model.J WithTaskLog: true, } - if err := NewISnapshotService().SnapshotCreate(req, jobRecord.ID); err != nil { + if err := NewISnapshotService().SnapshotCreate(taskItem, req, jobRecord.ID, cronjob.RetryTimes, cronjob.Timeout); err != nil { return err } record.FileName = req.Name + ".tar.gz" @@ -336,7 +362,7 @@ func loadWebsForJob(cronjob model.Cronjob) []model.Website { return weblist } -func handleBackupLogs(targetDir, fileName string, secret string) error { +func handleBackupLogs(taskItem *task.Task, targetDir, fileName string, secret string) error { fileOp := files.NewFileOp() websites, err := websiteRepo.List() if err != nil { @@ -345,6 +371,7 @@ func handleBackupLogs(targetDir, fileName string, secret string) error { if len(websites) != 0 { webItem := GetOpenrestyDir(SitesRootDir) for _, website := range websites { + taskItem.Logf("%s Website logs %s...", i18n.GetMsgByKey("TaskBackup"), website.Alias) dirItem := path.Join(targetDir, "website", website.Alias) if _, err := os.Stat(dirItem); err != nil && os.IsNotExist(err) { if err = os.MkdirAll(dirItem, os.ModePerm); err != nil { @@ -370,7 +397,6 @@ func handleBackupLogs(targetDir, fileName string, secret string) error { } } } - global.LOG.Debug("backup website log successful!") } systemDir := path.Join(targetDir, "system") @@ -379,6 +405,8 @@ func handleBackupLogs(targetDir, fileName string, secret string) error { return err } } + + taskItem.Logf("%s System logs...", i18n.GetMsgByKey("TaskBackup")) systemLogFiles, _ := os.ReadDir(global.Dir.LogDir) if len(systemLogFiles) != 0 { for i := 0; i < len(systemLogFiles); i++ { @@ -387,8 +415,8 @@ func handleBackupLogs(targetDir, fileName string, secret string) error { } } } - global.LOG.Debug("backup system log successful!") + taskItem.Logf("%s SSH logs...", i18n.GetMsgByKey("TaskBackup")) loginLogFiles, _ := os.ReadDir("/var/log") loginDir := path.Join(targetDir, "login") if _, err := os.Stat(loginDir); err != nil && os.IsNotExist(err) { @@ -403,7 +431,7 @@ func handleBackupLogs(targetDir, fileName string, secret string) error { } } } - global.LOG.Debug("backup ssh log successful!") + taskItem.Log("backup ssh log successful!") if err := fileOp.TarGzCompressPro(true, targetDir, path.Join(path.Dir(targetDir), fileName), secret, ""); err != nil { return err diff --git a/agent/app/service/cronjob_helper.go b/agent/app/service/cronjob_helper.go index 3a50eb39c..27492fb32 100644 --- a/agent/app/service/cronjob_helper.go +++ b/agent/app/service/cronjob_helper.go @@ -12,7 +12,6 @@ import ( "github.com/1Panel-dev/1Panel/agent/app/model" "github.com/1Panel-dev/1Panel/agent/app/repo" "github.com/1Panel-dev/1Panel/agent/app/task" - "github.com/1Panel-dev/1Panel/agent/buserr" "github.com/1Panel-dev/1Panel/agent/constant" "github.com/1Panel-dev/1Panel/agent/global" "github.com/1Panel-dev/1Panel/agent/i18n" @@ -25,114 +24,94 @@ import ( func (u *CronjobService) HandleJob(cronjob *model.Cronjob) { record := cronjobRepo.StartRecords(cronjob.ID, "", cronjob.Type) go func() { - var ( - message []byte - err error - ) - cronjob.RetryTimes = cronjob.RetryTimes + 1 - for i := uint(0); i < cronjob.RetryTimes; i++ { - ctx, cancel := context.WithTimeout(context.Background(), time.Duration(cronjob.Timeout)*time.Second) - done := make(chan error) - go func() { - message, err = u.handleJob(cronjob, record) - if err != nil { - global.LOG.Debugf("try handle cron job [%s] %s failed %d/%d, err: %v", cronjob.Type, cronjob.Name, i+1, cronjob.RetryTimes, err) + taskItem, err := task.NewTaskWithOps(fmt.Sprintf("cronjob-%s", cronjob.Name), task.TaskHandle, task.TaskScopeCronjob, record.TaskID, cronjob.ID) + if err != nil { + global.LOG.Errorf("new task for exec shell failed, err: %v", err) + return + } + err = u.loadTask(cronjob, &record, taskItem) + if cronjob.Type == "snapshot" { + if err != nil { + taskItem, _ := taskRepo.GetFirst(taskRepo.WithByID(record.TaskID)) + if len(taskItem.ID) == 0 { + record.TaskID = "" } - close(done) - }() - select { - case <-done: - cancel() - case <-ctx.Done(): - global.LOG.Debugf("try handle cron job [%s] %s failed %d/%d, err: timeout", cronjob.Type, cronjob.Name, i+1, cronjob.RetryTimes) - err = fmt.Errorf("handle timeout") - cancel() - continue + cronjobRepo.EndRecords(record, constant.StatusFailed, err.Error(), record.Records) + handleCronJobAlert(cronjob) + return } + cronjobRepo.EndRecords(record, constant.StatusSuccess, "", record.Records) + return } if err != nil { - if len(message) != 0 { - record.Records, _ = mkdirAndWriteFile(cronjob, record.StartTime, message) - } + global.LOG.Debugf("preper to handle cron job [%s] %s failed, err: %v", cronjob.Type, cronjob.Name, err) + record.TaskID = "" + cronjobRepo.EndRecords(record, constant.StatusFailed, err.Error(), record.Records) + return + } + if err := taskItem.Execute(); err != nil { taskItem, _ := taskRepo.GetFirst(taskRepo.WithByID(record.TaskID)) if len(taskItem.ID) == 0 { record.TaskID = "" } cronjobRepo.EndRecords(record, constant.StatusFailed, err.Error(), record.Records) handleCronJobAlert(cronjob) - return + } else { + cronjobRepo.EndRecords(record, constant.StatusSuccess, "", record.Records) } - if len(message) != 0 { - record.Records, err = mkdirAndWriteFile(cronjob, record.StartTime, message) - if err != nil { - global.LOG.Errorf("save file %s failed, err: %v", record.Records, err) - } - } - cronjobRepo.EndRecords(record, constant.StatusSuccess, "", record.Records) }() } -func (u *CronjobService) handleJob(cronjob *model.Cronjob, record model.JobRecords) ([]byte, error) { - var ( - message []byte - err error - ) +func (u *CronjobService) loadTask(cronjob *model.Cronjob, record *model.JobRecords, taskItem *task.Task) error { + var err error switch cronjob.Type { case "shell": if cronjob.ScriptMode == "library" { scriptItem, _ := scriptRepo.Get(repo.WithByID(cronjob.ScriptID)) if scriptItem.ID == 0 { - return nil, fmt.Errorf("load script from db failed, err: %v", err) + return fmt.Errorf("load script from db failed, err: %v", err) } cronjob.Script = scriptItem.Script cronjob.ScriptMode = "input" } if len(cronjob.Script) == 0 { - return nil, fmt.Errorf("the script content is empty and is skipped") + return fmt.Errorf("the script content is empty and is skipped") } - err = u.handleShell(*cronjob, record.TaskID) + u.handleShell(*cronjob, taskItem) case "curl": if len(cronjob.URL) == 0 { - return nil, fmt.Errorf("the url is empty and is skipped") + return fmt.Errorf("the url is empty and is skipped") } - err = u.handleCurl(*cronjob, record.TaskID) + u.handleCurl(*cronjob, taskItem) case "ntp": - err = u.handleNtpSync(*cronjob, record.TaskID) + u.handleNtpSync(*cronjob, taskItem) case "cutWebsiteLog": - var messageItem []string - messageItem, record.File, err = u.handleCutWebsiteLog(cronjob, record.StartTime) - message = []byte(strings.Join(messageItem, "\n")) + err = u.handleCutWebsiteLog(cronjob, record, taskItem) case "clean": - err = u.handleSystemClean(*cronjob, record.TaskID) + u.handleSystemClean(*cronjob, taskItem) case "website": - err = u.handleWebsite(*cronjob, record.StartTime, record.TaskID) + err = u.handleWebsite(*cronjob, record.StartTime, taskItem) case "app": - err = u.handleApp(*cronjob, record.StartTime, record.TaskID) + err = u.handleApp(*cronjob, record.StartTime, taskItem) case "database": - err = u.handleDatabase(*cronjob, record.StartTime, record.TaskID) + err = u.handleDatabase(*cronjob, record.StartTime, taskItem) case "directory": if len(cronjob.SourceDir) == 0 { - return nil, fmt.Errorf("the source dir is empty and is skipped") + return fmt.Errorf("the source dir is empty and is skipped") } - err = u.handleDirectory(*cronjob, record.StartTime) + err = u.handleDirectory(*cronjob, record.StartTime, taskItem) case "log": - err = u.handleSystemLog(*cronjob, record.StartTime) + err = u.handleSystemLog(*cronjob, record.StartTime, taskItem) case "snapshot": _ = cronjobRepo.UpdateRecords(record.ID, map[string]interface{}{"records": record.Records}) - err = u.handleSnapshot(*cronjob, record) + err = u.handleSnapshot(*cronjob, *record, taskItem) } - return message, err + return err } -func (u *CronjobService) handleShell(cronjob model.Cronjob, taskID string) error { - taskItem, err := task.NewTaskWithOps(fmt.Sprintf("cronjob-%s", cronjob.Name), task.TaskHandle, task.TaskScopeCronjob, taskID, cronjob.ID) - if err != nil { - global.LOG.Errorf("new task for exec shell failed, err: %v", err) - return err - } - - cmdMgr := cmd.NewCommandMgr(cmd.WithTask(*taskItem), cmd.WithTimeout(24*time.Hour)) - taskItem.AddSubTask(i18n.GetWithName("HandleShell", cronjob.Name), func(t *task.Task) error { +func (u *CronjobService) handleShell(cronjob model.Cronjob, taskItem *task.Task) { + cmdMgr := cmd.NewCommandMgr(cmd.WithTask(*taskItem)) + taskItem.AddSubTaskWithOps(i18n.GetWithName("HandleShell", cronjob.Name), func(t *task.Task) error { if len(cronjob.ContainerName) != 0 { command := "sh" if len(cronjob.Command) != 0 { @@ -166,36 +145,18 @@ func (u *CronjobService) handleShell(cronjob model.Cronjob, taskID string) error return err } return nil - }, - nil, - ) - return taskItem.Execute() + }, nil, int(cronjob.RetryTimes), time.Duration(cronjob.Timeout)*time.Second) } -func (u *CronjobService) handleCurl(cronjob model.Cronjob, taskID string) error { - taskItem, err := task.NewTaskWithOps(fmt.Sprintf("cronjob-%s", cronjob.Name), task.TaskHandle, task.TaskScopeCronjob, taskID, cronjob.ID) - if err != nil { - global.LOG.Errorf("new task for exec shell failed, err: %v", err) - return err - } - - taskItem.AddSubTask(i18n.GetWithName("HandleShell", cronjob.Name), func(t *task.Task) error { - cmdMgr := cmd.NewCommandMgr(cmd.WithTask(*taskItem), cmd.WithTimeout(time.Hour)) +func (u *CronjobService) handleCurl(cronjob model.Cronjob, taskItem *task.Task) { + taskItem.AddSubTaskWithOps(i18n.GetWithName("HandleShell", cronjob.Name), func(t *task.Task) error { + cmdMgr := cmd.NewCommandMgr(cmd.WithTask(*taskItem)) return cmdMgr.Run("curl", cronjob.URL) - }, - nil, - ) - return taskItem.Execute() + }, nil, int(cronjob.RetryTimes), time.Duration(cronjob.Timeout)*time.Second) } -func (u *CronjobService) handleNtpSync(cronjob model.Cronjob, taskID string) error { - taskItem, err := task.NewTaskWithOps(fmt.Sprintf("cronjob-%s", cronjob.Name), task.TaskHandle, task.TaskScopeCronjob, taskID, cronjob.ID) - if err != nil { - global.LOG.Errorf("new task for exec shell failed, err: %v", err) - return err - } - - taskItem.AddSubTask(i18n.GetMsgByKey("HandleNtpSync"), func(t *task.Task) error { +func (u *CronjobService) handleNtpSync(cronjob model.Cronjob, taskItem *task.Task) { + taskItem.AddSubTaskWithOps(i18n.GetMsgByKey("HandleNtpSync"), func(t *task.Task) error { ntpServer, err := settingRepo.Get(settingRepo.WithByKey("NtpSite")) if err != nil { return err @@ -209,47 +170,43 @@ func (u *CronjobService) handleNtpSync(cronjob model.Cronjob, taskID string) err return err } return nil - }, nil) - return taskItem.Execute() + }, nil, int(cronjob.RetryTimes), time.Duration(cronjob.Timeout)*time.Second) } -func (u *CronjobService) handleCutWebsiteLog(cronjob *model.Cronjob, startTime time.Time) ([]string, string, error) { - var ( - err error - filePaths []string - msgs []string - ) - websites := loadWebsForJob(*cronjob) - fileOp := files.NewFileOp() - baseDir := GetOpenrestyDir(SitesRootDir) - for _, website := range websites { - websiteLogDir := pathUtils.Join(baseDir, website.Alias, "log") - srcAccessLogPath := pathUtils.Join(websiteLogDir, "access.log") - srcErrorLogPath := pathUtils.Join(websiteLogDir, "error.log") - dstLogDir := pathUtils.Join(global.Dir.LocalBackupDir, "log", "website", website.Alias) - if !fileOp.Stat(dstLogDir) { - _ = os.MkdirAll(dstLogDir, constant.DirPerm) - } +func (u *CronjobService) handleCutWebsiteLog(cronjob *model.Cronjob, record *model.JobRecords, taskItem *task.Task) error { + taskItem.AddSubTaskWithOps(i18n.GetWithName("CutWebsiteLog", cronjob.Name), func(t *task.Task) error { + var filePaths []string + websites := loadWebsForJob(*cronjob) + fileOp := files.NewFileOp() + baseDir := GetOpenrestyDir(SitesRootDir) + for _, website := range websites { + taskItem.Log(website.Alias) + websiteLogDir := pathUtils.Join(baseDir, website.Alias, "log") + srcAccessLogPath := pathUtils.Join(websiteLogDir, "access.log") + srcErrorLogPath := pathUtils.Join(websiteLogDir, "error.log") + dstLogDir := pathUtils.Join(global.Dir.LocalBackupDir, "log", "website", website.Alias) + if !fileOp.Stat(dstLogDir) { + _ = os.MkdirAll(dstLogDir, constant.DirPerm) + } - dstName := fmt.Sprintf("%s_log_%s.gz", website.PrimaryDomain, startTime.Format(constant.DateTimeSlimLayout)) - dstFilePath := pathUtils.Join(dstLogDir, dstName) - filePaths = append(filePaths, dstFilePath) + dstName := fmt.Sprintf("%s_log_%s.gz", website.PrimaryDomain, record.StartTime.Format(constant.DateTimeSlimLayout)) + dstFilePath := pathUtils.Join(dstLogDir, dstName) + filePaths = append(filePaths, dstFilePath) - if err = backupLogFile(dstFilePath, websiteLogDir, fileOp); err != nil { - websiteErr := buserr.WithNameAndErr("ErrCutWebsiteLog", website.PrimaryDomain, err) - err = websiteErr - msgs = append(msgs, websiteErr.Error()) - global.LOG.Error(websiteErr.Error()) - continue - } else { - _ = fileOp.WriteFile(srcAccessLogPath, strings.NewReader(""), constant.DirPerm) - _ = fileOp.WriteFile(srcErrorLogPath, strings.NewReader(""), constant.DirPerm) + if err := backupLogFile(dstFilePath, websiteLogDir, fileOp); err != nil { + taskItem.LogFailedWithErr("CutWebsiteLog", err) + continue + } else { + _ = fileOp.WriteFile(srcAccessLogPath, strings.NewReader(""), constant.DirPerm) + _ = fileOp.WriteFile(srcErrorLogPath, strings.NewReader(""), constant.DirPerm) + } + taskItem.Log(i18n.GetMsgWithMap("CutWebsiteLogSuccess", map[string]interface{}{"name": website.PrimaryDomain, "path": dstFilePath})) } - msg := i18n.GetMsgWithMap("CutWebsiteLogSuccess", map[string]interface{}{"name": website.PrimaryDomain, "path": dstFilePath}) - msgs = append(msgs, msg) - } - u.removeExpiredLog(*cronjob) - return msgs, strings.Join(filePaths, ","), err + u.removeExpiredLog(*cronjob) + record.File = strings.Join(filePaths, ",") + return nil + }, nil, int(cronjob.RetryTimes), time.Duration(cronjob.Timeout)*time.Second) + return nil } func backupLogFile(dstFilePath, websiteLogDir string, fileOp files.FileOp) error { @@ -272,13 +229,9 @@ func backupLogFile(dstFilePath, websiteLogDir string, fileOp files.FileOp) error return nil } -func (u *CronjobService) handleSystemClean(cronjob model.Cronjob, taskID string) error { - taskItem, err := task.NewTaskWithOps(fmt.Sprintf("cronjob-%s", cronjob.Name), task.TaskHandle, task.TaskScopeCronjob, taskID, cronjob.ID) - if err != nil { - global.LOG.Errorf("new task for system clean failed, err: %v", err) - return err - } - return systemClean(taskItem) +func (u *CronjobService) handleSystemClean(cronjob model.Cronjob, taskItem *task.Task) { + cleanTask := doSystemClean(taskItem) + taskItem.AddSubTaskWithOps(i18n.GetMsgByKey("HandleSystemClean"), cleanTask, nil, int(cronjob.RetryTimes), time.Duration(cronjob.Timeout)*time.Second) } func (u *CronjobService) uploadCronjobBackFile(cronjob model.Cronjob, accountMap map[string]backupClientHelper, file string) (string, error) { diff --git a/agent/app/service/device_clean.go b/agent/app/service/device_clean.go index 1c4c18741..43807841a 100644 --- a/agent/app/service/device_clean.go +++ b/agent/app/service/device_clean.go @@ -10,7 +10,6 @@ import ( "time" "github.com/1Panel-dev/1Panel/agent/constant" - "github.com/1Panel-dev/1Panel/agent/i18n" "github.com/1Panel-dev/1Panel/agent/utils/docker" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" @@ -301,8 +300,8 @@ func (u *DeviceService) Clean(req []dto.Clean) { } } -func systemClean(taskItem *task.Task) error { - taskItem.AddSubTask(i18n.GetMsgByKey("HandleSystemClean"), func(t *task.Task) error { +func doSystemClean(taskItem *task.Task) func(t *task.Task) error { + return func(t *task.Task) error { size := int64(0) fileCount := 0 dropWithTask(path.Join(global.Dir.BaseDir, "1panel_original"), taskItem, &size, &fileCount) @@ -363,8 +362,7 @@ func systemClean(taskItem *task.Task) error { _ = settingRepo.Update("LastCleanData", fmt.Sprintf("%v", fileCount)) return nil - }, nil) - return taskItem.Execute() + } } func loadSnapshotTree(fileOp fileUtils.FileOp) []dto.CleanTree { diff --git a/agent/app/service/snapshot.go b/agent/app/service/snapshot.go index eb39a93bf..a88347a1b 100644 --- a/agent/app/service/snapshot.go +++ b/agent/app/service/snapshot.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/1Panel-dev/1Panel/agent/app/repo" + "github.com/1Panel-dev/1Panel/agent/app/task" "github.com/1Panel-dev/1Panel/agent/buserr" "github.com/1Panel-dev/1Panel/agent/app/dto" @@ -30,7 +31,7 @@ type SnapshotService struct { type ISnapshotService interface { SearchWithPage(req dto.PageSnapshot) (int64, interface{}, error) LoadSnapshotData() (dto.SnapshotData, error) - SnapshotCreate(req dto.SnapshotCreate, jobID uint) error + SnapshotCreate(parentTask *task.Task, req dto.SnapshotCreate, jobID, retry, timeout uint) error SnapshotReCreate(id uint) error SnapshotRecover(req dto.SnapshotRecover) error SnapshotRollback(req dto.SnapshotRecover) error diff --git a/agent/app/service/snapshot_create.go b/agent/app/service/snapshot_create.go index 55e6ed244..b00a51905 100644 --- a/agent/app/service/snapshot_create.go +++ b/agent/app/service/snapshot_create.go @@ -26,7 +26,7 @@ import ( "gorm.io/gorm" ) -func (u *SnapshotService) SnapshotCreate(req dto.SnapshotCreate, jobID uint) error { +func (u *SnapshotService) SnapshotCreate(parentTask *task.Task, req dto.SnapshotCreate, jobID, retry, timeout uint) error { versionItem, _ := settingRepo.Get(settingRepo.WithByKey("SystemVersion")) scope := "core" @@ -65,19 +65,23 @@ func (u *SnapshotService) SnapshotCreate(req dto.SnapshotCreate, jobID uint) err } req.ID = snap.ID - taskItem, err := task.NewTaskWithOps(req.Name, task.TaskCreate, task.TaskScopeSnapshot, req.TaskID, req.ID) - if err != nil { - global.LOG.Errorf("new task for create snapshot failed, err: %v", err) - return err + var err error + taskItem := parentTask + if parentTask == nil { + taskItem, err = task.NewTaskWithOps(req.Name, task.TaskCreate, task.TaskScopeSnapshot, req.TaskID, req.ID) + if err != nil { + global.LOG.Errorf("new task for create snapshot failed, err: %v", err) + return err + } } if jobID == 0 { go func() { - _ = handleSnapshot(req, taskItem, jobID) + _ = handleSnapshot(req, taskItem, jobID, 0, 0) }() return nil } - return handleSnapshot(req, taskItem, jobID) + return handleSnapshot(req, taskItem, jobID, retry, timeout) } func (u *SnapshotService) SnapshotReCreate(id uint) error { @@ -108,20 +112,23 @@ func (u *SnapshotService) SnapshotReCreate(id uint) error { return err } go func() { - _ = handleSnapshot(req, taskItem, 0) + _ = handleSnapshot(req, taskItem, 0, 0, 0) }() return nil } -func handleSnapshot(req dto.SnapshotCreate, taskItem *task.Task, jobID uint) error { +func handleSnapshot(req dto.SnapshotCreate, taskItem *task.Task, jobID, retry, timeout uint) error { rootDir := path.Join(global.Dir.TmpDir, "system", req.Name) openrestyDir, _ := settingRepo.GetValueByKey("WEBSITE_DIR") itemHelper := snapHelper{SnapID: req.ID, Task: *taskItem, FileOp: files.NewFileOp(), Ctx: context.Background(), OpenrestyDir: openrestyDir} baseDir := path.Join(rootDir, "base") _ = os.MkdirAll(baseDir, os.ModePerm) - taskItem.AddSubTaskWithAlias( + if timeout == 0 { + timeout = 1800 + } + taskItem.AddSubTaskWithAliasAndOps( "SnapDBInfo", func(t *task.Task) error { if err := loadDbConn(&itemHelper, rootDir, req); err != nil { @@ -132,68 +139,65 @@ func handleSnapshot(req dto.SnapshotCreate, taskItem *task.Task, jobID uint) err _ = itemHelper.snapAgentDB.Where("id = ?", jobID).Delete(&model.JobRecords{}).Error } return nil - }, - nil, + }, nil, int(retry), time.Duration(timeout)*time.Second, ) if len(req.InterruptStep) == 0 || req.InterruptStep == "SnapBaseInfo" { - taskItem.AddSubTaskWithAlias( + taskItem.AddSubTaskWithAliasAndOps( "SnapBaseInfo", func(t *task.Task) error { return snapBaseData(itemHelper, baseDir) }, - nil, + nil, int(retry), time.Duration(timeout)*time.Second, ) req.InterruptStep = "" } if len(req.InterruptStep) == 0 || req.InterruptStep == "SnapInstallApp" { - taskItem.AddSubTaskWithAlias( + taskItem.AddSubTaskWithAliasAndOps( "SnapInstallApp", func(t *task.Task) error { return snapAppImage(itemHelper, req, rootDir) }, - nil, + nil, int(retry), time.Duration(timeout)*time.Second, ) req.InterruptStep = "" } if len(req.InterruptStep) == 0 || req.InterruptStep == "SnapLocalBackup" { - taskItem.AddSubTaskWithAlias( + taskItem.AddSubTaskWithAliasAndOps( "SnapLocalBackup", func(t *task.Task) error { return snapBackupData(itemHelper, req, rootDir) }, - nil, + nil, int(retry), time.Duration(timeout)*time.Second, ) req.InterruptStep = "" } if len(req.InterruptStep) == 0 || req.InterruptStep == "SnapPanelData" { - taskItem.AddSubTaskWithAlias( + taskItem.AddSubTaskWithAliasAndOps( "SnapPanelData", func(t *task.Task) error { return snapPanelData(itemHelper, req, rootDir) }, - nil, + nil, int(retry), time.Duration(timeout)*time.Second, ) req.InterruptStep = "" } - taskItem.AddSubTaskWithAlias( + taskItem.AddSubTaskWithAliasAndOps( "SnapCloseDBConn", func(t *task.Task) error { taskItem.Log("---------------------- 6 / 8 ----------------------") common.CloseDB(itemHelper.snapAgentDB) common.CloseDB(itemHelper.snapCoreDB) return nil - }, - nil, + }, nil, int(retry), time.Duration(timeout)*time.Second, ) if len(req.InterruptStep) == 0 || req.InterruptStep == "SnapCompress" { - taskItem.AddSubTaskWithAlias( + taskItem.AddSubTaskWithAliasAndOps( "SnapCompress", func(t *task.Task) error { return snapCompress(itemHelper, rootDir, req.Secret) }, - nil, + nil, int(retry), time.Duration(timeout)*time.Second, ) req.InterruptStep = "" } if len(req.InterruptStep) == 0 || req.InterruptStep == "SnapUpload" { - taskItem.AddSubTaskWithAlias( + taskItem.AddSubTaskWithAliasAndOps( "SnapUpload", func(t *task.Task) error { return snapUpload(itemHelper, req.SourceAccountIDs, fmt.Sprintf("%s.tar.gz", rootDir)) - }, - nil, + }, nil, int(retry), time.Duration(timeout)*time.Second, ) req.InterruptStep = "" } diff --git a/agent/app/task/task.go b/agent/app/task/task.go index efc794271..7e5ba3a33 100644 --- a/agent/app/task/task.go +++ b/agent/app/task/task.go @@ -3,6 +3,7 @@ package task import ( "bufio" "context" + "errors" "fmt" "log" "os" @@ -156,6 +157,11 @@ func (t *Task) AddSubTaskWithOps(name string, action ActionFunc, rollback Rollba t.SubTasks = append(t.SubTasks, subTask) } +func (t *Task) AddSubTaskWithAliasAndOps(key string, action ActionFunc, rollback RollbackFunc, retry int, timeout time.Duration) { + subTask := &SubTask{RootTask: t, Name: i18n.GetMsgByKey(key), Retry: retry, Timeout: timeout, Action: action, Rollback: rollback} + t.SubTasks = append(t.SubTasks, subTask) +} + func (t *Task) AddSubTaskWithIgnoreErr(name string, action ActionFunc) { subTask := &SubTask{RootTask: t, Name: name, Retry: 0, Timeout: 30 * time.Minute, Action: action, Rollback: nil, IgnoreErr: true} t.SubTasks = append(t.SubTasks, subTask) @@ -182,6 +188,7 @@ func (s *SubTask) Execute() error { select { case <-ctx.Done(): s.RootTask.Log(i18n.GetWithName("TaskTimeout", subTaskName)) + err = errors.New("timeout!") case err = <-done: if err != nil { s.RootTask.Log(i18n.GetWithNameAndErr("SubTaskFailed", subTaskName, err)) diff --git a/agent/i18n/lang/en.yaml b/agent/i18n/lang/en.yaml index cd46c85f7..ec454ec3a 100644 --- a/agent/i18n/lang/en.yaml +++ b/agent/i18n/lang/en.yaml @@ -192,11 +192,13 @@ ErrConfigAlreadyExist: 'A configuration file with the same name already exists' ErrUserFindErr: 'User {{ .name }} search failed {{ .err }}' #cronjob -ErrCutWebsiteLog: '{{ .name }} website log cutting failed, error {{ .err }}' CutWebsiteLogSuccess: '{{ .name }} website log cut successfully, backup path {{ .path }}' HandleShell: 'Execute script {{ .name }}' HandleNtpSync: 'System time synchronization' HandleSystemClean: 'System cache cleanup' +SystemLog: 'System Log' +CutWebsiteLog: 'Rotate Website Log' +FileOrDir: 'Directory / File' #toolbox ErrNotExistUser: 'The current user does not exist, please modify and try again!' diff --git a/agent/i18n/lang/ja.yaml b/agent/i18n/lang/ja.yaml index 2706cba61..4bc44f563 100644 --- a/agent/i18n/lang/ja.yaml +++ b/agent/i18n/lang/ja.yaml @@ -192,11 +192,13 @@ ErrConfigAlreadyExist: '同じ名前の設定ファイルがすでに存在し ErrUserFindErr: 'ユーザー {{ .name }} の検索に失敗しました {{ .err }}' #cronjob -ErrCutWebsiteLog: '{{ .name }} ウェブサイトのログの切り取りに失敗しました。エラー {{ .err }}' CutWebsiteLogSuccess: '{{ .name }} ウェブサイトのログが正常にカットされました。バックアップ パス {{ .path }}' HandleShell: 'スクリプト {{ .name }} を実行します' HandleNtpSync: 'システム時刻の同期' HandleSystemClean: 'システム キャッシュのクリーンアップ' +SystemLog: 'システムログ' +CutWebsiteLog: 'ウェブサイトログのローテーション' +FileOrDir: 'ディレクトリ / ファイル' #toolbox ErrNotExistUser: '現在のユーザーは存在しません。変更してもう一度お試しください。' diff --git a/agent/i18n/lang/ko.yaml b/agent/i18n/lang/ko.yaml index 66b6848cd..db15cfa1e 100644 --- a/agent/i18n/lang/ko.yaml +++ b/agent/i18n/lang/ko.yaml @@ -192,11 +192,13 @@ ErrConfigAlreadyExist: '같은 이름의 구성 파일이 이미 존재합니다 ErrUserFindErr: '사용자 {{ .name }} 검색에 실패했습니다 {{ .err }}' #크론잡 -ErrCutWebsiteLog: '{{ .name }} 웹사이트 로그 잘라내기에 실패했습니다. 오류 {{ .err }}' CutWebsiteLogSuccess: '{{ .name }} 웹사이트 로그가 성공적으로 잘렸습니다. 백업 경로 {{ .path }}' HandleShell: '스크립트 {{ .name }} 실행' HandleNtpSync: '시스템 시간 동기화' HandleSystemClean: '시스템 캐시 정리' +SystemLog: '시스템 로그' +CutWebsiteLog: '웹사이트 로그 회전' +FileOrDir: '디렉터리 / 파일' #도구상자 ErrNotExistUser: '현재 사용자가 존재하지 않습니다. 수정한 후 다시 시도하세요!' diff --git a/agent/i18n/lang/ms.yaml b/agent/i18n/lang/ms.yaml index f88fc716e..b850611b9 100644 --- a/agent/i18n/lang/ms.yaml +++ b/agent/i18n/lang/ms.yaml @@ -192,11 +192,13 @@ ErrConfigAlreadyExist: 'Fail konfigurasi dengan nama yang sama sudah wujud' ErrUserFindErr: 'Pengguna {{ .name }} carian gagal {{ .err }}' #cronjob -ErrCutWebsiteLog: '{{ .name }} pemotongan log tapak web gagal, ralat {{ .err }}' CutWebsiteLogSuccess: '{{ .name }} log tapak web berjaya dipotong, laluan sandaran {{ .path }}' HandleShell: 'Laksanakan skrip {{ .name }}' HandleNtpSync: 'Penyegerakan masa sistem' HandleSystemClean: 'Pembersihan cache sistem' +SystemLog: 'Log Sistem' +CutWebsiteLog: 'Putar Log Laman Web' +FileOrDir: 'Direktori / Fail' #kotak alat ErrNotExistUser: 'Pengguna semasa tidak wujud, sila ubah suai dan cuba lagi!' diff --git a/agent/i18n/lang/pt-BR.yaml b/agent/i18n/lang/pt-BR.yaml index aedd3bea9..d0458c5af 100644 --- a/agent/i18n/lang/pt-BR.yaml +++ b/agent/i18n/lang/pt-BR.yaml @@ -192,11 +192,13 @@ ErrConfigAlreadyExist: 'Um arquivo de configuração com o mesmo nome já existe ErrUserFindErr: 'Falha na pesquisa do usuário {{ .name }} {{ .err }}' #cronjob -ErrCutWebsiteLog: '{{ .name }} falha ao cortar o log do site, erro {{ .err }}' CutWebsiteLogSuccess: '{{ .name }} registro do site cortado com sucesso, caminho de backup {{ .path }}' HandleShell: 'Executar script {{ .name }}' HandleNtpSync: 'Sincronização de hora do sistema' HandleSystemClean: 'Limpeza de cache do sistema' +SystemLog: 'Log do Sistema' +CutWebsiteLog: 'Rotacionar Log do Website' +FileOrDir: 'Diretório / Arquivo' #caixa de ferramentas ErrNotExistUser: 'O usuário atual não existe, modifique e tente novamente!' diff --git a/agent/i18n/lang/ru.yaml b/agent/i18n/lang/ru.yaml index fe07cd0b2..f92b10893 100644 --- a/agent/i18n/lang/ru.yaml +++ b/agent/i18n/lang/ru.yaml @@ -192,11 +192,13 @@ ErrConfigAlreadyExist: 'Файл конфигурации с таким имен ErrUserFindErr: 'Поиск пользователя {{ .name }} не удался {{ .err }}' #cronjob -ErrCutWebsiteLog: '{{ .name }} не удалось вырезать журнал веб-сайта, ошибка {{ .err }}' CutWebsiteLogSuccess: 'Журнал веб-сайта {{ .name }} успешно вырезан, путь к резервной копии {{ .path }}' HandleShell: 'Выполнить скрипт {{ .name }}' HandleNtpSync: 'Синхронизация системного времени' HandleSystemClean: 'Очистка системного кэша' +SystemLog: 'Системный лог' +CutWebsiteLog: 'Ротация логов сайта' +FileOrDir: 'Каталог / Файл' #ящик для инструментов ErrNotExistUser: 'Текущий пользователь не существует, измените его и повторите попытку!' diff --git a/agent/i18n/lang/zh-Hant.yaml b/agent/i18n/lang/zh-Hant.yaml index 223198ca2..376462718 100644 --- a/agent/i18n/lang/zh-Hant.yaml +++ b/agent/i18n/lang/zh-Hant.yaml @@ -192,11 +192,13 @@ ErrConfigAlreadyExist: '已存在同名設定檔' ErrUserFindErr: '使用者{{ .name }} 尋找失敗{{ .err }}' #cronjob -ErrCutWebsiteLog: '{{ .name }} 網站日誌切割失敗,錯誤{{ .err }}' CutWebsiteLogSuccess: '{{ .name }} 網站日誌切割成功,備份路徑{{ .path }}' HandleShell: '執行腳本{{ .name }}' HandleNtpSync: '系統時間同步' HandleSystemClean: '系統快取清理' +SystemLog: '系統日誌' +CutWebsiteLog: '切割網站日誌' +FileOrDir: '目錄 / 檔案' #toolbox ErrNotExistUser: '目前使用者不存在,請修改後重試!' diff --git a/agent/i18n/lang/zh.yaml b/agent/i18n/lang/zh.yaml index 7722679e3..d6e47f4cf 100644 --- a/agent/i18n/lang/zh.yaml +++ b/agent/i18n/lang/zh.yaml @@ -191,11 +191,13 @@ ErrConfigAlreadyExist: "已存在同名配置文件" ErrUserFindErr: "用户 {{ .name }} 查找失败 {{ .err }}" #cronjob -ErrCutWebsiteLog: "{{ .name }} 网站日志切割失败,错误 {{ .err }}" CutWebsiteLogSuccess: "{{ .name }} 网站日志切割成功,备份路径 {{ .path }}" HandleShell: "执行脚本 {{ .name }}" HandleNtpSync: "系统时间同步" HandleSystemClean: "系统缓存清理" +SystemLog: "系统日志" +CutWebsiteLog: "切割网站日志" +FileOrDir: "目录 / 文件" #toolbox ErrNotExistUser: "当前用户不存在,请修改后重试!" diff --git a/agent/utils/files/file_op.go b/agent/utils/files/file_op.go index f017f60f2..c7460c950 100644 --- a/agent/utils/files/file_op.go +++ b/agent/utils/files/file_op.go @@ -742,7 +742,7 @@ func (f FileOp) TarGzCompressPro(withDir bool, src, dst, secret, exclusionRules itemPrefix = "" } if len(secret) != 0 { - commands = fmt.Sprintf("tar --warning=no-file-changed --ignore-failed-read --exclude-from=<(find %s -type s -printf '%s' | sed 's|^|%s/|') -zcf - %s | openssl enc -aes-256-cbc -salt -k '%s' -out %s", src, "%P\n", itemPrefix, srcItem, secret, dst) + commands = fmt.Sprintf("tar --warning=no-file-changed --ignore-failed-read %s --exclude-from=<(find %s -type s -printf '%s' | sed 's|^|%s/|') -zcf - %s | openssl enc -aes-256-cbc -salt -k '%s' -out %s", exStr, src, "%P\n", itemPrefix, srcItem, secret, dst) global.LOG.Debug(strings.ReplaceAll(commands, fmt.Sprintf(" %s ", secret), "******")) } else { commands = fmt.Sprintf("tar --warning=no-file-changed --ignore-failed-read --exclude-from=<(find %s -type s -printf '%s' | sed 's|^|%s/|') -zcf %s %s %s", src, "%P\n", itemPrefix, dst, exStr, srcItem)