增加运行指定命令接口

This commit is contained in:
whyour 2023-05-01 14:28:58 +08:00
parent df1addc1ff
commit aab6bbeb15
7 changed files with 124 additions and 25 deletions

View File

@ -7,7 +7,12 @@ import SystemService from '../services/system';
import { celebrate, Joi } from 'celebrate';
import UserService from '../services/user';
import { EnvModel } from '../data/env';
import { parseVersion, promiseExec } from '../config/util';
import {
getUniqPath,
handleLogPath,
parseVersion,
promiseExec,
} from '../config/util';
import dayjs from 'dayjs';
const route = Router();
@ -147,4 +152,40 @@ export default (app: Router) => {
}
},
);
route.put(
'/command-run',
celebrate({
body: Joi.object({
command: Joi.string().required(),
}),
}),
async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger');
try {
const systemService = Container.get(SystemService);
const uniqPath = await getUniqPath(req.body.command);
const logTime = dayjs().format('YYYY-MM-DD-HH-mm-ss');
const logPath = `${uniqPath}/${logTime}.log`;
res.setHeader('Content-type', 'application/octet-stream');
await systemService.run(req.body, {
onEnd: async (cp, endTime, diff) => {
res.end();
},
onError: async (message: string) => {
res.write(`\n${message}`);
const absolutePath = await handleLogPath(logPath);
fs.appendFileSync(absolutePath, `\n${message}`);
},
onLog: async (message: string) => {
res.write(`\n${message}`);
const absolutePath = await handleLogPath(logPath);
fs.appendFileSync(absolutePath, `\n${message}`);
},
});
} catch (e) {
return next(e);
}
},
);
};

View File

@ -7,6 +7,8 @@ import FormData from 'form-data';
import psTreeFun from 'pstree.remy';
import { promisify } from 'util';
import { load } from 'js-yaml';
import config from './index';
import { TASK_COMMAND } from './const';
export function getFileContentByName(fileName: string) {
if (fs.existsSync(fileName)) {
@ -245,6 +247,18 @@ export async function createFile(file: string, data: string = '') {
});
}
export async function handleLogPath(
logPath: string,
data: string = '',
): Promise<string> {
const absolutePath = path.resolve(config.logPath, logPath);
const logFileExist = await fileExist(absolutePath);
if (!logFileExist) {
await createFile(absolutePath, data);
}
return absolutePath;
}
export async function concurrentRun(
fnList: Array<() => Promise<any>> = [],
max = 5,
@ -501,3 +515,40 @@ export async function parseVersion(path: string): Promise<IVersion> {
export async function parseContentVersion(content: string): Promise<IVersion> {
return load(content) as IVersion;
}
export async function getUniqPath(command: string): Promise<string> {
const idStr = `cat ${config.crontabFile} | grep -E "${command}" | perl -pe "s|.*ID=(.*) ${command}.*|\\1|" | head -1 | awk -F " " '{print $1}' | xargs echo -n`;
let id = await promiseExec(idStr);
if (/^\d\d*\d$/.test(id)) {
id = `_${id}`;
} else {
id = '';
}
const items = command.split(/ +/);
let str = items[0];
if (items[0] === TASK_COMMAND) {
str = items[1];
}
const dotIndex = str.lastIndexOf('.');
if (dotIndex !== -1) {
str = str.slice(0, dotIndex);
}
const slashIndex = str.lastIndexOf('/');
let tempStr = '';
if (slashIndex !== -1) {
tempStr = str.slice(0, slashIndex);
const _slashIndex = tempStr.lastIndexOf('/');
if (_slashIndex !== -1) {
tempStr = tempStr.slice(_slashIndex + 1);
}
str = `${tempStr}_${str.slice(slashIndex + 1)}`;
}
return `${str}${id}`;
}

View File

@ -19,6 +19,7 @@ import {
fileExist,
createFile,
killTask,
handleLogPath,
} from '../config/util';
import { promises, existsSync } from 'fs';
import { FindOptions, Op } from 'sequelize';
@ -121,18 +122,6 @@ export default class SubscriptionService {
});
}
private async handleLogPath(
logPath: string,
data: string = '',
): Promise<string> {
const absolutePath = path.resolve(config.logPath, logPath);
const logFileExist = await fileExist(absolutePath);
if (!logFileExist) {
await createFile(absolutePath, data);
}
return absolutePath;
}
private taskCallbacks(doc: Subscription): TaskCallbacks {
return {
onBefore: async (startTime) => {
@ -145,7 +134,7 @@ export default class SubscriptionService {
},
{ where: { id: doc.id } },
);
const absolutePath = await this.handleLogPath(
const absolutePath = await handleLogPath(
logPath as string,
`## 开始执行... ${startTime.format('YYYY-MM-DD HH:mm:ss')}\n`,
);
@ -175,7 +164,7 @@ export default class SubscriptionService {
},
onEnd: async (cp, endTime, diff) => {
const sub = await this.getDb({ id: doc.id });
const absolutePath = await this.handleLogPath(sub.log_path as string);
const absolutePath = await handleLogPath(sub.log_path as string);
// 执行 sub_after
let afterStr = '';
@ -212,12 +201,12 @@ export default class SubscriptionService {
},
onError: async (message: string) => {
const sub = await this.getDb({ id: doc.id });
const absolutePath = await this.handleLogPath(sub.log_path as string);
const absolutePath = await handleLogPath(sub.log_path as string);
fs.appendFileSync(absolutePath, `\n${message}`);
},
onLog: async (message: string) => {
const sub = await this.getDb({ id: doc.id });
const absolutePath = await this.handleLogPath(sub.log_path as string);
const absolutePath = await handleLogPath(sub.log_path as string);
fs.appendFileSync(absolutePath, `\n${message}`);
},
};
@ -236,7 +225,7 @@ export default class SubscriptionService {
}
public async update(payload: Subscription): Promise<Subscription> {
const doc = await this.getDb({ id: payload.id })
const doc = await this.getDb({ id: payload.id });
const tab = new Subscription({ ...doc, ...payload });
const newDoc = await this.updateDb(tab);
await this.handleTask(newDoc, !newDoc.is_disabled);
@ -289,7 +278,9 @@ export default class SubscriptionService {
await this.setSshConfig();
}
public async getDb(query: FindOptions<Subscription>['where']): Promise<Subscription> {
public async getDb(
query: FindOptions<Subscription>['where'],
): Promise<Subscription> {
const doc: any = await SubscriptionModel.findOne({ where: { ...query } });
return doc && (doc.get({ plain: true }) as Subscription);
}
@ -315,7 +306,7 @@ export default class SubscriptionService {
this.logger.silly(error);
}
}
const absolutePath = await this.handleLogPath(doc.log_path as string);
const absolutePath = await handleLogPath(doc.log_path as string);
fs.appendFileSync(
`${absolutePath}`,
@ -369,7 +360,7 @@ export default class SubscriptionService {
return '';
}
const absolutePath = await this.handleLogPath(doc.log_path as string);
const absolutePath = await handleLogPath(doc.log_path as string);
return getFileContentByName(absolutePath);
}

View File

@ -5,11 +5,12 @@ import * as fs from 'fs';
import { AuthDataType, AuthInfo, AuthModel, LoginStatus } from '../data/auth';
import { NotificationInfo } from '../data/notify';
import NotificationService from './notify';
import ScheduleService from './schedule';
import ScheduleService, { TaskCallbacks } from './schedule';
import { spawn } from 'child_process';
import SockService from './sock';
import got from 'got';
import { parseContentVersion, parseVersion } from '../config/util';
import { TASK_COMMAND } from '../config/const';
@Service()
export default class SystemService {
@ -170,4 +171,11 @@ export default class SystemService {
return { code: 400, message: '通知发送失败,请检查系统设置/通知配置' };
}
}
public async run({ command }: { command: string }, callback: TaskCallbacks) {
if (!command.startsWith(TASK_COMMAND)) {
command = `${TASK_COMMAND} ${command}`;
}
this.scheduleService.runTask(`real_time=true ${command}`, callback);
}
}

View File

@ -178,7 +178,7 @@ update_cron() {
code=$(echo "$api" | jq -r .code)
message=$(echo "$api" | jq -r .message)
if [[ $code != 200 ]]; then
echo -e "\n## 更新任务状态失败(${message})\n" >>$dir_log/$log_path
echo -e "\n## 更新任务状态失败(${message})\n"
fi
}

View File

@ -89,7 +89,7 @@ check_server() {
## 正常运行单个脚本,$1传入参数
run_normal() {
local file_param=$1
if [[ $# -eq 1 ]]; then
if [[ $# -eq 1 ]] && [[ "$real_time" != "true" ]]; then
random_delay "$file_param"
fi

View File

@ -43,7 +43,11 @@ handle_log_path() {
fi
local suffix=""
if [[ ! -z $ID ]]; then
suffix="_${ID}"
if [[ "$ID" -gt 0 ]] 2>/dev/null; then
suffix="_${ID}"
else
ID=""
fi
fi
time=$(date "+$mtime_format")
@ -66,6 +70,10 @@ handle_log_path() {
if [[ "$show_log" == "true" ]]; then
cmd="2>&1 | tee -a $dir_log/$log_path"
fi
if [[ "$real_time" == "true" ]]; then
cmd=""
fi
}
format_params() {