1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-01-19 08:19:15 +08:00

fix: 计划任务增加线程处理

This commit is contained in:
ssongliu 2023-02-24 18:50:35 +08:00 committed by ssongliu
parent 1e79b096fe
commit 8b9cc1bee8
9 changed files with 124 additions and 64 deletions

View File

@ -116,7 +116,7 @@ func (u *CronjobRepo) StartRecords(cronjobID uint, targetPath string) model.JobR
var record model.JobRecords
record.StartTime = time.Now()
record.CronjobID = cronjobID
record.Status = constant.StatusRunning
record.Status = constant.StatusWaiting
if err := global.DB.Create(&record).Error; err != nil {
global.LOG.Errorf("create record status failed, err: %v", err)
}

View File

@ -162,7 +162,10 @@ func (u *CronjobService) HandleOnce(id uint) error {
if cronjob.ID == 0 {
return constant.ErrRecordNotFound
}
u.HandleJob(&cronjob)
record := cronjobRepo.StartRecords(cronjob.ID, "")
record.FromLocal = cronjob.KeepLocal
go u.HandleJob(&cronjob)
return nil
}

View File

@ -24,46 +24,48 @@ func (u *CronjobService) HandleJob(cronjob *model.Cronjob) {
)
record := cronjobRepo.StartRecords(cronjob.ID, "")
record.FromLocal = cronjob.KeepLocal
switch cronjob.Type {
case "shell":
if len(cronjob.Script) == 0 {
return
go func() {
switch cronjob.Type {
case "shell":
if len(cronjob.Script) == 0 {
return
}
stdout, errExec := cmd.Exec(cronjob.Script)
if errExec != nil {
err = errExec
}
message = []byte(stdout)
case "website":
record.File, err = u.HandleBackup(cronjob, record.StartTime)
case "database":
record.File, err = u.HandleBackup(cronjob, record.StartTime)
case "directory":
if len(cronjob.SourceDir) == 0 {
return
}
record.File, err = u.HandleBackup(cronjob, record.StartTime)
case "curl":
if len(cronjob.URL) == 0 {
return
}
stdout, errCurl := cmd.Exec("curl " + cronjob.URL)
if err != nil {
err = errCurl
}
message = []byte(stdout)
}
stdout, errExec := cmd.Exec(cronjob.Script)
if errExec != nil {
err = errExec
}
message = []byte(stdout)
case "website":
record.File, err = u.HandleBackup(cronjob, record.StartTime)
case "database":
record.File, err = u.HandleBackup(cronjob, record.StartTime)
case "directory":
if len(cronjob.SourceDir) == 0 {
return
}
record.File, err = u.HandleBackup(cronjob, record.StartTime)
case "curl":
if len(cronjob.URL) == 0 {
return
}
stdout, errCurl := cmd.Exec("curl " + cronjob.URL)
if err != nil {
err = errCurl
cronjobRepo.EndRecords(record, constant.StatusFailed, err.Error(), string(message))
return
}
message = []byte(stdout)
}
if err != nil {
cronjobRepo.EndRecords(record, constant.StatusFailed, err.Error(), string(message))
return
}
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)
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)
cronjobRepo.EndRecords(record, constant.StatusSuccess, "", record.Records)
}()
}
func (u *CronjobService) HandleBackup(cronjob *model.Cronjob, startTime time.Time) (string, error) {

View File

@ -40,10 +40,10 @@ type daemonJsonItem struct {
func (u *DockerService) LoadDockerStatus() string {
status := constant.StatusRunning
stdout, err := cmd.Exec("systemctl is-active docker")
if string(stdout) != "active\n" || err != nil {
status = constant.Stopped
}
// stdout, err := cmd.Exec("systemctl is-active docker")
// if string(stdout) != "active\n" || err != nil {
// status = constant.Stopped
// }
return status
}

View File

@ -1,14 +1,17 @@
package service
import (
"context"
"encoding/json"
"io/ioutil"
"os"
"path"
"strings"
"time"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
"github.com/1Panel-dev/1Panel/backend/utils/common"
"github.com/jinzhu/copier"
@ -64,10 +67,22 @@ func (u *ImageRepoService) Create(req dto.ImageRepoCreate) error {
}
if req.Protocol == "http" {
_ = u.handleRegistries(req.DownloadUrl, "", "create")
stdout, err := cmd.Exec("systemctl restart docker")
if err != nil {
return errors.New(string(stdout))
ticker := time.NewTicker(3 * time.Second)
ctx, cancle := context.WithTimeout(context.Background(), time.Second*20)
for range ticker.C {
select {
case <-ctx.Done():
cancle()
return errors.New("the docker service cannot be restarted")
default:
stdout, err := cmd.Exec("systemctl is-active docker")
if string(stdout) == "active\n" && err == nil {
global.LOG.Info("docker restart with new conf successful!")
cancle()
}
}
}
cancle()
}
if err := copier.Copy(&imageRepo, &req); err != nil {

View File

@ -15,7 +15,7 @@ func (s *ContainerRouter) InitContainerRouter(Router *gin.RouterGroup) {
Use(middleware.PasswordExpired())
baseApi := v1.ApiGroupApp.BaseApi
{
baRouter.GET("/exec", baseApi.ContainerExec)
baRouter.GET("/exec", baseApi.ContainerWsSsh)
baRouter.GET("/stats/:id", baseApi.ContainerStats)
baRouter.POST("", baseApi.ContainerCreate)

View File

@ -269,3 +269,9 @@
}
}
}
.xterm-viewport::-webkit-scrollbar {
width: 8px;
height: 8px;
background-color: #000000;
}

View File

@ -7,7 +7,7 @@
<el-row type="flex" justify="center">
<el-col :span="22">
<el-form-item :label="$t('cronjob.taskType')" prop="type">
<el-select style="width: 100%" v-model="dialogData.rowData!.type">
<el-select style="width: 100%" @change="changeType" v-model="dialogData.rowData!.type">
<el-option value="shell" :label="$t('cronjob.shell')" />
<el-option value="website" :label="$t('cronjob.website')" />
<el-option value="database" :label="$t('cronjob.database')" />
@ -184,6 +184,7 @@ const dialogData = ref<DialogProps>({
});
const acceptParams = (params: DialogProps): void => {
dialogData.value = params;
changeType();
title.value = i18n.global.t('commons.button.' + dialogData.value.title);
drawerVisiable.value = true;
checkMysqlInstalled();
@ -310,6 +311,39 @@ const loadDir = async (path: string) => {
dialogData.value.rowData!.sourceDir = path;
};
const changeType = () => {
switch (dialogData.value.rowData!.type) {
case 'shell':
dialogData.value.rowData.specType = 'perWeek';
dialogData.value.rowData.week = 1;
dialogData.value.rowData.hour = 1;
dialogData.value.rowData.minute = 30;
break;
case 'database':
dialogData.value.rowData.specType = 'perDay';
dialogData.value.rowData.hour = 2;
dialogData.value.rowData.minute = 30;
break;
case 'website':
dialogData.value.rowData.specType = 'perWeek';
dialogData.value.rowData.week = 1;
dialogData.value.rowData.hour = 1;
dialogData.value.rowData.minute = 30;
break;
case 'directory':
dialogData.value.rowData.specType = 'perDay';
dialogData.value.rowData.hour = 1;
dialogData.value.rowData.minute = 30;
break;
case 'curl':
dialogData.value.rowData.specType = 'perWeek';
dialogData.value.rowData.week = 1;
dialogData.value.rowData.hour = 1;
dialogData.value.rowData.minute = 30;
break;
}
};
const loadBackups = async () => {
const res = await getBackupList();
backupOptions.value = [];

View File

@ -21,7 +21,7 @@
:start-placeholder="$t('commons.search.timeStart')"
:end-placeholder="$t('commons.search.timeEnd')"
:shortcuts="shortcuts"
style="float: right; right: 20px"
style="float: right"
></el-date-picker>
</template>
<div id="loadLoadChart" style="width: 100%; height: 400px"></div>
@ -41,7 +41,7 @@
:start-placeholder="$t('commons.search.timeStart')"
:end-placeholder="$t('commons.search.timeEnd')"
:shortcuts="shortcuts"
style="float: right; right: 20px"
style="float: right"
></el-date-picker>
</template>
<div id="loadCPUChart" style="width: 100%; height: 400px"></div>
@ -59,7 +59,7 @@
:start-placeholder="$t('commons.search.timeStart')"
:end-placeholder="$t('commons.search.timeEnd')"
:shortcuts="shortcuts"
style="float: right; right: 20px"
style="float: right"
></el-date-picker>
</template>
<div id="loadMemoryChart" style="width: 100%; height: 400px"></div>
@ -79,27 +79,16 @@
:start-placeholder="$t('commons.search.timeStart')"
:end-placeholder="$t('commons.search.timeEnd')"
:shortcuts="shortcuts"
style="float: right; right: 20px"
style="float: right"
></el-date-picker>
</template>
<div id="loadIOChart" style="width: 100%; height: 400px"></div>
<div id="loadIOChart" style="width: 100%; height: 400px; margin-top: 34px"></div>
</el-card>
</el-col>
<el-col :span="12">
<el-card style="overflow: inherit">
<template #header>
<span style="font-size: 16px; font-weight: 500">{{ $t('monitor.network') }} IO</span>
<el-select
v-model="networkChoose"
clearable
filterable
@change="search('network')"
style="margin-left: 20px"
placeholder="Select"
>
<template #prefix>{{ $t('monitor.networkCard') }}</template>
<el-option v-for="item in netOptions" :key="item" :label="item" :value="item" />
</el-select>
<el-date-picker
@change="search('network')"
v-model="timeRangeNetwork"
@ -108,9 +97,20 @@
:start-placeholder="$t('commons.search.timeStart')"
:end-placeholder="$t('commons.search.timeEnd')"
:shortcuts="shortcuts"
style="float: right; right: 20px"
style="float: right"
></el-date-picker>
</template>
<el-select
v-model="networkChoose"
clearable
filterable
@change="search('network')"
style="margin-left: 20px"
placeholder="Select"
>
<template #prefix>{{ $t('monitor.networkCard') }}</template>
<el-option v-for="item in netOptions" :key="item" :label="item" :value="item" />
</el-select>
<div id="loadNetworkChart" style="width: 100%; height: 400px"></div>
</el-card>
</el-col>