mirror of
https://github.com/whyour/qinglong.git
synced 2026-07-01 04:40:38 +08:00
统一 Alpine/Debian 分支,QL_SCHEDULER 参数化调度
* 修改获取示例文件 api path * 增加 debian-slim 基础镜像 * 修复 debian apt 命令,支持 qinglong 命令 * 更新 npm 版本 0.7.7 * 更新 npm v0.8.4 * 修复linux依赖检测 (#2082) * 修复拉取私有仓库 * 修复 shell check_server * 修复 qinglong 命令 * 更新 npm 版本 v0.13.2 * 增加 debian 开发版本 * 修改切换 linux 镜像源 * 修复 qinglong 命令 * 移除 qinglong 命令 npm 默认镜像源 * 修复 workflow * 更新 npm 版本 v0.14.5 * 增加 npx 命令 * 更新 workflow action 版本 * 更新 npm 版本 v0.16.0 * 修复 linux 镜像源 * 更新 npm 版本 v0.17.0 * 更新 npm 版本 v0.18.0 * 修改 npm 安装启动命令 * 更新 npm 版本 v0.19.9 * 修复 debian netcat 包名 * 更新 npm 版本 v0.20.4 * 安装 linux 依赖自动识别 alpine 和 debian * 修改 apt 命令 * 更新 npm 版本 v0.21.2 * 修改 ts 文件执行依赖 * npm 启动增加 reload 逻辑 * 更新 npm 版本 v2.17.8 * 修复 qinglong 命令 * 更新 npm 版本 v2.17.9 * 更新 npm 版本 v2.17.10 * 更新 npm 版本 v2.17.11 * 修改 debian 版本为 12 bookworm * 更新 npm 版本 v2.17.12 * 修改本地服务启动提示 * 更新 npm 版本 v2.17.13 * 写入文件增加文件锁 * 修复系统安装依赖提示 * 更新 npm 版本 v2.18.2-6 * 更新 nodejs 版本 * 更新 npm 版本 v2.18.3-3 * 修复 command 变量 * 移除自动清除 deb * 修复 npm 启动脚本 * 修复发布 npm包依赖文件 * 修改 linux 启动文件逻辑 * 更新 npm 版本 v2.19.0-10 * 修复 apt 命令 * 更新 npm 版本 v2.19.1-0 * 更新 npm 版本 v2.19.2-2 * 增加 packageManager * 增加用户 qinglong * 更新 pipeline * 移除 init_nginx * 更新 npm 版本 v2.20.0 * 更新 npm 版本 2.20.1 * 更新 npm 版本 2.20.2 * fix: 修复非 root 用户启动 * chore: 合并 debian 和 alpine 逻辑 --------- Co-authored-by: dream10201 <xiuxiu10201@gmail.com>
This commit is contained in:
+1
-1
@@ -14,7 +14,7 @@ export default (app: Router) => {
|
||||
app.use('/configs', route);
|
||||
|
||||
route.get(
|
||||
'/sample',
|
||||
'/samples',
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
res.send({
|
||||
|
||||
@@ -49,3 +49,38 @@ export const NotificationModeStringMap = {
|
||||
19: 'ntfy',
|
||||
20: 'wxPusherBot',
|
||||
} as const;
|
||||
|
||||
export const LINUX_DEPENDENCE_COMMAND: Record<
|
||||
'Debian' | 'Ubuntu' | 'Alpine',
|
||||
{
|
||||
install: string;
|
||||
uninstall: string;
|
||||
info: string;
|
||||
check(info: string): boolean;
|
||||
}
|
||||
> = {
|
||||
Debian: {
|
||||
install: 'apt-get install -y',
|
||||
uninstall: 'apt-get remove -y',
|
||||
info: 'dpkg-query -s',
|
||||
check(info: string) {
|
||||
return info.includes('install ok installed');
|
||||
},
|
||||
},
|
||||
Ubuntu: {
|
||||
install: 'apt-get install -y',
|
||||
uninstall: 'apt-get remove -y',
|
||||
info: 'dpkg-query -s',
|
||||
check(info: string) {
|
||||
return info.includes('install ok installed');
|
||||
},
|
||||
},
|
||||
Alpine: {
|
||||
install: 'apk add --no-check-certificate',
|
||||
uninstall: 'apk del',
|
||||
info: 'apk info -es',
|
||||
check(info: string) {
|
||||
return info.includes('installed');
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
+196
-4
@@ -1,6 +1,6 @@
|
||||
import * as fs from 'fs/promises';
|
||||
import * as path from 'path';
|
||||
import { exec } from 'child_process';
|
||||
import { exec, execSync } from 'child_process';
|
||||
import psTreeFun from 'ps-tree';
|
||||
import { promisify } from 'util';
|
||||
import { load } from 'js-yaml';
|
||||
@@ -10,9 +10,38 @@ import Logger from '../loaders/logger';
|
||||
import { writeFileWithLock } from '../shared/utils';
|
||||
import { DependenceTypes } from '../data/dependence';
|
||||
import { FormData } from 'undici';
|
||||
import os from 'os';
|
||||
|
||||
export * from './share';
|
||||
|
||||
let osType: 'Debian' | 'Ubuntu' | 'Alpine' | undefined;
|
||||
|
||||
function getOsTypeSync(): 'Debian' | 'Ubuntu' | 'Alpine' | undefined {
|
||||
// 1. 环境变量覆盖
|
||||
const envOs = process.env.QL_OS_TYPE?.toLowerCase();
|
||||
if (envOs === 'alpine') return 'Alpine';
|
||||
if (envOs === 'debian') return 'Debian';
|
||||
if (envOs === 'ubuntu') return 'Ubuntu';
|
||||
|
||||
// 2. 模块缓存(由 detectOS 设置)
|
||||
if (osType) return osType;
|
||||
|
||||
// 3. 能力检测:检查包管理器二进制
|
||||
try {
|
||||
execSync('which apt-get', { stdio: 'ignore' });
|
||||
return 'Debian';
|
||||
} catch {
|
||||
try {
|
||||
execSync('which apk', { stdio: 'ignore' });
|
||||
return 'Alpine';
|
||||
} catch {
|
||||
// macOS / 未知系统
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export async function getFileContentByName(fileName: string) {
|
||||
const _exsit = await fileExist(fileName);
|
||||
if (_exsit) {
|
||||
@@ -550,7 +579,9 @@ except:
|
||||
spec=u.find_spec(name)
|
||||
print(name if spec else '')
|
||||
''')"`,
|
||||
[DependenceTypes.linux]: `apk info -es ${name}`,
|
||||
[DependenceTypes.linux]: getOsTypeSync() === 'Alpine'
|
||||
? `apk info -es ${name}`
|
||||
: `dpkg-query -s ${name}`,
|
||||
};
|
||||
|
||||
return baseCommands[type];
|
||||
@@ -561,7 +592,9 @@ export function getInstallCommand(type: DependenceTypes, name: string): string {
|
||||
[DependenceTypes.nodejs]: 'pnpm add -g',
|
||||
[DependenceTypes.python3]:
|
||||
'pip3 install --disable-pip-version-check --root-user-action=ignore',
|
||||
[DependenceTypes.linux]: 'apk add --no-check-certificate',
|
||||
[DependenceTypes.linux]: getOsTypeSync() === 'Alpine'
|
||||
? 'apk add --no-check-certificate'
|
||||
: 'apt-get install -y',
|
||||
};
|
||||
|
||||
let command = baseCommands[type];
|
||||
@@ -581,7 +614,9 @@ export function getUninstallCommand(
|
||||
[DependenceTypes.nodejs]: 'pnpm remove -g',
|
||||
[DependenceTypes.python3]:
|
||||
'pip3 uninstall --disable-pip-version-check --root-user-action=ignore -y',
|
||||
[DependenceTypes.linux]: 'apk del',
|
||||
[DependenceTypes.linux]: getOsTypeSync() === 'Alpine'
|
||||
? 'apk del'
|
||||
: 'apt-get remove -y',
|
||||
};
|
||||
|
||||
return `${baseCommands[type]} ${name.trim()}`;
|
||||
@@ -590,3 +625,160 @@ export function getUninstallCommand(
|
||||
export function isDemoEnv() {
|
||||
return process.env.DeployEnv === 'demo';
|
||||
}
|
||||
|
||||
async function getOSReleaseInfo(): Promise<string> {
|
||||
const osRelease = await fs.readFile('/etc/os-release', 'utf8');
|
||||
return osRelease;
|
||||
}
|
||||
|
||||
function isDebian(osReleaseInfo: string): boolean {
|
||||
return osReleaseInfo.includes('Debian');
|
||||
}
|
||||
|
||||
function isUbuntu(osReleaseInfo: string): boolean {
|
||||
return osReleaseInfo.includes('Ubuntu');
|
||||
}
|
||||
|
||||
function isCentOS(osReleaseInfo: string): boolean {
|
||||
return osReleaseInfo.includes('CentOS') || osReleaseInfo.includes('Red Hat');
|
||||
}
|
||||
|
||||
function isAlpine(osReleaseInfo: string): boolean {
|
||||
return osReleaseInfo.includes('Alpine');
|
||||
}
|
||||
|
||||
export async function detectOS(): Promise<
|
||||
'Debian' | 'Ubuntu' | 'Alpine' | undefined
|
||||
> {
|
||||
if (osType) return osType;
|
||||
|
||||
const envOs = process.env.QL_OS_TYPE?.toLowerCase();
|
||||
if (envOs === 'alpine') {
|
||||
osType = 'Alpine';
|
||||
return osType;
|
||||
}
|
||||
if (envOs === 'debian') {
|
||||
osType = 'Debian';
|
||||
return osType;
|
||||
}
|
||||
if (envOs === 'ubuntu') {
|
||||
osType = 'Ubuntu';
|
||||
return osType;
|
||||
}
|
||||
|
||||
const platform = os.platform();
|
||||
|
||||
if (platform === 'linux') {
|
||||
const osReleaseInfo = await getOSReleaseInfo();
|
||||
if (isDebian(osReleaseInfo)) {
|
||||
osType = 'Debian';
|
||||
} else if (isUbuntu(osReleaseInfo)) {
|
||||
osType = 'Ubuntu';
|
||||
} else if (isAlpine(osReleaseInfo)) {
|
||||
osType = 'Alpine';
|
||||
} else {
|
||||
Logger.error(`Unknown Linux Distribution: ${osReleaseInfo}`);
|
||||
console.error(`Unknown Linux Distribution: ${osReleaseInfo}`);
|
||||
}
|
||||
} else if (platform === 'darwin') {
|
||||
osType = undefined;
|
||||
} else {
|
||||
Logger.error(`Unsupported platform: ${platform}`);
|
||||
console.error(`Unsupported platform: ${platform}`);
|
||||
}
|
||||
|
||||
return osType;
|
||||
}
|
||||
|
||||
async function getCurrentMirrorDomain(
|
||||
filePath: string,
|
||||
): Promise<string | null> {
|
||||
const fileContent = await fs.readFile(filePath, 'utf8');
|
||||
const lines = fileContent.split('\n');
|
||||
for (const line of lines) {
|
||||
if (line.trim().startsWith('#')) {
|
||||
continue;
|
||||
}
|
||||
const match = line.match(/https?:\/\/[^\/]+/);
|
||||
if (match) {
|
||||
return match[0];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async function replaceDomainInFile(
|
||||
filePath: string,
|
||||
oldDomainWithScheme: string,
|
||||
newDomainWithScheme: string,
|
||||
): Promise<void> {
|
||||
let fileContent = await fs.readFile(filePath, 'utf8');
|
||||
let updatedContent = fileContent.replace(
|
||||
new RegExp(oldDomainWithScheme, 'g'),
|
||||
newDomainWithScheme,
|
||||
);
|
||||
|
||||
if (!newDomainWithScheme.endsWith('/')) {
|
||||
newDomainWithScheme += '/';
|
||||
}
|
||||
|
||||
await writeFileWithLock(filePath, updatedContent);
|
||||
}
|
||||
|
||||
async function _updateLinuxMirror(
|
||||
osType: string,
|
||||
mirrorDomainWithScheme: string,
|
||||
): Promise<string> {
|
||||
let filePath: string, currentDomainWithScheme: string | null;
|
||||
switch (osType) {
|
||||
case 'Debian':
|
||||
filePath = '/etc/apt/sources.list.d/debian.sources';
|
||||
currentDomainWithScheme = await getCurrentMirrorDomain(filePath);
|
||||
if (currentDomainWithScheme) {
|
||||
await replaceDomainInFile(
|
||||
filePath,
|
||||
currentDomainWithScheme,
|
||||
mirrorDomainWithScheme || 'http://deb.debian.org',
|
||||
);
|
||||
return 'apt-get update';
|
||||
} else {
|
||||
throw Error(`Current mirror domain not found.`);
|
||||
}
|
||||
case 'Ubuntu':
|
||||
filePath = '/etc/apt/sources.list.d/ubuntu.sources';
|
||||
currentDomainWithScheme = await getCurrentMirrorDomain(filePath);
|
||||
if (currentDomainWithScheme) {
|
||||
await replaceDomainInFile(
|
||||
filePath,
|
||||
currentDomainWithScheme,
|
||||
mirrorDomainWithScheme || 'http://archive.ubuntu.com',
|
||||
);
|
||||
return 'apt-get update';
|
||||
} else {
|
||||
throw Error(`Current mirror domain not found.`);
|
||||
}
|
||||
case 'Alpine':
|
||||
filePath = '/etc/apk/repositories';
|
||||
currentDomainWithScheme = await getCurrentMirrorDomain(filePath);
|
||||
if (currentDomainWithScheme) {
|
||||
await replaceDomainInFile(
|
||||
filePath,
|
||||
currentDomainWithScheme,
|
||||
mirrorDomainWithScheme || 'http://dl-cdn.alpinelinux.org',
|
||||
);
|
||||
return 'apk update';
|
||||
} else {
|
||||
throw Error(`Current mirror domain not found.`);
|
||||
}
|
||||
default:
|
||||
throw Error('Unsupported OS type for updating mirrors.');
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateLinuxMirrorFile(mirror: string): Promise<string> {
|
||||
const detectedOS = await detectOS();
|
||||
if (!detectedOS) {
|
||||
throw Error(`Unknown Linux Distribution`);
|
||||
}
|
||||
return await _updateLinuxMirror(detectedOS, mirror);
|
||||
}
|
||||
|
||||
+34
-15
@@ -39,6 +39,25 @@ export default class CronService {
|
||||
return false;
|
||||
}
|
||||
|
||||
private get schedulerMode(): 'system' | 'node' {
|
||||
const env = process.env.QL_SCHEDULER;
|
||||
if (env === 'system') return 'system';
|
||||
if (env === 'node') return 'node';
|
||||
try {
|
||||
execSync('which crond', { stdio: 'ignore' });
|
||||
return 'system';
|
||||
} catch {
|
||||
return 'node';
|
||||
}
|
||||
}
|
||||
|
||||
private shouldUseCronClient(cron: Crontab): boolean {
|
||||
if (this.schedulerMode === 'node') {
|
||||
return !this.isSpecialSchedule(cron.schedule);
|
||||
}
|
||||
return this.isNodeCron(cron) && !this.isSpecialSchedule(cron.schedule);
|
||||
}
|
||||
|
||||
private isOnceSchedule(schedule?: string) {
|
||||
return schedule?.startsWith(ScheduleType.ONCE);
|
||||
}
|
||||
@@ -80,7 +99,7 @@ export default class CronService {
|
||||
return doc;
|
||||
}
|
||||
|
||||
if (this.isNodeCron(doc) && !this.isSpecialSchedule(doc.schedule)) {
|
||||
if (this.shouldUseCronClient(doc)) {
|
||||
await cronClient.addCron([
|
||||
{
|
||||
name: doc.name || '',
|
||||
@@ -111,11 +130,9 @@ export default class CronService {
|
||||
return newDoc;
|
||||
}
|
||||
|
||||
if (this.isNodeCron(doc)) {
|
||||
await cronClient.delCron([String(doc.id)]);
|
||||
}
|
||||
await cronClient.delCron([String(newDoc.id)]);
|
||||
|
||||
if (this.isNodeCron(newDoc) && !this.isSpecialSchedule(newDoc.schedule)) {
|
||||
if (this.shouldUseCronClient(newDoc)) {
|
||||
await cronClient.addCron([
|
||||
{
|
||||
name: doc.name || '',
|
||||
@@ -577,8 +594,8 @@ export default class CronService {
|
||||
public async enabled(ids: number[]) {
|
||||
await CrontabModel.update({ isDisabled: 0 }, { where: { id: ids } });
|
||||
const docs = await CrontabModel.findAll({ where: { id: ids } });
|
||||
const sixCron = docs
|
||||
.filter((x) => this.isNodeCron(x) && !this.isSpecialSchedule(x.schedule))
|
||||
const crons = docs
|
||||
.filter((x) => this.shouldUseCronClient(x))
|
||||
.map((doc) => ({
|
||||
name: doc.name || '',
|
||||
id: String(doc.id),
|
||||
@@ -590,7 +607,8 @@ export default class CronService {
|
||||
if (isDemoEnv()) {
|
||||
return;
|
||||
}
|
||||
await cronClient.addCron(sixCron);
|
||||
|
||||
await cronClient.addCron(crons);
|
||||
await this.setCrontab();
|
||||
}
|
||||
|
||||
@@ -690,11 +708,13 @@ export default class CronService {
|
||||
|
||||
await writeFileWithLock(config.crontabFile, crontab_string);
|
||||
|
||||
try {
|
||||
execSync(`crontab ${config.crontabFile}`);
|
||||
} catch (error: any) {
|
||||
const errorMsg = error.message || String(error);
|
||||
this.logger.error('[crontab] Failed to update system crontab:', errorMsg);
|
||||
if (this.schedulerMode === 'system') {
|
||||
try {
|
||||
execSync(`crontab ${config.crontabFile}`);
|
||||
} catch (error: any) {
|
||||
const errorMsg = error.message || String(error);
|
||||
this.logger.error('[crontab] Failed to update system crontab:', errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
await CrontabModel.update({ saved: true }, { where: {} });
|
||||
@@ -745,8 +765,7 @@ export default class CronService {
|
||||
.filter(
|
||||
(x) =>
|
||||
x.isDisabled !== 1 &&
|
||||
this.isNodeCron(x) &&
|
||||
!this.isSpecialSchedule(x.schedule),
|
||||
this.shouldUseCronClient(x),
|
||||
)
|
||||
.map((doc) => ({
|
||||
name: doc.name || '',
|
||||
|
||||
+61
-17
@@ -22,6 +22,8 @@ import {
|
||||
} from '../config/util';
|
||||
import dayjs from 'dayjs';
|
||||
import taskLimit from '../shared/pLimit';
|
||||
import { detectOS } from '../config/util';
|
||||
import { LINUX_DEPENDENCE_COMMAND } from '../config/const';
|
||||
|
||||
@Service()
|
||||
export default class DependenceService {
|
||||
@@ -159,8 +161,19 @@ export default class DependenceService {
|
||||
const docs = await DependenceModel.findAll({ where: { id: ids } });
|
||||
for (const doc of docs) {
|
||||
taskLimit.removeQueuedDependency(doc);
|
||||
const depInstallCommand = getInstallCommand(doc.type, doc.name);
|
||||
const depUnInstallCommand = getUninstallCommand(doc.type, doc.name);
|
||||
let depInstallCommand = getInstallCommand(doc.type, doc.name);
|
||||
let depUnInstallCommand = getUninstallCommand(doc.type, doc.name);
|
||||
const isLinuxDependence = doc.type === DependenceTypes.linux;
|
||||
|
||||
if (isLinuxDependence) {
|
||||
const osType = await detectOS();
|
||||
if (!osType) {
|
||||
continue;
|
||||
}
|
||||
const linuxCommand = LINUX_DEPENDENCE_COMMAND[osType];
|
||||
depInstallCommand = `${linuxCommand.install} ${doc.name.trim()}`;
|
||||
depUnInstallCommand = `${linuxCommand.uninstall} ${doc.name.trim()}`;
|
||||
}
|
||||
const pids = await Promise.all([
|
||||
getPid(depInstallCommand),
|
||||
getPid(depUnInstallCommand),
|
||||
@@ -217,23 +230,54 @@ export default class DependenceService {
|
||||
if (taskLimit.firstDependencyId !== dependency.id) {
|
||||
return resolve(null);
|
||||
}
|
||||
|
||||
taskLimit.removeQueuedDependency(dependency);
|
||||
|
||||
const depIds = [dependency.id!];
|
||||
let depName = dependency.name.trim();
|
||||
const actionText = isInstall ? '安装' : '删除';
|
||||
const socketMessageType = isInstall
|
||||
? 'installDependence'
|
||||
: 'uninstallDependence';
|
||||
const isNodeDependence = dependency.type === DependenceTypes.nodejs;
|
||||
const isLinuxDependence = dependency.type === DependenceTypes.linux;
|
||||
const isPythonDependence = dependency.type === DependenceTypes.python3;
|
||||
const osType = await detectOS();
|
||||
let linuxCommand = {} as typeof LINUX_DEPENDENCE_COMMAND.Alpine;
|
||||
taskLimit.removeQueuedDependency(dependency);
|
||||
if (isLinuxDependence) {
|
||||
if (!osType) {
|
||||
await DependenceModel.update(
|
||||
{ status: DependenceStatus.installFailed },
|
||||
{ where: { id: depIds } },
|
||||
);
|
||||
const startTime = dayjs();
|
||||
const message = `开始${actionText}依赖 ${depName},开始时间 ${startTime.format(
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
)}\n\n当前系统不支持\n\n依赖${actionText}失败,结束时间 ${startTime.format(
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
)},耗时 ${startTime.diff(startTime, 'second')} 秒`;
|
||||
this.sockService.sendMessage({
|
||||
type: socketMessageType,
|
||||
message,
|
||||
references: depIds,
|
||||
});
|
||||
this.updateLog(depIds, message);
|
||||
return resolve(null);
|
||||
}
|
||||
linuxCommand = LINUX_DEPENDENCE_COMMAND[osType];
|
||||
}
|
||||
|
||||
const status = isInstall
|
||||
? DependenceStatus.installing
|
||||
: DependenceStatus.removing;
|
||||
await DependenceModel.update({ status }, { where: { id: depIds } });
|
||||
|
||||
const socketMessageType = isInstall
|
||||
? 'installDependence'
|
||||
: 'uninstallDependence';
|
||||
let depName = dependency.name.trim();
|
||||
const command = isInstall
|
||||
let command = isInstall
|
||||
? getInstallCommand(dependency.type, depName)
|
||||
: getUninstallCommand(dependency.type, depName);
|
||||
const actionText = isInstall ? '安装' : '删除';
|
||||
if (isLinuxDependence) {
|
||||
command = isInstall
|
||||
? `${linuxCommand.install} ${depName.trim()}`
|
||||
: `${linuxCommand.uninstall} ${depName.trim()}`;
|
||||
}
|
||||
const startTime = dayjs();
|
||||
|
||||
const message = `开始${actionText}依赖 ${depName},开始时间 ${startTime.format(
|
||||
@@ -248,8 +292,12 @@ export default class DependenceService {
|
||||
|
||||
// 判断是否已经安装过依赖
|
||||
if (isInstall && !force) {
|
||||
const getCommand = getGetCommand(dependency.type, depName);
|
||||
let getCommand = getGetCommand(dependency.type, depName);
|
||||
const depVersionStr = versionDependenceCommandTypes[dependency.type];
|
||||
if (isLinuxDependence) {
|
||||
getCommand = `${linuxCommand.info} ${depName}`;
|
||||
}
|
||||
|
||||
let depVersion = '';
|
||||
if (depName.includes(depVersionStr)) {
|
||||
const symbolRegx = new RegExp(
|
||||
@@ -261,10 +309,6 @@ export default class DependenceService {
|
||||
depVersion = _depVersion;
|
||||
}
|
||||
}
|
||||
const isNodeDependence = dependency.type === DependenceTypes.nodejs;
|
||||
const isLinuxDependence = dependency.type === DependenceTypes.linux;
|
||||
const isPythonDependence =
|
||||
dependency.type === DependenceTypes.python3;
|
||||
const depInfo = (await promiseExecSuccess(getCommand))
|
||||
.replace(/\s{2,}/, ' ')
|
||||
.replace(/\s+$/, '');
|
||||
@@ -273,7 +317,7 @@ export default class DependenceService {
|
||||
depInfo &&
|
||||
((isNodeDependence && depInfo.split(' ')?.[0] === depName) ||
|
||||
(isLinuxDependence &&
|
||||
depInfo.toLocaleLowerCase().includes('installed')) ||
|
||||
linuxCommand.check(depInfo.toLocaleLowerCase())) ||
|
||||
isPythonDependence) &&
|
||||
(!depVersion || depInfo.includes(depVersion))
|
||||
) {
|
||||
|
||||
+10
-24
@@ -37,6 +37,7 @@ import ScheduleService, { TaskCallbacks } from './schedule';
|
||||
import SockService from './sock';
|
||||
import os from 'os';
|
||||
import dayjs from 'dayjs';
|
||||
import { updateLinuxMirrorFile } from '../config/util';
|
||||
|
||||
@Service()
|
||||
export default class SystemService {
|
||||
@@ -214,33 +215,11 @@ export default class SystemService {
|
||||
onEnd?: () => void,
|
||||
) {
|
||||
const oDoc = await this.getSystemConfig();
|
||||
await this.updateAuthDb({
|
||||
...oDoc,
|
||||
info: { ...oDoc.info, ...info },
|
||||
});
|
||||
let defaultDomain = 'https://dl-cdn.alpinelinux.org';
|
||||
let targetDomain = 'https://dl-cdn.alpinelinux.org';
|
||||
if (os.platform() !== 'linux') {
|
||||
return;
|
||||
}
|
||||
const content = await fs.promises.readFile('/etc/apk/repositories', {
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
const domainMatch = content.match(/(http.*)\/alpine\/.*/);
|
||||
if (domainMatch) {
|
||||
defaultDomain = domainMatch[1];
|
||||
}
|
||||
if (info.linuxMirror) {
|
||||
targetDomain = info.linuxMirror;
|
||||
}
|
||||
const command = `sed -i 's/${defaultDomain.replace(
|
||||
/\//g,
|
||||
'\\/',
|
||||
)}/${targetDomain.replace(
|
||||
/\//g,
|
||||
'\\/',
|
||||
)}/g' /etc/apk/repositories && apk update -f`;
|
||||
|
||||
const command = await updateLinuxMirrorFile(info.linuxMirror || '');
|
||||
let hasError = false;
|
||||
this.scheduleService.runTask(
|
||||
command,
|
||||
{
|
||||
@@ -254,8 +233,15 @@ export default class SystemService {
|
||||
message: 'update linux mirror end',
|
||||
});
|
||||
onEnd?.();
|
||||
if (!hasError) {
|
||||
await this.updateAuthDb({
|
||||
...oDoc,
|
||||
info: { ...oDoc.info, ...info },
|
||||
});
|
||||
}
|
||||
},
|
||||
onError: async (message: string) => {
|
||||
hasError = true;
|
||||
this.sockService.sendMessage({ type: 'updateLinuxMirror', message });
|
||||
},
|
||||
onLog: async (message: string) => {
|
||||
|
||||
Reference in New Issue
Block a user