diff --git a/src/entity/commands/dispatcher.ts b/src/entity/commands/dispatcher.ts index beb88ac..f4a0669 100644 --- a/src/entity/commands/dispatcher.ts +++ b/src/entity/commands/dispatcher.ts @@ -36,6 +36,7 @@ import TimeCheck from "./task/time"; import MinecraftBedrockGetPlayersCommand from "../minecraft/mc_getplayer_bedrock"; import GeneralUpdateCommand from "./general/general_update"; import PtyStartCommand from "./pty/pty_start"; +import PtyStopCommand from "./pty/pty_stop"; // 实例功能调度器 // 根据不同的类型调度分配不同的功能 @@ -68,10 +69,12 @@ export default class FunctionDispatcher extends InstanceCommand { if (instance.config.terminalOption.pty && instance.config.terminalOption.ptyWindowCol && instance.config.terminalOption.ptyWindowRow) { if (!fs.existsSync(ptyProgramPath)) throw new Error("无法启用 PTY 模式,因为 ./lib/pty 附属程序不存在"); instance.setPreset("start", new PtyStartCommand()); + instance.setPreset("stop", new PtyStopCommand()); + instance.setPreset("resize", new NullCommand()); } // 是否启用 Docker PTY 模式 if (instance.config.processType === "docker") { - instance.setPreset("resize", new DockerResizeCommand()); + instance.setPreset("resize", new NullCommand()); instance.setPreset("start", new DockerStartCommand()); } diff --git a/src/entity/commands/pty/pty_stop.ts b/src/entity/commands/pty/pty_stop.ts new file mode 100644 index 0000000..0b02cd4 --- /dev/null +++ b/src/entity/commands/pty/pty_stop.ts @@ -0,0 +1,53 @@ +/* + Copyright (C) 2022 Suwings + + 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 + + 该程序是免费软件,您可以重新分发和/或修改据 GNU Affero 通用公共许可证的条款, + 由自由软件基金会,许可证的第 3 版,或(由您选择)任何更高版本。 + + 根据 AGPL 与用户协议,您必须保留所有版权声明,如果修改源代码则必须开源修改后的源代码。 + 可以前往 https://mcsmanager.com/ 阅读用户协议,申请闭源开发授权等。 +*/ + +import Instance from "../../instance/instance"; +import InstanceCommand from "../base/command"; +import SendCommand from "../cmd"; + +export default class PtyStopCommand extends InstanceCommand { + constructor() { + super("PtyStopCommand"); + } + + async exec(instance: Instance) { + const stopCommand = instance.config.stopCommand; + if (stopCommand.toLocaleLowerCase() == "^c") return instance.failure(new Error("伪终端无法使用^C命令关闭进程,请重新设置关服命令")); + + if (instance.status() === Instance.STATUS_STOP || !instance.process) return instance.failure(new Error("实例未处于运行中状态,无法进行停止")); + instance.status(Instance.STATUS_STOPPING); + + await instance.exec(new SendCommand(stopCommand)); + + instance.println("INFO", `已执行预设的关闭命令:${stopCommand}\n如果无法关闭实例请前往实例设置更改关闭实例的正确命令,比如 exit,stop,end 等`); + + // 若 10 分钟后实例还处于停止中状态,则恢复状态 + const cacheStartCount = instance.startCount; + setTimeout(() => { + if (instance.status() === Instance.STATUS_STOPPING && instance.startCount === cacheStartCount) { + instance.println("ERROR", "关闭命令已发出但长时间未能关闭实例,可能是实例关闭命令错误或实例进程假死导致,现在将恢复到运行中状态,可使用强制终止指令结束进程。"); + instance.status(Instance.STATUS_RUNNING); + } + }, 1000 * 60 * 10); + + return instance; + } +}