mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-31 22:18:07 +08:00
fix: 计划任务增加线程处理
This commit is contained in:
parent
1e79b096fe
commit
8b9cc1bee8
@ -116,7 +116,7 @@ func (u *CronjobRepo) StartRecords(cronjobID uint, targetPath string) model.JobR
|
|||||||
var record model.JobRecords
|
var record model.JobRecords
|
||||||
record.StartTime = time.Now()
|
record.StartTime = time.Now()
|
||||||
record.CronjobID = cronjobID
|
record.CronjobID = cronjobID
|
||||||
record.Status = constant.StatusRunning
|
record.Status = constant.StatusWaiting
|
||||||
if err := global.DB.Create(&record).Error; err != nil {
|
if err := global.DB.Create(&record).Error; err != nil {
|
||||||
global.LOG.Errorf("create record status failed, err: %v", err)
|
global.LOG.Errorf("create record status failed, err: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -162,7 +162,10 @@ func (u *CronjobService) HandleOnce(id uint) error {
|
|||||||
if cronjob.ID == 0 {
|
if cronjob.ID == 0 {
|
||||||
return constant.ErrRecordNotFound
|
return constant.ErrRecordNotFound
|
||||||
}
|
}
|
||||||
u.HandleJob(&cronjob)
|
|
||||||
|
record := cronjobRepo.StartRecords(cronjob.ID, "")
|
||||||
|
record.FromLocal = cronjob.KeepLocal
|
||||||
|
go u.HandleJob(&cronjob)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,46 +24,48 @@ func (u *CronjobService) HandleJob(cronjob *model.Cronjob) {
|
|||||||
)
|
)
|
||||||
record := cronjobRepo.StartRecords(cronjob.ID, "")
|
record := cronjobRepo.StartRecords(cronjob.ID, "")
|
||||||
record.FromLocal = cronjob.KeepLocal
|
record.FromLocal = cronjob.KeepLocal
|
||||||
switch cronjob.Type {
|
go func() {
|
||||||
case "shell":
|
switch cronjob.Type {
|
||||||
if len(cronjob.Script) == 0 {
|
case "shell":
|
||||||
return
|
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 {
|
if err != nil {
|
||||||
err = errCurl
|
cronjobRepo.EndRecords(record, constant.StatusFailed, err.Error(), string(message))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
message = []byte(stdout)
|
if len(message) != 0 {
|
||||||
}
|
record.Records, err = mkdirAndWriteFile(cronjob, record.StartTime, message)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cronjobRepo.EndRecords(record, constant.StatusFailed, err.Error(), string(message))
|
global.LOG.Errorf("save file %s failed, err: %v", record.Records, err)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
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) {
|
func (u *CronjobService) HandleBackup(cronjob *model.Cronjob, startTime time.Time) (string, error) {
|
||||||
|
@ -40,10 +40,10 @@ type daemonJsonItem struct {
|
|||||||
|
|
||||||
func (u *DockerService) LoadDockerStatus() string {
|
func (u *DockerService) LoadDockerStatus() string {
|
||||||
status := constant.StatusRunning
|
status := constant.StatusRunning
|
||||||
stdout, err := cmd.Exec("systemctl is-active docker")
|
// stdout, err := cmd.Exec("systemctl is-active docker")
|
||||||
if string(stdout) != "active\n" || err != nil {
|
// if string(stdout) != "active\n" || err != nil {
|
||||||
status = constant.Stopped
|
// status = constant.Stopped
|
||||||
}
|
// }
|
||||||
|
|
||||||
return status
|
return status
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,17 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
"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/cmd"
|
||||||
"github.com/1Panel-dev/1Panel/backend/utils/common"
|
"github.com/1Panel-dev/1Panel/backend/utils/common"
|
||||||
"github.com/jinzhu/copier"
|
"github.com/jinzhu/copier"
|
||||||
@ -64,10 +67,22 @@ func (u *ImageRepoService) Create(req dto.ImageRepoCreate) error {
|
|||||||
}
|
}
|
||||||
if req.Protocol == "http" {
|
if req.Protocol == "http" {
|
||||||
_ = u.handleRegistries(req.DownloadUrl, "", "create")
|
_ = u.handleRegistries(req.DownloadUrl, "", "create")
|
||||||
stdout, err := cmd.Exec("systemctl restart docker")
|
ticker := time.NewTicker(3 * time.Second)
|
||||||
if err != nil {
|
ctx, cancle := context.WithTimeout(context.Background(), time.Second*20)
|
||||||
return errors.New(string(stdout))
|
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 {
|
if err := copier.Copy(&imageRepo, &req); err != nil {
|
||||||
|
@ -15,7 +15,7 @@ func (s *ContainerRouter) InitContainerRouter(Router *gin.RouterGroup) {
|
|||||||
Use(middleware.PasswordExpired())
|
Use(middleware.PasswordExpired())
|
||||||
baseApi := v1.ApiGroupApp.BaseApi
|
baseApi := v1.ApiGroupApp.BaseApi
|
||||||
{
|
{
|
||||||
baRouter.GET("/exec", baseApi.ContainerExec)
|
baRouter.GET("/exec", baseApi.ContainerWsSsh)
|
||||||
baRouter.GET("/stats/:id", baseApi.ContainerStats)
|
baRouter.GET("/stats/:id", baseApi.ContainerStats)
|
||||||
|
|
||||||
baRouter.POST("", baseApi.ContainerCreate)
|
baRouter.POST("", baseApi.ContainerCreate)
|
||||||
|
@ -269,3 +269,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.xterm-viewport::-webkit-scrollbar {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
background-color: #000000;
|
||||||
|
}
|
@ -7,7 +7,7 @@
|
|||||||
<el-row type="flex" justify="center">
|
<el-row type="flex" justify="center">
|
||||||
<el-col :span="22">
|
<el-col :span="22">
|
||||||
<el-form-item :label="$t('cronjob.taskType')" prop="type">
|
<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="shell" :label="$t('cronjob.shell')" />
|
||||||
<el-option value="website" :label="$t('cronjob.website')" />
|
<el-option value="website" :label="$t('cronjob.website')" />
|
||||||
<el-option value="database" :label="$t('cronjob.database')" />
|
<el-option value="database" :label="$t('cronjob.database')" />
|
||||||
@ -184,6 +184,7 @@ const dialogData = ref<DialogProps>({
|
|||||||
});
|
});
|
||||||
const acceptParams = (params: DialogProps): void => {
|
const acceptParams = (params: DialogProps): void => {
|
||||||
dialogData.value = params;
|
dialogData.value = params;
|
||||||
|
changeType();
|
||||||
title.value = i18n.global.t('commons.button.' + dialogData.value.title);
|
title.value = i18n.global.t('commons.button.' + dialogData.value.title);
|
||||||
drawerVisiable.value = true;
|
drawerVisiable.value = true;
|
||||||
checkMysqlInstalled();
|
checkMysqlInstalled();
|
||||||
@ -310,6 +311,39 @@ const loadDir = async (path: string) => {
|
|||||||
dialogData.value.rowData!.sourceDir = path;
|
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 loadBackups = async () => {
|
||||||
const res = await getBackupList();
|
const res = await getBackupList();
|
||||||
backupOptions.value = [];
|
backupOptions.value = [];
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
:start-placeholder="$t('commons.search.timeStart')"
|
:start-placeholder="$t('commons.search.timeStart')"
|
||||||
:end-placeholder="$t('commons.search.timeEnd')"
|
:end-placeholder="$t('commons.search.timeEnd')"
|
||||||
:shortcuts="shortcuts"
|
:shortcuts="shortcuts"
|
||||||
style="float: right; right: 20px"
|
style="float: right"
|
||||||
></el-date-picker>
|
></el-date-picker>
|
||||||
</template>
|
</template>
|
||||||
<div id="loadLoadChart" style="width: 100%; height: 400px"></div>
|
<div id="loadLoadChart" style="width: 100%; height: 400px"></div>
|
||||||
@ -41,7 +41,7 @@
|
|||||||
:start-placeholder="$t('commons.search.timeStart')"
|
:start-placeholder="$t('commons.search.timeStart')"
|
||||||
:end-placeholder="$t('commons.search.timeEnd')"
|
:end-placeholder="$t('commons.search.timeEnd')"
|
||||||
:shortcuts="shortcuts"
|
:shortcuts="shortcuts"
|
||||||
style="float: right; right: 20px"
|
style="float: right"
|
||||||
></el-date-picker>
|
></el-date-picker>
|
||||||
</template>
|
</template>
|
||||||
<div id="loadCPUChart" style="width: 100%; height: 400px"></div>
|
<div id="loadCPUChart" style="width: 100%; height: 400px"></div>
|
||||||
@ -59,7 +59,7 @@
|
|||||||
:start-placeholder="$t('commons.search.timeStart')"
|
:start-placeholder="$t('commons.search.timeStart')"
|
||||||
:end-placeholder="$t('commons.search.timeEnd')"
|
:end-placeholder="$t('commons.search.timeEnd')"
|
||||||
:shortcuts="shortcuts"
|
:shortcuts="shortcuts"
|
||||||
style="float: right; right: 20px"
|
style="float: right"
|
||||||
></el-date-picker>
|
></el-date-picker>
|
||||||
</template>
|
</template>
|
||||||
<div id="loadMemoryChart" style="width: 100%; height: 400px"></div>
|
<div id="loadMemoryChart" style="width: 100%; height: 400px"></div>
|
||||||
@ -79,27 +79,16 @@
|
|||||||
:start-placeholder="$t('commons.search.timeStart')"
|
:start-placeholder="$t('commons.search.timeStart')"
|
||||||
:end-placeholder="$t('commons.search.timeEnd')"
|
:end-placeholder="$t('commons.search.timeEnd')"
|
||||||
:shortcuts="shortcuts"
|
:shortcuts="shortcuts"
|
||||||
style="float: right; right: 20px"
|
style="float: right"
|
||||||
></el-date-picker>
|
></el-date-picker>
|
||||||
</template>
|
</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-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-card style="overflow: inherit">
|
<el-card style="overflow: inherit">
|
||||||
<template #header>
|
<template #header>
|
||||||
<span style="font-size: 16px; font-weight: 500">{{ $t('monitor.network') }} IO</span>
|
<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
|
<el-date-picker
|
||||||
@change="search('network')"
|
@change="search('network')"
|
||||||
v-model="timeRangeNetwork"
|
v-model="timeRangeNetwork"
|
||||||
@ -108,9 +97,20 @@
|
|||||||
:start-placeholder="$t('commons.search.timeStart')"
|
:start-placeholder="$t('commons.search.timeStart')"
|
||||||
:end-placeholder="$t('commons.search.timeEnd')"
|
:end-placeholder="$t('commons.search.timeEnd')"
|
||||||
:shortcuts="shortcuts"
|
:shortcuts="shortcuts"
|
||||||
style="float: right; right: 20px"
|
style="float: right"
|
||||||
></el-date-picker>
|
></el-date-picker>
|
||||||
</template>
|
</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>
|
<div id="loadNetworkChart" style="width: 100%; height: 400px"></div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user