Compare commits

...
12 Commits
Author SHA1 Message Date
whyour acb43f3ad8 更新版本 v2.13.2 2022-06-01 00:28:35 +08:00
whyour b160f914ad 修改订阅执行逻辑 2022-06-01 00:25:32 +08:00
whyour 6116aa6d12 修复私钥配置文件匹配 2022-06-01 00:03:58 +08:00
whyour d43cee53c9 修改interval_schedule验证 2022-05-30 10:26:30 +08:00
whyour defea8ff9b 修复订阅添加定时规则 2022-05-30 10:21:15 +08:00
whyour b290b60d46 修复新建订阅定时 2022-05-30 09:58:51 +08:00
whyour 706b5e8108 修复订阅任务创建逻辑 2022-05-29 22:51:36 +08:00
whyour b55c7d5747 修复依赖安装顺序,优先linux依赖安装 2022-05-29 15:01:48 +08:00
whyour 6b8fd94f0c 系统启动安装依赖优先安装linux依赖 2022-05-29 11:35:31 +08:00
whyour e18710a30a 更新dockerfile 2022-05-29 11:13:32 +08:00
whyour c0f0da4e96 修复dockerfile 2022-05-29 10:18:08 +08:00
whyour 49ef5cd61f 修复pnpm环境变量 2022-05-29 10:02:03 +08:00
11 changed files with 78 additions and 36 deletions
+7 -1
View File
@@ -29,7 +29,13 @@ export default (app: Router) => {
body: Joi.object({
type: Joi.string().required(),
schedule: Joi.string().optional().allow('').allow(null),
interval_schedule: Joi.object().optional().allow('').allow(null),
interval_schedule: Joi.object({
type: Joi.string().required(),
value: Joi.number().min(1).required(),
})
.optional()
.allow('')
.allow(null),
name: Joi.string().optional().allow('').allow(null),
url: Joi.string().required(),
whitelist: Joi.string().optional().allow('').allow(null),
+7 -4
View File
@@ -21,15 +21,18 @@ export default async () => {
);
// 初始化时安装所有处于安装中,安装成功,安装失败的依赖
DependenceModel.findAll({ where: {}, raw: true }).then(async (docs) => {
DependenceModel.findAll({
where: {},
order: [['type', 'DESC']],
raw: true,
}).then(async (docs) => {
const groups = _.groupBy(docs, 'type');
for (const key in groups) {
if (Object.prototype.hasOwnProperty.call(groups, key)) {
const keys = Object.keys(groups).sort((a, b) => parseInt(b) - parseInt(a));
for (const key of keys) {
const group = groups[key];
const depIds = group.map((x) => x.id);
await dependenceService.reInstall(depIds as number[]);
}
}
});
// 初始化时执行一次所有的ql repo 任务
+6 -1
View File
@@ -26,6 +26,11 @@ export default async () => {
// 运行所有订阅
const subs = await subscriptionService.list();
for (const sub of subs) {
await subscriptionService.handleTask(sub, true, true, true);
await subscriptionService.handleTask(
sub,
!sub.is_disabled,
true,
!sub.is_disabled,
);
}
};
+3
View File
@@ -18,6 +18,7 @@ interface ScheduleTaskType {
}
export interface TaskCallbacks {
onBefore?: (startTime: dayjs.Dayjs) => Promise<void>;
onStart?: (
cp: ChildProcessWithoutNullStreams,
startTime: dayjs.Dayjs,
@@ -45,6 +46,8 @@ export default class ScheduleService {
return new Promise(async (resolve, reject) => {
try {
const startTime = dayjs();
await callbacks.onBefore?.(startTime);
const cp = spawn(command, { shell: '/bin/bash' });
// TODO:
+13 -5
View File
@@ -23,6 +23,13 @@ export default class SshKeyService {
}
}
private getConfigRegx(alias: string) {
return new RegExp(
`Host ${alias}\n.*[^StrictHostKeyChecking]*.*[\n]*.*StrictHostKeyChecking no`,
'g',
);
}
private removePrivateKeyFile(alias: string): void {
try {
fs.unlinkSync(`${this.sshPath}/${alias}`);
@@ -47,24 +54,25 @@ export default class SshKeyService {
}
}
private removeSshConfig(config: string) {
private removeSshConfig(alias: string) {
try {
const configRegx = this.getConfigRegx(alias);
const data = fs
.readFileSync(this.sshConfigFilePath, { encoding: 'utf8' })
.replace(config, '')
.replace(/\n\n+/, '\n\n');
.replace(configRegx, '')
.replace(/\n[\n]+/g, '\n');
fs.writeFileSync(this.sshConfigFilePath, data, {
encoding: 'utf8',
});
} catch (error) {
this.logger.error(`删除ssh配置文件${config}失败`, error);
this.logger.error(`删除ssh配置文件${alias}失败`, error);
}
}
public addSSHKey(key: string, alias: string, host: string): void {
this.generatePrivateKeyFile(alias, key);
const config = this.generateSingleSshConfig(alias, host);
this.removeSshConfig(config);
this.removeSshConfig(alias);
this.generateSshConfig([config]);
}
+12 -6
View File
@@ -192,14 +192,13 @@ export default class SubscriptionService {
private taskCallbacks(doc: Subscription): TaskCallbacks {
return {
onStart: async (cp: ChildProcessWithoutNullStreams, startTime) => {
onBefore: async (startTime) => {
const logTime = startTime.format('YYYY-MM-DD-HH-mm-ss');
const logPath = `${doc.alias}/${logTime}.log`;
await SubscriptionModel.update(
{
status: SubscriptionStatus.running,
log_path: logPath,
pid: cp.pid,
},
{ where: { id: doc.id } },
);
@@ -220,9 +219,17 @@ export default class SubscriptionService {
(error.stderr && error.stderr.toString()) || JSON.stringify(error);
}
if (beforeStr) {
fs.appendFileSync(absolutePath, `${beforeStr}\n\n`);
fs.appendFileSync(absolutePath, `${beforeStr}\n`);
}
},
onStart: async (cp: ChildProcessWithoutNullStreams, startTime) => {
await SubscriptionModel.update(
{
pid: cp.pid,
},
{ where: { id: doc.id } },
);
},
onEnd: async (cp, endTime, diff) => {
const sub = await this.getDb({ id: doc.id });
const absolutePath = await this.handleLogPath(sub.log_path as string);
@@ -231,7 +238,7 @@ export default class SubscriptionService {
let afterStr = '';
try {
if (sub.sub_after) {
fs.appendFileSync(absolutePath, `\n\n## 执行after命令...\n`);
fs.appendFileSync(absolutePath, `\n\n## 执行after命令...\n\n`);
afterStr = await this.promiseExec(sub.sub_after);
}
} catch (error: any) {
@@ -286,7 +293,7 @@ export default class SubscriptionService {
public async update(payload: Subscription): Promise<Subscription> {
const newDoc = await this.updateDb(payload);
await this.handleTask(newDoc);
await this.handleTask(newDoc, !newDoc.is_disabled);
return newDoc;
}
@@ -360,7 +367,6 @@ export default class SubscriptionService {
this.logger.silly(error);
}
}
await this.handleTask(doc, false);
const command = this.formatCommand(doc);
const err = await this.killTask(command);
const absolutePath = await this.handleLogPath(doc.log_path as string);
+2 -3
View File
@@ -5,7 +5,8 @@ LABEL maintainer="${QL_MAINTAINER}"
ARG QL_URL=https://github.com/${QL_MAINTAINER}/qinglong.git
ARG QL_BRANCH=master
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/.local/share/pnpm:/root/.local/share/pnpm/global/5/node_modules \
ENV PNPM_HOME=/root/.local/share/pnpm \
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/.local/share/pnpm:/root/.local/share/pnpm/global/5/node_modules:$PNPM_HOME \
LANG=zh_CN.UTF-8 \
SHELL=/bin/bash \
PS1="\u@\h:\w \$ " \
@@ -38,8 +39,6 @@ RUN set -x \
&& git config --global user.email "qinglong@@users.noreply.github.com" \
&& git config --global user.name "qinglong" \
&& npm install -g pnpm \
&& pnpm setup \
&& source ~/.bashrc \
&& pnpm add -g pm2 ts-node typescript tslib \
&& git clone -b ${QL_BRANCH} ${QL_URL} ${QL_DIR} \
&& cd ${QL_DIR} \
+3 -3
View File
@@ -40,8 +40,8 @@
},
"dependencies": {
"@otplib/preset-default": "^12.0.1",
"@sentry/node": "^6.18.1",
"@sentry/tracing": "^6.18.1",
"@sentry/node": "^7.0.0",
"@sentry/tracing": "^7.0.0",
"body-parser": "^1.19.2",
"celebrate": "^15.0.1",
"chokidar": "^3.5.3",
@@ -77,7 +77,7 @@
"@ant-design/icons": "^4.7.0",
"@ant-design/pro-layout": "^6.33.1",
"@monaco-editor/react": "^4.3.1",
"@sentry/react": "^6.18.1",
"@sentry/react": "^7.0.0",
"@types/body-parser": "^1.19.2",
"@types/cors": "^2.8.12",
"@types/express": "^4.17.13",
+6
View File
@@ -107,12 +107,18 @@ const SubscriptionModal = ({
const [intervalNumber, setIntervalNumber] = useState<number>();
const intervalTypeChange = (type: string) => {
setIntervalType(type);
if (intervalNumber && intervalNumber > 0) {
onChange?.({ type, value: intervalNumber });
}
};
const numberChange = (value: number) => {
setIntervalNumber(value);
if (!value) {
onChange?.(null);
} else {
onChange?.({ type: intervalType, value });
}
};
useEffect(() => {
+8 -2
View File
@@ -7,9 +7,15 @@ export function init() {
// sentry监控 init
Sentry.init({
dsn: 'https://3406424fb1dc4813a62d39e844a9d0ac@o1098464.ingest.sentry.io/6122818',
integrations: [new Integrations.BrowserTracing()],
integrations: [
new Integrations.BrowserTracing({
shouldCreateSpanForRequest(url) {
return !url.includes('/api/ws') && !url.includes('/api/static');
},
}),
],
release: version,
tracesSampleRate: 1.0,
tracesSampleRate: 0.1,
beforeBreadcrumb(breadcrumb, hint?) {
if (breadcrumb.data && breadcrumb.data.url) {
const url = breadcrumb.data.url.replace(/token=.*/, '');
+6 -6
View File
@@ -1,8 +1,8 @@
export const version = '2.13.1';
export const version = '2.13.2';
export const changeLogLink = 'https://t.me/jiao_long/303';
export const changeLog = `2.13.1 版本说明
1. 修复新建订阅repo命令快捷导入
2. 修复执行订阅任务含有before/after命令时,造成面板无法访问
3. 修复任务详情日志列表访问
4. 修复安装依赖造成CPU满负荷,服务器崩溃
export const changeLog = `2.13.2 版本说明
1. 修复nodejs依赖安装失败pnpm setup
2. 修复订阅禁用失效
3. 修复新建订阅定时验证
4. 修复ssh配置文件更新逻辑
`;