Refactor: 重命名

This commit is contained in:
Suwings 2022-07-09 13:05:03 +08:00
parent e54227522b
commit 9fc0d4d83d

View File

@ -1,160 +0,0 @@
/*
Copyright (C) 2022 Suwings <Suwings@outlook.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
According to the AGPL, it is forbidden to delete all copyright notices,
and if you modify the source code, you must open source the
modified source code.
(C) 2022 Suwings <Suwings@outlook.com>
/ GNU Affero
3
AGPL
https://mcsmanager.com/ 阅读用户协议,申请闭源开发授权等。
*/
import os from "os";
import Instance from "../../instance/instance";
import logger from "../../../service/log";
import fs from "fs-extra";
import path from "path";
import InstanceCommand from "../base/command";
import EventEmitter from "events";
import { IInstanceProcess } from "../../../entity/instance/interface";
import { ChildProcess, exec, spawn } from "child_process";
import { commandStringToArray } from "../base/command_parser";
import { killProcess } from "../../../common/process_tools";
// 启动时错误异常
class StartupError extends Error {
constructor(msg: string) {
super(msg);
}
}
// 进程适配器
class ProcessAdapter extends EventEmitter implements IInstanceProcess {
pid?: number | string;
constructor(private process: ChildProcess) {
super();
this.pid = this.process.pid;
process.stdout.on("data", (text) => this.emit("data", text));
process.stderr.on("data", (text) => this.emit("data", text));
process.on("exit", (code) => this.emit("exit", code));
}
public write(data?: string) {
return this.process.stdin.write(data);
}
public kill(s?: any) {
return killProcess(this.pid, this.process, s);
}
public async destroy() {
try {
if (this.process && this.process.stdout && this.process.stderr) {
// 移除所有动态新增的事件监听者
for (const eventName of this.process.stdout.eventNames()) this.process.stdout.removeAllListeners(eventName);
for (const eventName of this.process.stderr.eventNames()) this.process.stderr.removeAllListeners(eventName);
for (const eventName of this.process.eventNames()) this.process.removeAllListeners(eventName);
this.process.stdout.destroy();
this.process.stderr.destroy();
}
} catch (error) {}
}
}
export default class PtyStartCommand extends InstanceCommand {
constructor() {
super("PtyStartCommand");
}
async exec(instance: Instance, source = "Unknown") {
if (!instance.config.startCommand || !instance.config.cwd || !instance.config.ie || !instance.config.oe) return instance.failure(new StartupError("启动命令,输入输出编码或工作目录为空值"));
if (!fs.existsSync(instance.absoluteCwdPath())) return instance.failure(new StartupError("工作目录并不存在"));
try {
instance.setLock(true);
// 设置启动状态
instance.status(Instance.STATUS_STARTING);
// 启动次数增加
instance.startCount++;
// 命令解析
const commandList = commandStringToArray(instance.config.startCommand);
if (commandList.length === 0) {
return instance.failure(new StartupError("无法启动实例,启动命令为空"));
}
let ptyAppName = "pty.exe";
if (os.platform() !== "win32") ptyAppName = "pty";
const ptyAppPath = path.normalize(path.join(process.cwd(), "lib", ptyAppName));
const ptyParameter = ["-dir", instance.config.cwd, "-cmd", commandList.join(" "), "-size", `${instance.config.ptyWindowCol},${instance.config.ptyWindowRow}`];
logger.info("----------------");
logger.info(`会话 ${source}: 请求开启实例.`);
logger.info(`实例标识符: [${instance.instanceUuid}]`);
logger.info(`启动命令: ${commandList.join(" ")}`);
logger.info(`PTY 路径: ${[ptyAppPath]}`);
logger.info(`PTY 参数: ${ptyParameter.join(" ")}`);
logger.info(`工作目录: ${instance.config.cwd}`);
logger.info("----------------");
if (!fs.existsSync(ptyAppPath)) {
console.log(ptyAppPath);
return instance.failure(new StartupError("PTY 转发程序不存在,请勿使用 PTY 模式,请在终端设置中更改"));
}
// 创建子进程
// 参数1直接传进程名或路径含空格无需双引号
console.log(path.dirname(ptyAppPath));
const subProcess = spawn(ptyAppName, ptyParameter, {
cwd: path.dirname(ptyAppPath),
stdio: "pipe",
windowsHide: true
});
// 子进程创建结果检查
if (!subProcess || !subProcess.pid) {
instance.println(
"ERROR",
`检测到实例进程/容器启动失败PID 为空),其可能的原因是:
1.
2. Java
${instance.config.startCommand}
:
${ptyAppName}
${JSON.stringify(ptyParameter)}
`
);
throw new StartupError("实例启动失败,请检查启动命令,主机环境和配置文件等");
}
// 创建进程适配器
const processAdapter = new ProcessAdapter(subProcess);
// 产生开启事件
instance.started(processAdapter);
logger.info(`实例 ${instance.instanceUuid} 成功启动 PID: ${process.pid}.`);
} catch (err) {
instance.instanceStatus = Instance.STATUS_STOP;
instance.releaseResources();
return instance.failure(err);
} finally {
instance.setLock(false);
}
}
}