fix: Fix the problem of abnormal script execution (#8510)

This commit is contained in:
ssongliu 2025-04-29 15:59:57 +08:00 committed by GitHub
parent 8bd712d891
commit 1b8e049ad3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 64 additions and 27 deletions

View file

@ -160,7 +160,13 @@ func (u *UpgradeService) Upgrade(req dto.Upgrade) error {
return
}
if err := files.CopyItem(false, true, path.Join(tmpDir, "1panel*.service"), "/etc/systemd/system"); err != nil {
if err := files.CopyItem(false, true, path.Join(tmpDir, "1panel-core.service"), "/etc/systemd/system"); err != nil {
global.LOG.Errorf("upgrade 1panel.service failed, err: %v", err)
_ = settingRepo.Update("SystemStatus", "Free")
u.handleRollback(originalDir, 3)
return
}
if err := files.CopyItem(false, true, path.Join(tmpDir, "1panel-agent.service"), "/etc/systemd/system"); err != nil {
global.LOG.Errorf("upgrade 1panel.service failed, err: %v", err)
_ = settingRepo.Update("SystemStatus", "Free")
u.handleRollback(originalDir, 3)
@ -192,13 +198,19 @@ func (u *UpgradeService) Rollback(req dto.OperateByID) error {
}
func (u *UpgradeService) handleBackup(originalDir string) error {
if err := files.CopyItem(false, true, "/usr/local/bin/1panel*", originalDir); err != nil {
if err := files.CopyItem(false, true, "/usr/local/bin/1panel-core", originalDir); err != nil {
return err
}
if err := files.CopyItem(false, true, "/usr/local/bin/1panel-agent", originalDir); err != nil {
return err
}
if err := files.CopyItem(false, true, "/usr/local/bin/1pctl", originalDir); err != nil {
return err
}
if err := files.CopyItem(false, true, "/etc/systemd/system/1panel*.service", originalDir); err != nil {
if err := files.CopyItem(false, true, "/etc/systemd/system/1panel-core.service", originalDir); err != nil {
return err
}
if err := files.CopyItem(false, true, "/etc/systemd/system/1panel-agent.service", originalDir); err != nil {
return err
}
if err := files.CopyItem(true, true, path.Join(global.CONF.Base.InstallDir, "1panel/db"), originalDir); err != nil {

View file

@ -98,7 +98,7 @@ SyncNode: "Sync node data"
SyncPackageData: "Package sync data [{{ .detail }}]"
SyncPackageEncrypt: "Data package encryption"
SyncRequest: "Request node sync API"
SyncFailedRetry: "Node data sync failed (attempt {{ .index }}), {{ .err }}"
SyncFailedRetry: "Node data sync timeout (attempt {{ .index }}), retrying..."
SyncFailed: "Sync failed, please manually sync in the node list!"
#upgrade node

View file

@ -99,7 +99,7 @@ SyncNode: "ノードデータ同期"
SyncPackageData: "同期データのパッケージ化 [{{ .detail }}]"
SyncPackageEncrypt: "データパッケージの暗号化"
SyncRequest: "ード同期APIをリクエスト"
SyncFailedRetry: "ノードデータ同期失敗 ({{ .index }}回目), {{ .err }}"
SyncFailedRetry: "ノードデータ同期タイムアウト ({{ .index }}回目)、再試行中..."
SyncFailed: "同期に失敗しました、ノードリストで手動同期してください!"
#upgrade node

View file

@ -98,7 +98,7 @@ SyncNode: "노드 데이터 동기화"
SyncPackageData: "동기화 데이터 패키징 [{{ .detail }}]"
SyncPackageEncrypt: "데이터 패키지 암호화"
SyncRequest: "노드 동기화 API 요청"
SyncFailedRetry: "노드 데이터 동기화 실패 ({{ .index }}번째 시도), {{ .err }}"
SyncFailedRetry: "노드 데이터 동기화 시간 초과 ({{ .index }}번째 시도), 재시도 중..."
SyncFailed: "동기화 실패, 노드 목록에서 수동 동기화를 실행하세요!"
#upgrade node

View file

@ -98,7 +98,7 @@ SyncNode: "Segerakkan data nod"
SyncPackageData: "Pakej data segerak [{{ .detail }}]"
SyncPackageEncrypt: "Enkripsi pakej data"
SyncRequest: "Permintaan API segerak nod"
SyncFailedRetry: "Gagal segerak data nod (percubaan ke-{{ .index }}), {{ .err }}"
SyncFailedRetry: "Segerakan data nod tamat masa (percubaan ke-{{ .index }}), mencuba semula..."
SyncFailed: "Segerakan gagal, sila segerakkan secara manual dalam senarai nod!"
#upgrade node

View file

@ -98,7 +98,7 @@ SyncNode: "Sincronizar dados do nó"
SyncPackageData: "Empacotar dados de sincronização [{{ .detail }}]"
SyncPackageEncrypt: "Criptografia de pacote de dados"
SyncRequest: "Solicitar API de sincronização de nó"
SyncFailedRetry: "Falha na sincronização de dados do nó (tentativa {{ .index }}), {{ .err }}"
SyncFailedRetry: "Tempo esgotado na sincronização de dados do nó (tentativa {{ .index }}), tentando novamente..."
SyncFailed: "Falha na sincronização, por favor sincronize manualmente na lista de nós!"
#upgrade node

View file

@ -98,7 +98,7 @@ SyncNode: "Синхронизация данных узла"
SyncPackageData: "Упаковка данных синхронизации [{{ .detail }}]"
SyncPackageEncrypt: "Шифрование пакета данных"
SyncRequest: "Запрос API синхронизации узла"
SyncFailedRetry: "Ошибка синхронизации данных узла (попытка {{ .index }}), {{ .err }}"
SyncFailedRetry: "Таймаут синхронизации данных узла (попытка {{ .index }}), повторная попытка..."
SyncFailed: "Ошибка синхронизации, выполните ручную синхронизацию в списке узлов!"
#upgrade node

View file

@ -98,7 +98,7 @@ SyncNode: "同步節點數據"
SyncPackageData: "打包同步數據 [{{ .detail }}]"
SyncPackageEncrypt: "數據包加密"
SyncRequest: "請求節點同步接口"
SyncFailedRetry: "第 {{ .index }} 次同步節點數據失敗{{ .err }}"
SyncFailedRetry: "第 {{ .index }} 次同步節點數據失敗逾時,正在重試..."
SyncFailed: "同步失敗,請在節點列表中手動同步!"
#upgrade node

View file

@ -99,7 +99,7 @@ SyncNode: "同步节点数据"
SyncPackageData: "打包同步数据 [{{ .detail }}]"
SyncPackageEncrypt: "数据包加密"
SyncRequest: "请求节点同步接口"
SyncFailedRetry: "第 {{ .index }} 次同步节点数据失败{{ .err }}"
SyncFailedRetry: "第 {{ .index }} 次同步节点数据失败超时,正在重试..."
SyncFailed: "同步失败,请在节点列表中手动同步!"
#upgrade node

View file

@ -32,14 +32,14 @@ func NewCommand(script string) (*LocalCommand, error) {
} else {
cmd.Env = append(os.Environ(), "TERM=xterm")
}
cmd.Env = append(cmd.Env, "1PANEL_INIT_SCRIPT="+script)
cmd.Env = append(cmd.Env, "INIT_SCRIPT="+script)
pty, err := pty.Start(cmd)
if err != nil {
return nil, errors.Wrapf(err, "failed to start command")
}
if len(script) != 0 {
time.Sleep(100 * time.Millisecond)
_, _ = pty.Write([]byte("bash -c \"$1PANEL_INIT_SCRIPT\"\n"))
_, _ = pty.Write([]byte("bash -c \"$INIT_SCRIPT\"\n"))
}
lcmd := &LocalCommand{

View file

@ -89,7 +89,7 @@ func NewLogicSshWsSession(cols, rows int, sshClient *ssh.Client, wsConn *websock
}
if len(initCmd) != 0 {
time.Sleep(100 * time.Millisecond)
_, _ = stdinP.Write([]byte(initCmd + "\n"))
_, _ = stdinP.Write([]byte(" clear &&" + initCmd + "\n"))
}
return &LogicSshWsSession{
stdinPipe: stdinP,

View file

@ -347,6 +347,7 @@ const message = {
ssl: 'Certificate',
database: 'Database',
aiTools: 'AI',
mcp: 'MCP',
container: 'Container',
cronjob: 'Cronjob',
system: 'System',
@ -1891,7 +1892,7 @@ const message = {
license: 'License',
bindNode: 'Bind Node',
menuSetting: 'Menu Settings',
menuSettingHelper: 'If only 1 menu is kept, the sidebar will directly display that menu.',
menuSettingHelper: 'When only 1 submenu exists, the menu bar will display only that submenu',
showAll: 'Show All',
hideALL: 'Hide All',
ifShow: 'Whether to Show',

View file

@ -339,6 +339,7 @@ const message = {
ssl: '証明書|証明書',
database: 'データベース|データベース',
aiTools: 'AI',
mcp: 'MCP',
container: 'コンテナ|コンテナ',
cronjob: 'クロンジョブ|クロンの仕事',
system: 'システム',
@ -1799,7 +1800,7 @@ const message = {
license: 'ライセンス',
bindNode: 'ノードをバインド',
menuSetting: 'メニュー設定',
menuSettingHelper: '1つのメニューだけを保持する場合サイドバーにはそのメニューが直接表示されます',
menuSettingHelper: 'サブメニューが1つしか存在しない場合メニューバーにはそのサブメニューのみが表示されます',
showAll: 'すべてを表示します',
hideALL: 'すべてを隠します',
ifShow: '表示するかどうか',

View file

@ -341,6 +341,7 @@ const message = {
ssl: '인증서 | 인증서들',
database: '데이터베이스 | 데이터베이스들',
aiTools: 'AI',
mcp: 'MCP',
container: '컨테이너 | 컨테이너들',
cronjob: '크론 작업 | 크론 작업들',
system: '시스템',
@ -1771,7 +1772,7 @@ const message = {
license: '라이선스',
bindNode: '노드 바인딩',
menuSetting: '메뉴 설정',
menuSettingHelper: '메뉴를 1개만 유지하면 사이드바에 해당 메뉴가 직접 표시됩니다.',
menuSettingHelper: '하위 메뉴가 1개만 존재할 경우, 메뉴 바에는 해당 하위 메뉴만 표시됩니다',
showAll: '모두 표시',
hideALL: '모두 숨기기',
ifShow: '표시 여부',

View file

@ -347,6 +347,7 @@ const message = {
ssl: 'Certificate | Certificates',
database: 'Database | Databases',
aiTools: 'AI',
mcp: 'MCP',
container: 'Container | Containers',
cronjob: 'Cron Job | Cron Jobs',
system: 'System',
@ -1856,7 +1857,7 @@ const message = {
license: 'Lesen',
bindNode: 'Ikatan Nod',
menuSetting: 'Tetapan Menu',
menuSettingHelper: 'Jika hanya 1 menu yang disimpan, bar sisi akan langsung menampilkan menu tersebut.',
menuSettingHelper: 'Apabila hanya terdapat 1 submenu, bar menu hanya akan memaparkan submenu tersebut',
showAll: 'Papar Semua',
hideALL: 'Sembunyikan Semua',
ifShow: 'Sama ada untuk Dipaparkan',

View file

@ -345,6 +345,7 @@ const message = {
ssl: 'Certificado | Certificados',
database: 'Banco de Dados | Bancos de Dados',
aiTools: 'AI',
mcp: 'MCP',
container: 'Container | Containers',
cronjob: 'Tarefa Cron | Tarefas Cron',
system: 'Sistema',
@ -1842,7 +1843,7 @@ const message = {
license: 'Licença',
bindNode: 'Vincular ',
menuSetting: 'Configurações do Menu',
menuSettingHelper: 'Se apenas 1 menu for mantido, a barra lateral exibirá diretamente esse menu.',
menuSettingHelper: 'Quando apenas 1 submenu existir, a barra de menus exibirá apenas esse submenu',
showAll: 'Mostrar Tudo',
hideALL: 'Ocultar Tudo',
ifShow: 'Exibir?',

View file

@ -342,6 +342,7 @@ const message = {
ssl: 'Сертификат | Сертификаты',
database: 'База данных | Базы данных',
aiTools: 'AI',
mcp: 'MCP',
container: 'Контейнер | Контейнеры',
cronjob: 'Cron | Задачи Cron',
system: 'Система',
@ -1841,7 +1842,7 @@ const message = {
license: 'Лицензия',
bindNode: 'Привязать Узел',
menuSetting: 'Настройки меню',
menuSettingHelper: 'Если оставить только 1 меню, боковая панель будет напрямую отображать это меню.',
menuSettingHelper: 'Если существует только 1 подменю, в панели меню будет отображаться только это подменю',
showAll: 'Показать все',
hideALL: 'Скрыть все',
ifShow: 'Показывать',

View file

@ -341,6 +341,7 @@ const message = {
ssl: '證書',
database: '數據庫',
aiTools: 'AI',
mcp: 'MCP',
container: '容器',
cronjob: '計劃任務',
system: '系統',
@ -1758,7 +1759,7 @@ const message = {
license: '許可證',
bindNode: '綁定節點',
menuSetting: '菜單設定',
menuSettingHelper: '如果只保留 1 個菜單則側邊欄會直接顯示該菜單',
menuSettingHelper: '當只存在 1 個子選單時選單列將僅展示該子選單',
showAll: '全部顯示',
hideALL: '全部隱藏',
ifShow: '是否顯示',

View file

@ -339,6 +339,7 @@ const message = {
ssl: '证书',
database: '数据库',
aiTools: 'AI',
mcp: 'MCP',
container: '容器',
cronjob: '计划任务',
system: '系统',
@ -1751,7 +1752,7 @@ const message = {
license: '许可证',
bindNode: '绑定节点',
menuSetting: '菜单设置',
menuSettingHelper: '如果只保留 1 个菜单则侧边栏会直接显示该菜单',
menuSettingHelper: '当只存在 1 个子菜单时菜单栏将仅展示该子菜单',
showAll: '全部显示',
hideALL: '全部隐藏',
ifShow: '是否显示',

View file

@ -61,7 +61,7 @@
</div>
</div>
<el-input
v-if="showNodes() && nodeOptions?.length > 5"
v-if="showNodes() && nodes?.length > 5"
suffix-icon="Search"
v-model="filter"
@input="changeFilter"

View file

@ -25,7 +25,7 @@ const databaseRouter = {
name: 'MCPServer',
component: () => import('@/views/ai/mcp/server/index.vue'),
meta: {
title: 'MCP',
title: 'menu.mcp',
requiresAuth: true,
},
},

View file

@ -19,7 +19,12 @@
<el-select v-model="group" @change="search()" clearable class="p-w-200">
<template #prefix>{{ $t('commons.table.group') }}</template>
<div v-for="item in groupOptions" :key="item.id">
<el-option :label="item.name" :value="item.id" />
<el-option
v-if="item.name === 'Default'"
:label="$t('commons.table.default')"
:value="item.id"
/>
<el-option v-else :label="item.name" :value="item.id" />
</div>
</el-select>
<TableSearch @search="search()" v-model:searchName="searchInfo" />
@ -47,7 +52,10 @@
<el-button class="mr-3" size="small" v-if="row.isSystem">system</el-button>
<span v-if="row.groupBelong">
<el-button size="small" v-for="(item, index) in row.groupBelong" :key="index">
{{ item }}
<span v-if="item === 'Default'">
{{ $t('commons.table.default') }}
</span>
<span v-else>{{ item }}</span>
</el-button>
</span>
</template>

View file

@ -12,7 +12,14 @@
</el-form-item>
<el-form-item :label="$t('commons.table.group')" prop="groupList">
<el-select filterable v-model="dialogData.rowData!.groupList" multiple>
<el-option v-for="item in groupOptions" :key="item.id" :label="item.name" :value="item.id" />
<div v-for="item in groupOptions" :key="item.id">
<el-option
v-if="item.name === 'Default'"
:label="$t('commons.table.default')"
:value="item.id"
/>
<el-option v-else :label="item.name" :value="item.id" />
</div>
</el-select>
<span class="input-help">{{ $t('cronjob.library.groupHelper') }}</span>
</el-form-item>

View file

@ -218,6 +218,8 @@ const emit = defineEmits(['search']);
const acceptParams = (): void => {
form.downloadAccountID = '';
form.fromAccounts = [];
form.description = '';
form.secret = '';
nowIndex.value = 0;
search();
loadBackups();