修改系统重启逻辑

This commit is contained in:
whyour 2024-03-14 17:37:52 +08:00
parent 2ac4581d54
commit 7a8a8ab9b3
10 changed files with 91 additions and 64 deletions

View File

@ -5,28 +5,6 @@ import Sock from './sock';
export default async ({ server }: { server: Server }) => { export default async ({ server }: { server: Server }) => {
await Sock({ server }); await Sock({ server });
Logger.info('✌️ Sock loaded'); Logger.info('✌️ Sock loaded');
let exitTime = 0;
let timer: NodeJS.Timeout;
process.on('SIGINT', (singal) => {
Logger.warn(`Server need close, singal ${singal}`);
console.warn(`Server need close, singal ${singal}`);
exitTime++;
if (exitTime >= 3) {
Logger.warn('Forcing server close');
console.warn('Forcing server close');
clearTimeout(timer);
process.exit(1);
}
server.close(() => {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
process.exit();
}, 15000);
});
});
process.on('uncaughtException', (error) => { process.on('uncaughtException', (error) => {
Logger.error('Uncaught exception:', error); Logger.error('Uncaught exception:', error);

View File

@ -4,9 +4,9 @@ import cors from 'cors';
import { Application, NextFunction, Request, Response } from 'express'; import { Application, NextFunction, Request, Response } from 'express';
import jwt from 'express-jwt'; import jwt from 'express-jwt';
import Container from 'typedi'; import Container from 'typedi';
import Logger from './logger';
import config from '../config'; import config from '../config';
import SystemService from '../services/system'; import SystemService from '../services/system';
import Logger from './logger';
export default ({ app }: { app: Application }) => { export default ({ app }: { app: Application }) => {
app.set('trust proxy', 'loopback'); app.set('trust proxy', 'loopback');
@ -22,6 +22,20 @@ export default ({ app }: { app: Application }) => {
}), }),
); );
app.put(
'/api/reload',
async (req: Request, res: Response, next: NextFunction) => {
try {
const systemService = Container.get(SystemService);
const result = await systemService.reloadSystem();
res.send(result);
} catch (e) {
Logger.error('🔥 error: %o', e);
return next(e);
}
},
);
app.put( app.put(
'/api/system', '/api/system',
async (req: Request, res: Response, next: NextFunction) => { async (req: Request, res: Response, next: NextFunction) => {
@ -35,6 +49,7 @@ export default ({ app }: { app: Application }) => {
} }
}, },
); );
app.put( app.put(
'/api/data', '/api/data',
async (req: Request, res: Response, next: NextFunction) => { async (req: Request, res: Response, next: NextFunction) => {

View File

@ -1,20 +1,14 @@
import { spawn } from 'cross-spawn';
import { Response } from 'express'; import { Response } from 'express';
import { Service, Inject } from 'typedi'; import fs from 'fs';
import got from 'got';
import sum from 'lodash/sum';
import path from 'path';
import tar from 'tar';
import { Inject, Service } from 'typedi';
import winston from 'winston'; import winston from 'winston';
import config from '../config'; import config from '../config';
import { import { TASK_COMMAND } from '../config/const';
AuthDataType,
AuthInfo,
SystemInstance,
SystemModel,
SystemModelInfo,
} from '../data/system';
import { NotificationInfo } from '../data/notify';
import NotificationService from './notify';
import ScheduleService, { TaskCallbacks } from './schedule';
import { spawn } from 'cross-spawn';
import SockService from './sock';
import got from 'got';
import { import {
getPid, getPid,
killTask, killTask,
@ -23,13 +17,23 @@ import {
promiseExec, promiseExec,
readDirs, readDirs,
} from '../config/util'; } from '../config/util';
import { TASK_COMMAND } from '../config/const'; import {
DependenceModel,
DependenceStatus,
DependenceTypes,
} from '../data/dependence';
import { NotificationInfo } from '../data/notify';
import {
AuthDataType,
AuthInfo,
SystemInstance,
SystemModel,
SystemModelInfo,
} from '../data/system';
import taskLimit from '../shared/pLimit'; import taskLimit from '../shared/pLimit';
import tar from 'tar'; import NotificationService from './notify';
import path from 'path'; import ScheduleService, { TaskCallbacks } from './schedule';
import fs from 'fs'; import SockService from './sock';
import sum from 'lodash/sum';
import { DependenceModel, DependenceStatus, DependenceTypes } from '../data/dependence';
@Service() @Service()
export default class SystemService { export default class SystemService {
@ -139,7 +143,10 @@ export default class SystemService {
} }
let command = `cd && ${cmd}`; let command = `cd && ${cmd}`;
const docs = await DependenceModel.findAll({ const docs = await DependenceModel.findAll({
where: { type: DependenceTypes.nodejs, status: DependenceStatus.installed }, where: {
type: DependenceTypes.nodejs,
status: DependenceStatus.installed,
},
}); });
if (docs.length > 0) { if (docs.length > 0) {
command += ` && pnpm i -g`; command += ` && pnpm i -g`;
@ -326,7 +333,7 @@ export default class SystemService {
return { code: 200 }; return { code: 200 };
} }
public async reloadSystem(target: 'system' | 'data') { public async reloadSystem(target?: 'system' | 'data') {
const cmd = `real_time=true ql reload ${target || ''}`; const cmd = `real_time=true ql reload ${target || ''}`;
const cp = spawn(cmd, { shell: '/bin/bash' }); const cp = spawn(cmd, { shell: '/bin/bash' });
cp.unref(); cp.unref();
@ -382,8 +389,13 @@ export default class SystemService {
public async exportData(res: Response) { public async exportData(res: Response) {
try { try {
await tar.create( tar.create(
{ gzip: true, file: config.dataTgzFile, cwd: config.rootPath }, {
gzip: true,
file: config.dataTgzFile,
cwd: config.rootPath,
sync: true,
},
['data'], ['data'],
); );
res.download(config.dataTgzFile); res.download(config.dataTgzFile);
@ -395,7 +407,7 @@ export default class SystemService {
public async importData() { public async importData() {
try { try {
await promiseExec(`rm -rf ${path.join(config.tmpPath, 'data')}`); await promiseExec(`rm -rf ${path.join(config.tmpPath, 'data')}`);
await tar.x({ file: config.dataTgzFile, cwd: config.tmpPath }); tar.x({ file: config.dataTgzFile, cwd: config.tmpPath, sync: true });
return { code: 200 }; return { code: 200 };
} catch (error: any) { } catch (error: any) {
return { code: 400, message: error.message }; return { code: 400, message: error.message };

View File

@ -21,6 +21,7 @@ nginx -s reload 2>/dev/null || nginx -c /etc/nginx/nginx.conf
echo -e "nginx启动成功...\n" echo -e "nginx启动成功...\n"
echo -e "======================4. 启动pm2服务========================\n" echo -e "======================4. 启动pm2服务========================\n"
reload_update
reload_pm2 reload_pm2
if [[ $AutoStartBot == true ]]; then if [[ $AutoStartBot == true ]]; then

View File

@ -1,14 +1,5 @@
module.exports = { module.exports = {
apps: [ apps: [
{
name: 'update',
max_restarts: 10,
kill_timeout: 15000,
wait_ready: true,
listen_timeout: 10000,
time: true,
script: 'static/build/update.js',
},
{ {
name: 'schedule', name: 'schedule',
max_restarts: 10, max_restarts: 10,

13
other.config.js Normal file
View File

@ -0,0 +1,13 @@
module.exports = {
apps: [
{
name: 'update',
max_restarts: 10,
kill_timeout: 15000,
wait_ready: true,
listen_timeout: 10000,
time: true,
script: 'static/build/update.js',
},
],
};

View File

@ -81,6 +81,7 @@ main() {
check_ql check_ql
check_nginx check_nginx
check_pm2 check_pm2
reload_update
reload_pm2 reload_pm2
echo -e "\n=====> 检测结束\n" echo -e "\n=====> 检测结束\n"
} }

View File

@ -305,6 +305,11 @@ random_range() {
echo $((RANDOM % ($end - $beg) + $beg)) echo $((RANDOM % ($end - $beg) + $beg))
} }
delete_pm2() {
cd $dir_root
pm2 delete ecosystem.config.js
}
reload_pm2() { reload_pm2() {
cd $dir_root cd $dir_root
restore_env_vars restore_env_vars
@ -312,6 +317,13 @@ reload_pm2() {
pm2 startOrGracefulReload ecosystem.config.js pm2 startOrGracefulReload ecosystem.config.js
} }
reload_update() {
cd $dir_root
restore_env_vars
pm2 flush &>/dev/null
pm2 startOrGracefulReload other.config.js
}
diff_time() { diff_time() {
local format="$1" local format="$1"
local begin_time="$2" local begin_time="$2"

View File

@ -231,6 +231,8 @@ usage() {
} }
reload_qinglong() { reload_qinglong() {
delete_pm2
local reload_target="${1}" local reload_target="${1}"
local primary_branch="master" local primary_branch="master"
if [[ "${QL_BRANCH}" == "develop" ]]; then if [[ "${QL_BRANCH}" == "develop" ]]; then
@ -245,8 +247,8 @@ reload_qinglong() {
fi fi
if [[ "$reload_target" == 'data' ]]; then if [[ "$reload_target" == 'data' ]]; then
rm -rf ${dir_root}/data rm -rf ${dir_root}/data/*
cp -rf ${dir_tmp}/data ${dir_root}/ mv -f ${dir_tmp}/data/* ${dir_root}/data/
fi fi
reload_pm2 reload_pm2
@ -310,6 +312,8 @@ check_update_dep() {
echo -e "更新包下载成功..." echo -e "更新包下载成功..."
if [[ "$needRestart" == 'true' ]]; then if [[ "$needRestart" == 'true' ]]; then
delete_pm2
cp -rf ${dir_tmp}/qinglong-${primary_branch}/* ${dir_root}/ cp -rf ${dir_tmp}/qinglong-${primary_branch}/* ${dir_root}/
rm -rf $dir_static/* rm -rf $dir_static/*
cp -rf ${dir_tmp}/qinglong-static-${primary_branch}/* ${dir_static}/ cp -rf ${dir_tmp}/qinglong-static-${primary_branch}/* ${dir_static}/

View File

@ -1,10 +1,10 @@
import intl from 'react-intl-universal';
import React, { useEffect, useState, useRef, useCallback } from 'react';
import { Statistic, Modal, Tag, Button, Spin, message } from 'antd';
import { request } from '@/utils/http';
import config from '@/utils/config'; import config from '@/utils/config';
import { request } from '@/utils/http';
import WebSocketManager from '@/utils/websocket'; import WebSocketManager from '@/utils/websocket';
import Ansi from 'ansi-to-react'; import Ansi from 'ansi-to-react';
import { Button, Modal, Statistic, message } from 'antd';
import { useCallback, useEffect, useRef, useState } from 'react';
import intl from 'react-intl-universal';
const { Countdown } = Statistic; const { Countdown } = Statistic;
@ -220,7 +220,7 @@ const CheckUpdate = ({ systemInfo }: any) => {
</Button> </Button>
<Button <Button
type="primary" type="primary"
onClick={() => reloadSystem('system')} onClick={() => reloadSystem('reload')}
style={{ marginLeft: 8 }} style={{ marginLeft: 8 }}
> >
{intl.get('重新启动')} {intl.get('重新启动')}