Skip to content

Commit ba1d65f

Browse files
authored
feat: The result of the scheduled task execution is based on the task (#7586)
1 parent 72c86c3 commit ba1d65f

File tree

23 files changed

+435
-263
lines changed

23 files changed

+435
-263
lines changed

agent/app/api/v2/snapshot.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func (b *BaseApi) CreateSnapshot(c *gin.Context) {
3636
return
3737
}
3838

39-
if err := snapshotService.SnapshotCreate(req); err != nil {
39+
if err := snapshotService.SnapshotCreate(req, false); err != nil {
4040
helper.InternalServer(c, err)
4141
return
4242
}

agent/app/dto/cronjob.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ type SearchRecord struct {
134134

135135
type Record struct {
136136
ID uint `json:"id"`
137+
TaskID string `json:"taskID"`
137138
StartTime string `json:"startTime"`
138139
Records string `json:"records"`
139140
Status string `json:"status"`

agent/app/repo/cronjob.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"github.com/1Panel-dev/1Panel/agent/app/model"
77
"github.com/1Panel-dev/1Panel/agent/constant"
88
"github.com/1Panel-dev/1Panel/agent/global"
9+
"github.com/google/uuid"
910
"gorm.io/gorm"
1011
)
1112

@@ -146,6 +147,7 @@ func (u *CronjobRepo) StartRecords(cronjobID uint, targetPath string) model.JobR
146147
var record model.JobRecords
147148
record.StartTime = time.Now()
148149
record.CronjobID = cronjobID
150+
record.TaskID = uuid.New().String()
149151
record.Status = constant.StatusWaiting
150152
if err := global.DB.Create(&record).Error; err != nil {
151153
global.LOG.Errorf("create record status failed, err: %v", err)

agent/app/service/cronjob_backup.go

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import (
1717
"github.com/pkg/errors"
1818
)
1919

20-
func (u *CronjobService) handleApp(cronjob model.Cronjob, startTime time.Time) error {
20+
func (u *CronjobService) handleApp(cronjob model.Cronjob, startTime time.Time, taskID string) error {
2121
var apps []model.AppInstall
2222
if cronjob.AppID == "all" {
2323
apps, _ = appInstallRepo.ListBy()
@@ -46,7 +46,7 @@ func (u *CronjobService) handleApp(cronjob model.Cronjob, startTime time.Time) e
4646
record.DownloadAccountID, record.SourceAccountIDs = cronjob.DownloadAccountID, cronjob.SourceAccountIDs
4747
backupDir := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("app/%s/%s", app.App.Key, app.Name))
4848
record.FileName = fmt.Sprintf("app_%s_%s.tar.gz", app.Name, startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5))
49-
if err := handleAppBackup(&app, nil, backupDir, record.FileName, cronjob.ExclusionRules, cronjob.Secret, ""); err != nil {
49+
if err := handleAppBackup(&app, nil, backupDir, record.FileName, cronjob.ExclusionRules, cronjob.Secret, taskID); err != nil {
5050
return err
5151
}
5252
downloadPath, err := u.uploadCronjobBackFile(cronjob, accountMap, path.Join(backupDir, record.FileName))
@@ -63,7 +63,7 @@ func (u *CronjobService) handleApp(cronjob model.Cronjob, startTime time.Time) e
6363
return nil
6464
}
6565

66-
func (u *CronjobService) handleWebsite(cronjob model.Cronjob, startTime time.Time) error {
66+
func (u *CronjobService) handleWebsite(cronjob model.Cronjob, startTime time.Time, taskID string) error {
6767
webs := loadWebsForJob(cronjob)
6868
if len(webs) == 0 {
6969
return errors.New("no such website in database!")
@@ -82,7 +82,7 @@ func (u *CronjobService) handleWebsite(cronjob model.Cronjob, startTime time.Tim
8282
record.DownloadAccountID, record.SourceAccountIDs = cronjob.DownloadAccountID, cronjob.SourceAccountIDs
8383
backupDir := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("website/%s", web.PrimaryDomain))
8484
record.FileName = fmt.Sprintf("website_%s_%s.tar.gz", web.PrimaryDomain, startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5))
85-
if err := handleWebsiteBackup(&web, backupDir, record.FileName, cronjob.ExclusionRules, cronjob.Secret, ""); err != nil {
85+
if err := handleWebsiteBackup(&web, backupDir, record.FileName, cronjob.ExclusionRules, cronjob.Secret, taskID); err != nil {
8686
return err
8787
}
8888
downloadPath, err := u.uploadCronjobBackFile(cronjob, accountMap, path.Join(backupDir, record.FileName))
@@ -99,7 +99,7 @@ func (u *CronjobService) handleWebsite(cronjob model.Cronjob, startTime time.Tim
9999
return nil
100100
}
101101

102-
func (u *CronjobService) handleDatabase(cronjob model.Cronjob, startTime time.Time) error {
102+
func (u *CronjobService) handleDatabase(cronjob model.Cronjob, startTime time.Time, taskID string) error {
103103
dbs := loadDbsForJob(cronjob)
104104
if len(dbs) == 0 {
105105
return errors.New("no such db in database!")
@@ -120,11 +120,11 @@ func (u *CronjobService) handleDatabase(cronjob model.Cronjob, startTime time.Ti
120120
backupDir := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("database/%s/%s/%s", dbInfo.DBType, record.Name, dbInfo.Name))
121121
record.FileName = fmt.Sprintf("db_%s_%s.sql.gz", dbInfo.Name, startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5))
122122
if cronjob.DBType == "mysql" || cronjob.DBType == "mariadb" {
123-
if err := handleMysqlBackup(dbInfo, nil, backupDir, record.FileName, ""); err != nil {
123+
if err := handleMysqlBackup(dbInfo, nil, backupDir, record.FileName, taskID); err != nil {
124124
return err
125125
}
126126
} else {
127-
if err := handlePostgresqlBackup(dbInfo, nil, backupDir, record.FileName, ""); err != nil {
127+
if err := handlePostgresqlBackup(dbInfo, nil, backupDir, record.FileName, taskID); err != nil {
128128
return err
129129
}
130130
}
@@ -212,11 +212,15 @@ func (u *CronjobService) handleSystemLog(cronjob model.Cronjob, startTime time.T
212212
return nil
213213
}
214214

215-
func (u *CronjobService) handleSnapshot(cronjob model.Cronjob, startTime time.Time) error {
215+
func (u *CronjobService) handleSnapshot(cronjob model.Cronjob, startTime time.Time, taskID string) error {
216216
accountMap, err := NewBackupClientMap(strings.Split(cronjob.SourceAccountIDs, ","))
217217
if err != nil {
218218
return err
219219
}
220+
itemData, err := NewISnapshotService().LoadSnapshotData()
221+
if err != nil {
222+
return err
223+
}
220224

221225
var record model.BackupRecord
222226
record.From = "cronjob"
@@ -227,14 +231,28 @@ func (u *CronjobService) handleSnapshot(cronjob model.Cronjob, startTime time.Ti
227231
record.FileDir = "system_snapshot"
228232

229233
versionItem, _ := settingRepo.Get(settingRepo.WithByKey("SystemVersion"))
234+
scope := "core"
235+
if !global.IsMaster {
236+
scope = "agent"
237+
}
230238
req := dto.SnapshotCreate{
231-
Name: fmt.Sprintf("snapshot-1panel-%s-linux-%s-%s", versionItem.Value, loadOs(), startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5)),
239+
Name: fmt.Sprintf("snapshot-1panel-%s-%s-linux-%s-%s", scope, versionItem.Value, loadOs(), startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5)),
232240
Secret: cronjob.Secret,
241+
TaskID: taskID,
233242

234243
SourceAccountIDs: record.SourceAccountIDs,
235244
DownloadAccountID: cronjob.DownloadAccountID,
245+
AppData: itemData.AppData,
246+
PanelData: itemData.PanelData,
247+
BackupData: itemData.BackupData,
248+
WithMonitorData: true,
249+
WithLoginLog: true,
250+
WithOperationLog: true,
251+
WithSystemLog: true,
252+
WithTaskLog: true,
236253
}
237-
if err := NewISnapshotService().HandleSnapshot(req); err != nil {
254+
255+
if err := NewISnapshotService().SnapshotCreate(req, true); err != nil {
238256
return err
239257
}
240258
record.FileName = req.Name + ".tar.gz"

agent/app/service/cronjob_helper.go

Lines changed: 92 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010

1111
"github.com/1Panel-dev/1Panel/agent/app/model"
1212
"github.com/1Panel-dev/1Panel/agent/app/repo"
13+
"github.com/1Panel-dev/1Panel/agent/app/task"
1314
"github.com/1Panel-dev/1Panel/agent/buserr"
1415
"github.com/1Panel-dev/1Panel/agent/constant"
1516
"github.com/1Panel-dev/1Panel/agent/global"
@@ -31,36 +32,26 @@ func (u *CronjobService) HandleJob(cronjob *model.Cronjob) {
3132
if len(cronjob.Script) == 0 {
3233
return
3334
}
34-
record.Records = u.generateLogsPath(*cronjob, record.StartTime)
35-
_ = cronjobRepo.UpdateRecords(record.ID, map[string]interface{}{"records": record.Records})
36-
err = u.handleShell(*cronjob, record.Records)
37-
u.removeExpiredLog(*cronjob)
35+
err = u.handleShell(*cronjob, record.TaskID)
3836
case "curl":
3937
if len(cronjob.URL) == 0 {
4038
return
4139
}
42-
record.Records = u.generateLogsPath(*cronjob, record.StartTime)
43-
_ = cronjobRepo.UpdateRecords(record.ID, map[string]interface{}{"records": record.Records})
44-
err = cmd.ExecShell(record.Records, 24*time.Hour, "bash", "-c", "curl", cronjob.URL)
45-
u.removeExpiredLog(*cronjob)
40+
err = u.handleCurl(*cronjob, record.TaskID)
4641
case "ntp":
47-
err = u.handleNtpSync()
48-
u.removeExpiredLog(*cronjob)
42+
err = u.handleNtpSync(*cronjob, record.TaskID)
4943
case "cutWebsiteLog":
5044
var messageItem []string
5145
messageItem, record.File, err = u.handleCutWebsiteLog(cronjob, record.StartTime)
5246
message = []byte(strings.Join(messageItem, "\n"))
5347
case "clean":
54-
messageItem := ""
55-
messageItem, err = u.handleSystemClean()
56-
message = []byte(messageItem)
57-
u.removeExpiredLog(*cronjob)
48+
err = u.handleSystemClean(*cronjob, record.TaskID)
5849
case "website":
59-
err = u.handleWebsite(*cronjob, record.StartTime)
50+
err = u.handleWebsite(*cronjob, record.StartTime, record.TaskID)
6051
case "app":
61-
err = u.handleApp(*cronjob, record.StartTime)
52+
err = u.handleApp(*cronjob, record.StartTime, record.TaskID)
6253
case "database":
63-
err = u.handleDatabase(*cronjob, record.StartTime)
54+
err = u.handleDatabase(*cronjob, record.StartTime, record.TaskID)
6455
case "directory":
6556
if len(cronjob.SourceDir) == 0 {
6657
return
@@ -70,7 +61,7 @@ func (u *CronjobService) HandleJob(cronjob *model.Cronjob) {
7061
err = u.handleSystemLog(*cronjob, record.StartTime)
7162
case "snapshot":
7263
_ = cronjobRepo.UpdateRecords(record.ID, map[string]interface{}{"records": record.Records})
73-
err = u.handleSnapshot(*cronjob, record.StartTime)
64+
err = u.handleSnapshot(*cronjob, record.StartTime, record.TaskID)
7465
}
7566

7667
if err != nil {
@@ -90,53 +81,95 @@ func (u *CronjobService) HandleJob(cronjob *model.Cronjob) {
9081
}()
9182
}
9283

93-
func (u *CronjobService) handleShell(cronjob model.Cronjob, logPath string) error {
94-
if len(cronjob.ContainerName) != 0 {
95-
command := "sh"
96-
if len(cronjob.Command) != 0 {
97-
command = cronjob.Command
98-
}
99-
scriptFile, _ := os.ReadFile(cronjob.Script)
100-
return cmd.ExecShell(logPath, 24*time.Hour, "docker", "exec", cronjob.ContainerName, command, "-c", strings.ReplaceAll(string(scriptFile), "\"", "\\\""))
101-
}
102-
if len(cronjob.Executor) == 0 {
103-
cronjob.Executor = "bash"
84+
func (u *CronjobService) handleShell(cronjob model.Cronjob, taskID string) error {
85+
taskItem, err := task.NewTaskWithOps(fmt.Sprintf("cronjob-%s", cronjob.Name), task.TaskHandle, task.TaskScopeCronjob, taskID, cronjob.ID)
86+
if err != nil {
87+
global.LOG.Errorf("new task for exec shell failed, err: %v", err)
88+
return err
10489
}
105-
if cronjob.ScriptMode == "input" {
106-
fileItem := pathUtils.Join(global.CONF.System.BaseDir, "1panel", "task", "shell", cronjob.Name, cronjob.Name+".sh")
107-
_ = os.MkdirAll(pathUtils.Dir(fileItem), os.ModePerm)
108-
shellFile, err := os.OpenFile(fileItem, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, constant.FilePerm)
109-
if err != nil {
110-
return err
90+
91+
taskItem.AddSubTask(i18n.GetWithName("HandleShell", cronjob.Name), func(t *task.Task) error {
92+
if len(cronjob.ContainerName) != 0 {
93+
command := "sh"
94+
if len(cronjob.Command) != 0 {
95+
command = cronjob.Command
96+
}
97+
scriptFile, _ := os.ReadFile(cronjob.Script)
98+
return cmd.ExecShellWithTask(taskItem, 24*time.Hour, "docker", "exec", cronjob.ContainerName, command, "-c", strings.ReplaceAll(string(scriptFile), "\"", "\\\""))
11199
}
112-
defer shellFile.Close()
113-
if _, err := shellFile.WriteString(cronjob.Script); err != nil {
114-
return err
100+
if len(cronjob.Executor) == 0 {
101+
cronjob.Executor = "bash"
102+
}
103+
if cronjob.ScriptMode == "input" {
104+
fileItem := pathUtils.Join(global.CONF.System.BaseDir, "1panel", "task", "shell", cronjob.Name, cronjob.Name+".sh")
105+
_ = os.MkdirAll(pathUtils.Dir(fileItem), os.ModePerm)
106+
shellFile, err := os.OpenFile(fileItem, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, constant.FilePerm)
107+
if err != nil {
108+
return err
109+
}
110+
defer shellFile.Close()
111+
if _, err := shellFile.WriteString(cronjob.Script); err != nil {
112+
return err
113+
}
114+
if len(cronjob.User) == 0 {
115+
return cmd.ExecShellWithTask(taskItem, 24*time.Hour, cronjob.Executor, fileItem)
116+
}
117+
return cmd.ExecShellWithTask(taskItem, 24*time.Hour, "sudo", "-u", cronjob.User, cronjob.Executor, fileItem)
115118
}
116119
if len(cronjob.User) == 0 {
117-
return cmd.ExecShell(logPath, 24*time.Hour, cronjob.Executor, fileItem)
120+
return cmd.ExecShellWithTask(taskItem, 24*time.Hour, cronjob.Executor, cronjob.Script)
118121
}
119-
return cmd.ExecShell(logPath, 24*time.Hour, "sudo", "-u", cronjob.User, cronjob.Executor, fileItem)
120-
}
121-
if len(cronjob.User) == 0 {
122-
return cmd.ExecShell(logPath, 24*time.Hour, cronjob.Executor, cronjob.Script)
123-
}
124-
return cmd.ExecShell(logPath, 24*time.Hour, "sudo", "-u", cronjob.User, cronjob.Executor, cronjob.Script)
122+
if err := cmd.ExecShellWithTask(taskItem, 24*time.Hour, "sudo", "-u", cronjob.User, cronjob.Executor, cronjob.Script); err != nil {
123+
return err
124+
}
125+
return nil
126+
},
127+
nil,
128+
)
129+
return taskItem.Execute()
125130
}
126131

127-
func (u *CronjobService) handleNtpSync() error {
128-
ntpServer, err := settingRepo.Get(settingRepo.WithByKey("NtpSite"))
132+
func (u *CronjobService) handleCurl(cronjob model.Cronjob, taskID string) error {
133+
taskItem, err := task.NewTaskWithOps(fmt.Sprintf("cronjob-%s", cronjob.Name), task.TaskHandle, task.TaskScopeCronjob, taskID, cronjob.ID)
129134
if err != nil {
135+
global.LOG.Errorf("new task for exec shell failed, err: %v", err)
130136
return err
131137
}
132-
ntime, err := ntp.GetRemoteTime(ntpServer.Value)
138+
139+
taskItem.AddSubTask(i18n.GetWithName("HandleShell", cronjob.Name), func(t *task.Task) error {
140+
if err := cmd.ExecShellWithTask(taskItem, 24*time.Hour, "bash", "-c", "curl", cronjob.URL); err != nil {
141+
return err
142+
}
143+
return nil
144+
},
145+
nil,
146+
)
147+
return taskItem.Execute()
148+
}
149+
150+
func (u *CronjobService) handleNtpSync(cronjob model.Cronjob, taskID string) error {
151+
taskItem, err := task.NewTaskWithOps(fmt.Sprintf("cronjob-%s", cronjob.Name), task.TaskHandle, task.TaskScopeCronjob, taskID, cronjob.ID)
133152
if err != nil {
153+
global.LOG.Errorf("new task for exec shell failed, err: %v", err)
134154
return err
135155
}
136-
if err := ntp.UpdateSystemTime(ntime.Format(constant.DateTimeLayout)); err != nil {
137-
return err
138-
}
139-
return nil
156+
157+
taskItem.AddSubTask(i18n.GetMsgByKey("HandleNtpSync"), func(t *task.Task) error {
158+
ntpServer, err := settingRepo.Get(settingRepo.WithByKey("NtpSite"))
159+
if err != nil {
160+
return err
161+
}
162+
taskItem.Logf("ntp server: %s", ntpServer.Value)
163+
ntime, err := ntp.GetRemoteTime(ntpServer.Value)
164+
if err != nil {
165+
return err
166+
}
167+
if err := ntp.UpdateSystemTime(ntime.Format(constant.DateTimeLayout)); err != nil {
168+
return err
169+
}
170+
return nil
171+
}, nil)
172+
return taskItem.Execute()
140173
}
141174

142175
func (u *CronjobService) handleCutWebsiteLog(cronjob *model.Cronjob, startTime time.Time) ([]string, string, error) {
@@ -201,8 +234,13 @@ func backupLogFile(dstFilePath, websiteLogDir string, fileOp files.FileOp) error
201234
return nil
202235
}
203236

204-
func (u *CronjobService) handleSystemClean() (string, error) {
205-
return NewIDeviceService().CleanForCronjob()
237+
func (u *CronjobService) handleSystemClean(cronjob model.Cronjob, taskID string) error {
238+
taskItem, err := task.NewTaskWithOps(fmt.Sprintf("cronjob-%s", cronjob.Name), task.TaskHandle, task.TaskScopeCronjob, taskID, cronjob.ID)
239+
if err != nil {
240+
global.LOG.Errorf("new task for system clean failed, err: %v", err)
241+
return err
242+
}
243+
return systemClean(taskItem)
206244
}
207245

208246
func (u *CronjobService) uploadCronjobBackFile(cronjob model.Cronjob, accountMap map[string]backupClientHelper, file string) (string, error) {
@@ -274,16 +312,6 @@ func (u *CronjobService) removeExpiredLog(cronjob model.Cronjob) {
274312
}
275313
}
276314

277-
func (u *CronjobService) generateLogsPath(cronjob model.Cronjob, startTime time.Time) string {
278-
dir := fmt.Sprintf("%s/task/%s/%s", constant.DataDir, cronjob.Type, cronjob.Name)
279-
if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) {
280-
_ = os.MkdirAll(dir, os.ModePerm)
281-
}
282-
283-
path := fmt.Sprintf("%s/%s.log", dir, startTime.Format(constant.DateTimeSlimLayout))
284-
return path
285-
}
286-
287315
func hasBackup(cronjobType string) bool {
288316
return cronjobType == "app" || cronjobType == "database" || cronjobType == "website" || cronjobType == "directory" || cronjobType == "snapshot" || cronjobType == "log"
289317
}

agent/app/service/device.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ type IDeviceService interface {
4141

4242
Scan() dto.CleanData
4343
Clean(req []dto.Clean)
44-
CleanForCronjob() (string, error)
4544
}
4645

4746
func NewIDeviceService() IDeviceService {

0 commit comments

Comments
 (0)