diff --git a/backend/app/service/cronjob_helper.go b/backend/app/service/cronjob_helper.go index b0212b45a..7e8cbd473 100644 --- a/backend/app/service/cronjob_helper.go +++ b/backend/app/service/cronjob_helper.go @@ -69,6 +69,8 @@ func (u *CronjobService) HandleJob(cronjob *model.Cronjob) { messageItem, err = u.handleSystemClean() message = []byte(messageItem) u.HandleRmExpired("LOCAL", "", "", cronjob, nil) + case "log": + record.File, err = u.handleSystemLog(*cronjob, record.StartTime) } if err != nil { @@ -593,3 +595,99 @@ func (u *CronjobService) handleSnapshot(cronjob *model.Cronjob, startTime time.T func (u *CronjobService) handleSystemClean() (string, error) { return NewISettingService().SystemCleanForCronjob() } + +func (u *CronjobService) handleSystemLog(cronjob model.Cronjob, startTime time.Time) (string, error) { + websites, err := websiteRepo.List() + if err != nil { + return "", err + } + backup, err := backupRepo.Get(commonRepo.WithByID(uint(cronjob.TargetDirID))) + if err != nil { + return "", err + } + + pathItem := path.Join(global.CONF.System.BaseDir, "1panel/tmp/log", startTime.Format("20060102150405")) + nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) + if err != nil { + return "", err + } + webItem := path.Join(nginxInstall.GetPath(), "www/sites") + for _, website := range websites { + dirItem := path.Join(pathItem, "website", website.Alias) + if _, err := os.Stat(dirItem); err != nil && os.IsNotExist(err) { + if err = os.MkdirAll(dirItem, os.ModePerm); err != nil { + return "", err + } + } + itemDir := path.Join(webItem, website.Alias, "log") + logFiles, _ := os.ReadDir(itemDir) + if len(logFiles) != 0 { + for i := 0; i < len(logFiles); i++ { + if !logFiles[i].IsDir() { + _ = cpBinary([]string{path.Join(itemDir, logFiles[i].Name())}, dirItem) + } + } + } + itemDir2 := path.Join(global.CONF.System.Backup, "log/website", website.Alias) + logFiles2, _ := os.ReadDir(itemDir2) + if len(logFiles2) != 0 { + for i := 0; i < len(logFiles2); i++ { + if !logFiles2[i].IsDir() { + _ = cpBinary([]string{path.Join(itemDir2, logFiles2[i].Name())}, dirItem) + } + } + } + } + + systemLogDir := path.Join(global.CONF.System.BaseDir, "1panel/log") + systemDir := path.Join(pathItem, "system") + if _, err := os.Stat(systemDir); err != nil && os.IsNotExist(err) { + if err = os.MkdirAll(systemDir, os.ModePerm); err != nil { + return "", err + } + } + systemLogFiles, _ := os.ReadDir(systemLogDir) + if len(systemLogFiles) != 0 { + for i := 0; i < len(systemLogFiles); i++ { + if !systemLogFiles[i].IsDir() { + _ = cpBinary([]string{path.Join(systemLogDir, systemLogFiles[i].Name())}, systemDir) + } + } + } + loginLogFiles, _ := os.ReadDir("/var/log") + loginDir := path.Join(pathItem, "login") + if _, err := os.Stat(loginDir); err != nil && os.IsNotExist(err) { + if err = os.MkdirAll(loginDir, os.ModePerm); err != nil { + return "", err + } + } + if len(loginLogFiles) != 0 { + for i := 0; i < len(loginLogFiles); i++ { + if !loginLogFiles[i].IsDir() && (strings.HasPrefix(loginLogFiles[i].Name(), "secure") || strings.HasPrefix(loginLogFiles[i].Name(), "auth.log")) { + _ = cpBinary([]string{path.Join("/var/log", loginLogFiles[i].Name())}, loginDir) + } + } + } + + fileName := fmt.Sprintf("system_log_%s.tar.gz", startTime.Format("20060102150405")) + if err := handleTar(pathItem, pathItem, fileName, ""); err != nil { + return "", err + } + + client, err := NewIBackupService().NewClient(&backup) + if err != nil { + return "", err + } + + targetPath := "log/" + fileName + if len(backup.BackupPath) != 0 { + targetPath = strings.TrimPrefix(backup.BackupPath, "/") + "/log/" + fileName + } + + if _, err = client.Upload(path.Join(pathItem, fileName), targetPath); err != nil { + return "", err + } + + u.HandleRmExpired(backup.Type, backup.BackupPath, "", &cronjob, client) + return targetPath, nil +} diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index 2c21a15d7..2785e4e7f 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -733,6 +733,7 @@ const message = { taskType: 'Cronjob type', record: 'Records', shell: 'Shell script', + log: 'Backup logs', containerCheckBox: 'In container (no need to enter the container command)', containerName: 'Container name', ntp: 'Time synchronization', diff --git a/frontend/src/lang/modules/tw.ts b/frontend/src/lang/modules/tw.ts index 00451b8c8..508dc766b 100644 --- a/frontend/src/lang/modules/tw.ts +++ b/frontend/src/lang/modules/tw.ts @@ -705,6 +705,7 @@ const message = { taskType: '任務類型', record: '報告', shell: 'Shell 腳本', + log: '日誌備份', containerCheckBox: '在容器中執行(無需再輸入進入容器命令)', containerName: '容器名稱', ntp: '時間同步', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 33ca43f35..21a7978d6 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -706,6 +706,7 @@ const message = { taskType: '任务类型', record: '报告', shell: 'Shell 脚本', + log: '日志备份', containerCheckBox: '在容器中执行(无需再输入进入容器命令)', containerName: '容器名称', ntp: '时间同步', diff --git a/frontend/src/views/cronjob/operate/index.vue b/frontend/src/views/cronjob/operate/index.vue index 1616d2474..df920779b 100644 --- a/frontend/src/views/cronjob/operate/index.vue +++ b/frontend/src/views/cronjob/operate/index.vue @@ -28,6 +28,7 @@ + {{ $t('cronjob.' + dialogData.rowData!.type) }} @@ -176,7 +177,7 @@
@@ -195,7 +196,7 @@ {{ $t('cronjob.saveLocal') }} @@ -454,12 +455,14 @@ const changeType = () => { dialogData.value.rowData.hour = 2; dialogData.value.rowData.minute = 30; break; + case 'clean': case 'website': dialogData.value.rowData.specType = 'perWeek'; dialogData.value.rowData.week = 1; dialogData.value.rowData.hour = 1; dialogData.value.rowData.minute = 30; break; + case 'log': case 'snapshot': dialogData.value.rowData.specType = 'perWeek'; dialogData.value.rowData.week = 1; @@ -531,7 +534,8 @@ function isBackup() { dialogData.value.rowData!.type === 'website' || dialogData.value.rowData!.type === 'database' || dialogData.value.rowData!.type === 'directory' || - dialogData.value.rowData!.type === 'snapshot' + dialogData.value.rowData!.type === 'snapshot' || + dialogData.value.rowData!.type === 'log' ); }