fix: Fix backup compression failure (#8234)

This commit is contained in:
ssongliu 2025-03-25 10:11:32 +08:00 committed by GitHub
parent 0bddeef63e
commit 06b7ae2a38
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 76 additions and 52 deletions

View file

@ -184,7 +184,7 @@ func handleWebsiteRecover(website *model.Website, recoverFile string, isRollback
}
taskName := i18n.GetMsgByKey("TaskRecover") + i18n.GetMsgByKey("websiteDir")
t.Log(taskName)
if err = fileOp.TarGzExtractPro(fmt.Sprintf("%s/%s.web.tar.gz", tmpPath, website.Alias), GetOpenrestyDir(SitesRootDir), secret); err != nil {
if err = fileOp.TarGzExtractPro(fmt.Sprintf("%s/%s.web.tar.gz", tmpPath, website.Alias), GetOpenrestyDir(SitesRootDir), ""); err != nil {
t.LogFailedWithErr(taskName, err)
return err
}

View file

@ -80,7 +80,7 @@ func (u *CronjobService) handleWebsite(cronjob model.Cronjob, startTime time.Tim
record.From = "cronjob"
record.Type = "website"
record.CronjobID = cronjob.ID
record.Name = web.PrimaryDomain
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.PrimaryDomain))
@ -150,7 +150,7 @@ func (u *CronjobService) handleDirectory(cronjob model.Cronjob, startTime time.T
if err != nil {
return err
}
fileName := fmt.Sprintf("directory%s_%s.tar.gz", strings.ReplaceAll(cronjob.SourceDir, "/", "_"), startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5))
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()
@ -160,7 +160,7 @@ func (u *CronjobService) handleDirectory(cronjob model.Cronjob, startTime time.T
}
} else {
fileLists := strings.Split(cronjob.SourceDir, ",")
if err := fileOp.Compress(fileLists, backupDir, fileName, files.TarGz, cronjob.Secret); err != nil {
if err := fileOp.TarGzFilesWithCompressPro(fileLists, path.Join(backupDir, fileName), cronjob.Secret); err != nil {
return err
}
}

View file

@ -7,7 +7,6 @@ import (
"crypto/tls"
"encoding/json"
"fmt"
"github.com/1Panel-dev/1Panel/agent/buserr"
"io"
"io/fs"
"net/http"
@ -19,6 +18,8 @@ import (
"strings"
"time"
"github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/req_helper"
@ -758,6 +759,28 @@ func (f FileOp) TarGzCompressPro(withDir bool, src, dst, secret, exclusionRules
return cmd.ExecCmdWithDir(commands, workdir)
}
func (f FileOp) TarGzFilesWithCompressPro(list []string, dst, secret string) error {
if !f.Stat(path.Dir(dst)) {
if err := f.Fs.MkdirAll(path.Dir(dst), constant.FilePerm); err != nil {
return err
}
}
var filelist []string
for _, item := range list {
filelist = append(filelist, "-C "+path.Dir(item)+" "+path.Base(item))
}
commands := ""
if len(secret) != 0 {
commands = fmt.Sprintf("tar --warning=no-file-changed --ignore-failed-read -zcf - %s | openssl enc -aes-256-cbc -salt -k '%s' -out %s", strings.Join(filelist, " "), secret, dst)
global.LOG.Debug(strings.ReplaceAll(commands, fmt.Sprintf(" %s ", secret), "******"))
} else {
commands = fmt.Sprintf("tar --warning=no-file-changed --ignore-failed-read -zcf %s %s", dst, strings.Join(filelist, " "))
global.LOG.Debug(commands)
}
return cmd.ExecCmd(commands)
}
func (f FileOp) TarGzExtractPro(src, dst string, secret string) error {
if _, err := os.Stat(path.Dir(dst)); err != nil && os.IsNotExist(err) {
if err = os.MkdirAll(path.Dir(dst), os.ModePerm); err != nil {

View file

@ -78,7 +78,7 @@
size="small"
@close="handleBackupClose"
>
<el-form ref="backupForm" label-position="left" v-loading="loading">
<el-form ref="backupForm" @submit.prevent label-position="left" v-loading="loading">
<el-form-item
:label="$t('setting.compressPassword')"
class="mt-10"

View file

@ -37,7 +37,7 @@ const initLog = async () => {
if (editorRef.value && scrollerElement.value == undefined) {
const parentElement = editorRef.value.$el as HTMLElement;
scrollerElement.value = parentElement.querySelector('.hljs') as HTMLElement;
scrollerElement.value.style['min-height'] = '500px';
scrollerElement.value.style['min-height'] = '100px';
scrollerElement.value.style['max-height'] = 'calc(100vh - ' + props.heightDiff + 'px)';
}
};

View file

@ -32,7 +32,7 @@
import { reactive, ref } from 'vue';
import i18n from '@/lang';
import { MsgSuccess } from '@/utils/message';
import { updateSetting } from '@/api/modules/setting';
import { updateAgentSetting } from '@/api/modules/setting';
import { ElMessageBox, FormInstance } from 'element-plus';
const emit = defineEmits<{ (e: 'search'): void }>();
@ -85,7 +85,7 @@ const onSubmit = async (formEl: FormInstance | undefined) => {
? form.dockerSockPath
: 'unix://' + form.dockerSockPath,
};
await updateSetting(params)
await updateAgentSetting(params)
.then(() => {
loading.value = false;
handleClose();

View file

@ -12,28 +12,37 @@
<template #rightToolBar>
<el-select v-model="searchGroup" @change="search()" clearable class="p-w-200">
<template #prefix>{{ $t('logs.resource') }}</template>
<el-option :label="$t('commons.table.all')" value=""></el-option>
<el-option :label="$t('logs.detail.apps')" value="apps"></el-option>
<el-option :label="$t('logs.detail.websites')" value="websites"></el-option>
<el-option :label="$t('logs.detail.runtimes')" value="runtimes"></el-option>
<el-option :label="$t('logs.detail.databases')" value="databases"></el-option>
<el-option :label="$t('logs.detail.containers')" value="containers"></el-option>
<el-option :label="$t('logs.detail.cronjobs')" value="cronjobs"></el-option>
<el-option :label="$t('logs.detail.files')" value="files"></el-option>
<el-option :label="$t('logs.detail.hosts')" value="hosts"></el-option>
<el-option :label="$t('logs.detail.process')" value="process"></el-option>
<el-option :label="$t('logs.detail.logs')" value="logs"></el-option>
<el-option :label="$t('logs.detail.settings')" value="settings"></el-option>
<el-option :label="$t('commons.table.all')" value="" />
<el-option :label="$t('logs.detail.apps')" value="apps" />
<el-option :label="$t('logs.detail.websites')" value="websites" />
<el-option :label="$t('logs.detail.runtimes')" value="runtimes" />
<el-option :label="$t('logs.detail.ai')" value="ai" />
<el-option :label="$t('logs.detail.databases')" value="databases" />
<el-option :label="$t('logs.detail.containers')" value="containers" />
<el-option :label="$t('menu.system')" value="hosts" />
<el-option :label="$t('logs.detail.files')" value="files" />
<el-option :label="$t('logs.detail.cronjobs')" value="cronjobs" />
<el-option :label="$t('logs.detail.toolbox')" value="toolbox" />
<el-option :label="$t('logs.detail.process')" value="process" />
<el-option :label="$t('logs.detail.nodes')" value="nodes" />
<el-option :label="$t('logs.detail.tampers')" value="tampers" />
<el-option :label="$t('logs.detail.xsetting')" value="xsetting" />
<el-option :label="$t('logs.detail.licenses')" value="licenses" />
<el-option :label="$t('logs.detail.logs')" value="logs" />
<el-option :label="$t('logs.detail.settings')" value="settings" />
<el-option :label="$t('logs.detail.backups')" value="backups" />
<el-option :label="$t('logs.detail.groups')" value="groups" />
<el-option :label="$t('logs.detail.commands')" value="commands" />
</el-select>
<el-select v-model="searchStatus" @change="search()" clearable class="p-w-200">
<template #prefix>{{ $t('xpack.node.node') }}</template>
<el-option :label="$t('commons.table.all')" value=""></el-option>
<el-option :label="$t('commons.status.success')" value="Success"></el-option>
<el-option :label="$t('commons.status.failed')" value="Failed"></el-option>
<template #prefix>{{ $t('commons.table.status') }}</template>
<el-option :label="$t('commons.table.all')" value="" />
<el-option :label="$t('commons.status.success')" value="Success" />
<el-option :label="$t('commons.status.failed')" value="Failed" />
</el-select>
<el-select v-model="searchNode" @change="search()" clearable class="p-w-200">
<template #prefix>{{ $t('xpack.node.node') }}</template>
<el-option :label="$t('commons.table.all')" value=""></el-option>
<el-option :label="$t('commons.table.all')" value="" />
<el-option :label="$t('xpack.node.master')" value="local" />
<el-option v-for="(node, index) in nodes" :key="index" :label="node.name" :value="node.name" />
</el-select>
@ -181,7 +190,7 @@ const replacements = {
'[delete]': 'commons.button.delete',
'[get]': 'commons.button.get',
'[operate]': 'commons.table.operate',
'[UserName]': 'commons.button.username',
'[UserName]': 'commons.login.username',
'[PanelName]': 'setting.title',
'[Language]': 'setting.language',
'[Theme]': 'setting.theme',

View file

@ -138,7 +138,7 @@
<el-option :value="500" :label="500" />
<el-option :value="1000" :label="1000" />
</el-select>
<LogPro v-model="logContent"></LogPro>
<HighlightLog :modelValue="logContent" />
</el-row>
</el-form>
</el-col>
@ -164,6 +164,7 @@ import { ElMessageBox } from 'element-plus';
import { MsgSuccess } from '@/utils/message';
import { shortcuts } from '@/utils/shortcuts';
import { Toolbox } from '@/api/interface/toolbox';
import HighlightLog from '@/components/log/hightlight-log/index.vue';
import { cleanClamRecord, getClamRecordLog, handleClamScan, searchClamRecord } from '@/api/modules/toolbox';
import { useRouter } from 'vue-router';
const router = useRouter();

View file

@ -1,30 +1,22 @@
<template>
<div v-loading="loading">
<LayoutContent>
<LayoutContent backName="Clam">
<template #app>
<ClamStatus v-model:loading="loading" />
</template>
<template #title>
<back-button name="Clam" header="ClamAV">
<template #leftToolBar>
<el-button type="primary" :plain="activeName !== 'clamd'" @click="search('clamd')">
{{ $t('toolbox.clam.clamConf') }}
</el-button>
<el-button type="primary" :plain="activeName !== 'freshclam'" @click="search('freshclam')">
{{ $t('toolbox.clam.freshClam') }}
</el-button>
<el-button type="primary" :plain="activeName !== 'clamd-log'" @click="search('clamd-log')">
{{ $t('toolbox.clam.clamLog') }}
</el-button>
<el-button
type="primary"
:plain="activeName !== 'freshclam-log'"
@click="search('freshclam-log')"
>
{{ $t('toolbox.clam.freshClamLog') }}
</el-button>
</template>
</back-button>
<template #leftToolBar>
<el-button type="primary" :plain="activeName !== 'clamd'" @click="search('clamd')">
{{ $t('toolbox.clam.clamConf') }}
</el-button>
<el-button type="primary" :plain="activeName !== 'freshclam'" @click="search('freshclam')">
{{ $t('toolbox.clam.freshClam') }}
</el-button>
<el-button type="primary" :plain="activeName !== 'clamd-log'" @click="search('clamd-log')">
{{ $t('toolbox.clam.clamLog') }}
</el-button>
<el-button type="primary" :plain="activeName !== 'freshclam-log'" @click="search('freshclam-log')">
{{ $t('toolbox.clam.freshClamLog') }}
</el-button>
</template>
<template #main>

View file

@ -124,7 +124,7 @@ const onOperate = async (service: string, operation: string) => {
' ' + service + ' ',
i18n.global.t('commons.operate.' + operation),
]),
i18n.global.t('app.' + operation),
i18n.global.t('commons.operate.' + operation),
{
confirmButtonText: i18n.global.t('commons.button.confirm'),
cancelButtonText: i18n.global.t('commons.button.cancel'),

View file

@ -34,7 +34,6 @@
placeholder="# The hosts configuration file does not exist or is empty (/etc/hosts)"
v-model="hostsConf"
:heightDiff="300"
:disabled="true"
></CodemirrorPro>
</div>
<template #footer>